From f4a69e6d35d21cfbfcd121863c456af61be748ac Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Thu, 30 May 2024 11:37:17 -0400 Subject: [PATCH 001/284] add relationships for go binary packages (#2912) Signed-off-by: Alex Goodman --- syft/pkg/cataloger/golang/cataloger.go | 110 ++------------ syft/pkg/cataloger/golang/cataloger_test.go | 86 +++++++++++ syft/pkg/cataloger/golang/parse_go_binary.go | 34 ++++- .../cataloger/golang/parse_go_binary_test.go | 5 +- syft/pkg/cataloger/golang/stdlib_package.go | 100 +++++++++++++ .../cataloger/golang/stdlib_package_test.go | 137 ++++++++++++++++++ .../image-not-a-module/.gitignore | 1 + .../image-not-a-module/Dockerfile | 25 ++++ .../test-fixtures/image-not-a-module/go.mod | 17 +++ .../test-fixtures/image-not-a-module/go.sum | 26 ++++ .../test-fixtures/image-not-a-module/main.go | 19 +++ .../test-fixtures/image-small/.gitignore | 1 + .../test-fixtures/image-small/Dockerfile | 16 ++ .../golang/test-fixtures/image-small/go.mod | 17 +++ .../golang/test-fixtures/image-small/go.sum | 26 ++++ .../golang/test-fixtures/image-small/main.go | 19 +++ .../internal/pkgtest/test_generic_parser.go | 88 +++++++++++ syft/pkg/cataloger/python/cataloger_test.go | 53 ++----- 18 files changed, 627 insertions(+), 153 deletions(-) create mode 100644 syft/pkg/cataloger/golang/stdlib_package.go create mode 100644 syft/pkg/cataloger/golang/stdlib_package_test.go create mode 100644 syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/.gitignore create mode 100644 syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/Dockerfile create mode 100644 syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/go.mod create mode 100644 syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/go.sum create mode 100644 syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/main.go create mode 100644 syft/pkg/cataloger/golang/test-fixtures/image-small/.gitignore create mode 100644 syft/pkg/cataloger/golang/test-fixtures/image-small/Dockerfile create mode 100644 syft/pkg/cataloger/golang/test-fixtures/image-small/go.mod create mode 100644 syft/pkg/cataloger/golang/test-fixtures/image-small/go.sum create mode 100644 syft/pkg/cataloger/golang/test-fixtures/image-small/main.go diff --git a/syft/pkg/cataloger/golang/cataloger.go b/syft/pkg/cataloger/golang/cataloger.go index 985376d6c..6798b15a2 100644 --- a/syft/pkg/cataloger/golang/cataloger.go +++ b/syft/pkg/cataloger/golang/cataloger.go @@ -4,16 +4,9 @@ Package golang provides a concrete Cataloger implementation relating to packages package golang import ( - "context" - "fmt" "regexp" - "strings" - "github.com/anchore/syft/internal" "github.com/anchore/syft/internal/mimetype" - "github.com/anchore/syft/syft/artifact" - "github.com/anchore/syft/syft/cpe" - "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/generic" ) @@ -30,102 +23,17 @@ func NewGoModuleFileCataloger(opts CatalogerConfig) pkg.Cataloger { c := goModCataloger{ licenses: newGoLicenses(modFileCatalogerName, opts), } - return &progressingCataloger{ - cataloger: generic.NewCataloger(modFileCatalogerName). - WithParserByGlobs(c.parseGoModFile, "**/go.mod"), - } + + return generic.NewCataloger(modFileCatalogerName). + WithParserByGlobs(c.parseGoModFile, "**/go.mod") } // NewGoModuleBinaryCataloger returns a new cataloger object that searches within binaries built by the go compiler. func NewGoModuleBinaryCataloger(opts CatalogerConfig) pkg.Cataloger { - return &progressingCataloger{ - cataloger: generic.NewCataloger(binaryCatalogerName). - WithParserByMimeTypes( - newGoBinaryCataloger(opts).parseGoBinary, - mimetype.ExecutableMIMETypeSet.List()..., - ), - } -} - -type progressingCataloger struct { - cataloger *generic.Cataloger -} - -func (p *progressingCataloger) Name() string { - return p.cataloger.Name() -} - -func (p *progressingCataloger) Catalog(ctx context.Context, resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) { - pkgs, relationships, err := p.cataloger.Catalog(ctx, resolver) - goCompilerPkgs := []pkg.Package{} - totalLocations := file.NewLocationSet() - for _, goPkg := range pkgs { - mValue, ok := goPkg.Metadata.(pkg.GolangBinaryBuildinfoEntry) - if !ok { - continue - } - // go binary packages should only contain a single location - for _, location := range goPkg.Locations.ToSlice() { - if !totalLocations.Contains(location) { - stdLibPkg := newGoStdLib(mValue.GoCompiledVersion, goPkg.Locations) - if stdLibPkg != nil { - goCompilerPkgs = append(goCompilerPkgs, *stdLibPkg) - totalLocations.Add(location) - } - } - } - } - pkgs = append(pkgs, goCompilerPkgs...) - return pkgs, relationships, err -} - -func newGoStdLib(version string, location file.LocationSet) *pkg.Package { - stdlibCpe, err := generateStdlibCpe(version) - if err != nil { - return nil - } - goCompilerPkg := &pkg.Package{ - Name: "stdlib", - Version: version, - PURL: packageURL("stdlib", strings.TrimPrefix(version, "go")), - CPEs: []cpe.CPE{stdlibCpe}, - Locations: location, - Licenses: pkg.NewLicenseSet(pkg.NewLicense("BSD-3-Clause")), - Language: pkg.Go, - Type: pkg.GoModulePkg, - Metadata: pkg.GolangBinaryBuildinfoEntry{ - GoCompiledVersion: version, - }, - } - goCompilerPkg.SetID() - - return goCompilerPkg -} - -func generateStdlibCpe(version string) (stdlibCpe cpe.CPE, err error) { - // GoCompiledVersion when pulled from a binary is prefixed by go - version = strings.TrimPrefix(version, "go") - - // we also need to trim starting from the first + to - // correctly extract potential rc candidate information for cpe generation - // ex: 2.0.0-rc.1+build.123 -> 2.0.0-rc.1; if no + is found then + is returned - after, _, found := strings.Cut("+", version) - if found { - version = after - } - - // extracting and - // https://regex101.com/r/985GsI/1 - captureGroups := internal.MatchNamedCaptureGroups(versionCandidateGroups, version) - vr, ok := captureGroups["version"] - if !ok || vr == "" { - return stdlibCpe, fmt.Errorf("could not match candidate version for: %s", version) - } - - cpeString := fmt.Sprintf("cpe:2.3:a:golang:go:%s:-:*:*:*:*:*:*", captureGroups["version"]) - if candidate, ok := captureGroups["candidate"]; ok && candidate != "" { - cpeString = fmt.Sprintf("cpe:2.3:a:golang:go:%s:%s:*:*:*:*:*:*", vr, candidate) - } - - return cpe.New(cpeString, cpe.GeneratedSource) + return generic.NewCataloger(binaryCatalogerName). + WithParserByMimeTypes( + newGoBinaryCataloger(opts).parseGoBinary, + mimetype.ExecutableMIMETypeSet.List()..., + ). + WithProcessors(stdlibProcessor) } diff --git a/syft/pkg/cataloger/golang/cataloger_test.go b/syft/pkg/cataloger/golang/cataloger_test.go index 240944539..ed8296565 100644 --- a/syft/pkg/cataloger/golang/cataloger_test.go +++ b/syft/pkg/cataloger/golang/cataloger_test.go @@ -8,6 +8,92 @@ import ( "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" ) +func Test_PackageCataloger_Binary(t *testing.T) { + + tests := []struct { + name string + fixture string + expectedPkgs []string + expectedRels []string + }{ + { + name: "simple module with dependencies", + fixture: "image-small", + expectedPkgs: []string{ + "anchore.io/not/real @ (devel) (/run-me)", + "github.com/andybalholm/brotli @ v1.0.1 (/run-me)", + "github.com/dsnet/compress @ v0.0.2-0.20210315054119-f66993602bf5 (/run-me)", + "github.com/golang/snappy @ v0.0.2 (/run-me)", + "github.com/klauspost/compress @ v1.11.4 (/run-me)", + "github.com/klauspost/pgzip @ v1.2.5 (/run-me)", + "github.com/mholt/archiver/v3 @ v3.5.1 (/run-me)", + "github.com/nwaples/rardecode @ v1.1.0 (/run-me)", + "github.com/pierrec/lz4/v4 @ v4.1.2 (/run-me)", + "github.com/ulikunitz/xz @ v0.5.9 (/run-me)", + "github.com/xi2/xz @ v0.0.0-20171230120015-48954b6210f8 (/run-me)", + "stdlib @ go1.22.3 (/run-me)", + }, + expectedRels: []string{ + "github.com/andybalholm/brotli @ v1.0.1 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", + "github.com/dsnet/compress @ v0.0.2-0.20210315054119-f66993602bf5 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", + "github.com/golang/snappy @ v0.0.2 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", + "github.com/klauspost/compress @ v1.11.4 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", + "github.com/klauspost/pgzip @ v1.2.5 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", + "github.com/mholt/archiver/v3 @ v3.5.1 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", + "github.com/nwaples/rardecode @ v1.1.0 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", + "github.com/pierrec/lz4/v4 @ v4.1.2 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", + "github.com/ulikunitz/xz @ v0.5.9 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", + "github.com/xi2/xz @ v0.0.0-20171230120015-48954b6210f8 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", + "stdlib @ go1.22.3 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", + }, + }, + { + name: "partially built binary", + // the difference is the build flags used to build the binary... they will not reference the module directly + // see the dockerfile for details + fixture: "image-not-a-module", + expectedPkgs: []string{ + "command-line-arguments @ (devel) (/run-me)", // this is the difference! + "github.com/andybalholm/brotli @ v1.0.1 (/run-me)", + "github.com/dsnet/compress @ v0.0.2-0.20210315054119-f66993602bf5 (/run-me)", + "github.com/golang/snappy @ v0.0.2 (/run-me)", + "github.com/klauspost/compress @ v1.11.4 (/run-me)", + "github.com/klauspost/pgzip @ v1.2.5 (/run-me)", + "github.com/mholt/archiver/v3 @ v3.5.1 (/run-me)", + "github.com/nwaples/rardecode @ v1.1.0 (/run-me)", + "github.com/pierrec/lz4/v4 @ v4.1.2 (/run-me)", + "github.com/ulikunitz/xz @ v0.5.9 (/run-me)", + "github.com/xi2/xz @ v0.0.0-20171230120015-48954b6210f8 (/run-me)", + "stdlib @ go1.22.3 (/run-me)", + }, + expectedRels: []string{ + "github.com/andybalholm/brotli @ v1.0.1 (/run-me) [dependency-of] command-line-arguments @ (devel) (/run-me)", + "github.com/dsnet/compress @ v0.0.2-0.20210315054119-f66993602bf5 (/run-me) [dependency-of] command-line-arguments @ (devel) (/run-me)", + "github.com/golang/snappy @ v0.0.2 (/run-me) [dependency-of] command-line-arguments @ (devel) (/run-me)", + "github.com/klauspost/compress @ v1.11.4 (/run-me) [dependency-of] command-line-arguments @ (devel) (/run-me)", + "github.com/klauspost/pgzip @ v1.2.5 (/run-me) [dependency-of] command-line-arguments @ (devel) (/run-me)", + "github.com/mholt/archiver/v3 @ v3.5.1 (/run-me) [dependency-of] command-line-arguments @ (devel) (/run-me)", + "github.com/nwaples/rardecode @ v1.1.0 (/run-me) [dependency-of] command-line-arguments @ (devel) (/run-me)", + "github.com/pierrec/lz4/v4 @ v4.1.2 (/run-me) [dependency-of] command-line-arguments @ (devel) (/run-me)", + "github.com/ulikunitz/xz @ v0.5.9 (/run-me) [dependency-of] command-line-arguments @ (devel) (/run-me)", + "github.com/xi2/xz @ v0.0.0-20171230120015-48954b6210f8 (/run-me) [dependency-of] command-line-arguments @ (devel) (/run-me)", + "stdlib @ go1.22.3 (/run-me) [dependency-of] command-line-arguments @ (devel) (/run-me)", + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + pkgtest.NewCatalogTester(). + WithImageResolver(t, test.fixture). + ExpectsPackageStrings(test.expectedPkgs). + ExpectsRelationshipStrings(test.expectedRels). + TestCataloger(t, NewGoModuleBinaryCataloger(DefaultCatalogerConfig())) + }) + } + +} + func Test_Mod_Cataloger_Globs(t *testing.T) { tests := []struct { name string diff --git a/syft/pkg/cataloger/golang/parse_go_binary.go b/syft/pkg/cataloger/golang/parse_go_binary.go index a6940dcf6..f3ea97180 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary.go +++ b/syft/pkg/cataloger/golang/parse_go_binary.go @@ -69,17 +69,38 @@ func (c *goBinaryCataloger) parseGoBinary(_ context.Context, resolver file.Resol mods := scanFile(unionReader, reader.RealPath) internal.CloseAndLogError(reader.ReadCloser, reader.RealPath) + var rels []artifact.Relationship for _, mod := range mods { - pkgs = append(pkgs, c.buildGoPkgInfo(resolver, reader.Location, mod, mod.arch, unionReader)...) + var depPkgs []pkg.Package + mainPkg, depPkgs := c.buildGoPkgInfo(resolver, reader.Location, mod, mod.arch, unionReader) + if mainPkg != nil { + rels = createModuleRelationships(*mainPkg, depPkgs) + pkgs = append(pkgs, *mainPkg) + } + pkgs = append(pkgs, depPkgs...) + } + + return pkgs, rels, nil +} + +func createModuleRelationships(main pkg.Package, deps []pkg.Package) []artifact.Relationship { + var relationships []artifact.Relationship + + for _, dep := range deps { + relationships = append(relationships, artifact.Relationship{ + From: dep, + To: main, + Type: artifact.DependencyOfRelationship, + }) } - return pkgs, nil, nil + return relationships } -func (c *goBinaryCataloger) buildGoPkgInfo(resolver file.Resolver, location file.Location, mod *extendedBuildInfo, arch string, reader io.ReadSeekCloser) []pkg.Package { +func (c *goBinaryCataloger) buildGoPkgInfo(resolver file.Resolver, location file.Location, mod *extendedBuildInfo, arch string, reader io.ReadSeekCloser) (*pkg.Package, []pkg.Package) { var pkgs []pkg.Package if mod == nil { - return pkgs + return nil, pkgs } var empty debug.Module @@ -110,13 +131,12 @@ func (c *goBinaryCataloger) buildGoPkgInfo(resolver file.Resolver, location file } if mod.Main == empty { - return pkgs + return nil, pkgs } main := c.makeGoMainPackage(resolver, mod, arch, location, reader) - pkgs = append(pkgs, main) - return pkgs + return &main, pkgs } func (c *goBinaryCataloger) makeGoMainPackage(resolver file.Resolver, mod *extendedBuildInfo, arch string, location file.Location, reader io.ReadSeekCloser) pkg.Package { diff --git a/syft/pkg/cataloger/golang/parse_go_binary_test.go b/syft/pkg/cataloger/golang/parse_go_binary_test.go index 67a61bdfc..29de14f35 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary_test.go +++ b/syft/pkg/cataloger/golang/parse_go_binary_test.go @@ -964,7 +964,10 @@ func TestBuildGoPkgInfo(t *testing.T) { c := newGoBinaryCataloger(DefaultCatalogerConfig()) reader, err := unionreader.GetUnionReader(io.NopCloser(strings.NewReader(test.binaryContent))) require.NoError(t, err) - pkgs := c.buildGoPkgInfo(fileresolver.Empty{}, location, test.mod, test.mod.arch, reader) + mainPkg, pkgs := c.buildGoPkgInfo(fileresolver.Empty{}, location, test.mod, test.mod.arch, reader) + if mainPkg != nil { + pkgs = append(pkgs, *mainPkg) + } require.Len(t, pkgs, len(test.expected)) for i, p := range pkgs { pkgtest.AssertPackagesEqual(t, test.expected[i], p) diff --git a/syft/pkg/cataloger/golang/stdlib_package.go b/syft/pkg/cataloger/golang/stdlib_package.go new file mode 100644 index 000000000..19d37fe89 --- /dev/null +++ b/syft/pkg/cataloger/golang/stdlib_package.go @@ -0,0 +1,100 @@ +package golang + +import ( + "fmt" + "strings" + + "github.com/anchore/syft/internal" + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/cpe" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" +) + +func stdlibProcessor(pkgs []pkg.Package, relationships []artifact.Relationship, err error) ([]pkg.Package, []artifact.Relationship, error) { + compilerPkgs, newRelationships := stdlibPackageAndRelationships(pkgs) + return append(pkgs, compilerPkgs...), append(relationships, newRelationships...), err +} + +func stdlibPackageAndRelationships(pkgs []pkg.Package) ([]pkg.Package, []artifact.Relationship) { + var goCompilerPkgs []pkg.Package + var relationships []artifact.Relationship + totalLocations := file.NewLocationSet() + for _, goPkg := range pkgs { + mValue, ok := goPkg.Metadata.(pkg.GolangBinaryBuildinfoEntry) + if !ok { + continue + } + + // go binary packages should only contain a single location + for _, location := range goPkg.Locations.ToSlice() { + if totalLocations.Contains(location) { + continue + } + + stdLibPkg := newGoStdLib(mValue.GoCompiledVersion, goPkg.Locations) + if stdLibPkg != nil { + goCompilerPkgs = append(goCompilerPkgs, *stdLibPkg) + totalLocations.Add(location) + } + + relationships = append(relationships, artifact.Relationship{ + From: *stdLibPkg, + To: goPkg, + Type: artifact.DependencyOfRelationship, + }) + } + } + return goCompilerPkgs, relationships +} + +func newGoStdLib(version string, location file.LocationSet) *pkg.Package { + stdlibCpe, err := generateStdlibCpe(version) + if err != nil { + return nil + } + goCompilerPkg := &pkg.Package{ + Name: "stdlib", + Version: version, + PURL: packageURL("stdlib", strings.TrimPrefix(version, "go")), + CPEs: []cpe.CPE{stdlibCpe}, + Locations: location, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("BSD-3-Clause")), + Language: pkg.Go, + Type: pkg.GoModulePkg, + Metadata: pkg.GolangBinaryBuildinfoEntry{ + GoCompiledVersion: version, + }, + } + goCompilerPkg.SetID() + + return goCompilerPkg +} + +func generateStdlibCpe(version string) (stdlibCpe cpe.CPE, err error) { + // GoCompiledVersion when pulled from a binary is prefixed by go + version = strings.TrimPrefix(version, "go") + + // we also need to trim starting from the first + to + // correctly extract potential rc candidate information for cpe generation + // ex: 2.0.0-rc.1+build.123 -> 2.0.0-rc.1; if no + is found then + is returned + after, _, found := strings.Cut("+", version) + if found { + version = after + } + + // extracting and + // https://regex101.com/r/985GsI/1 + captureGroups := internal.MatchNamedCaptureGroups(versionCandidateGroups, version) + vr, ok := captureGroups["version"] + if !ok || vr == "" { + return stdlibCpe, fmt.Errorf("could not match candidate version for: %s", version) + } + + cpeString := fmt.Sprintf("cpe:2.3:a:golang:go:%s:-:*:*:*:*:*:*", captureGroups["version"]) + if candidate, ok := captureGroups["candidate"]; ok && candidate != "" { + cpeString = fmt.Sprintf("cpe:2.3:a:golang:go:%s:%s:*:*:*:*:*:*", vr, candidate) + } + + return cpe.New(cpeString, cpe.GeneratedSource) +} diff --git a/syft/pkg/cataloger/golang/stdlib_package_test.go b/syft/pkg/cataloger/golang/stdlib_package_test.go new file mode 100644 index 000000000..44653f82b --- /dev/null +++ b/syft/pkg/cataloger/golang/stdlib_package_test.go @@ -0,0 +1,137 @@ +package golang + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/anchore/syft/internal/cmptest" + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/cpe" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" +) + +func Test_stdlibPackageAndRelationships(t *testing.T) { + + tests := []struct { + name string + pkgs []pkg.Package + wantPkgs int + wantRels int + }{ + { + name: "no packages", + }, + { + name: "ignore non-go-binary packages", + pkgs: []pkg.Package{ + { + Name: "not-go", + Version: "1.0.0", + Metadata: pkg.GolangModuleEntry{}, + }, + }, + wantPkgs: 0, + wantRels: 0, + }, + { + name: "with go-binary packages -- missing location", + pkgs: []pkg.Package{ + { + Name: "github.com/something/go", + Version: "1.0.0", + Metadata: pkg.GolangBinaryBuildinfoEntry{ + GoCompiledVersion: "go1.22.2", + MainModule: "github.com/something/go", + }, + }, + }, + wantPkgs: 0, + wantRels: 0, + }, + { + name: "with go-binary packages", + pkgs: []pkg.Package{ + { + Name: "github.com/something/go", + Version: "1.0.0", + Locations: file.NewLocationSet(file.NewLocation("/bin/my-app")), + Metadata: pkg.GolangBinaryBuildinfoEntry{ + GoCompiledVersion: "go1.22.2", + MainModule: "github.com/something/go", + }, + }, + }, + wantPkgs: 1, + wantRels: 1, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotPkgs, gotRels := stdlibPackageAndRelationships(tt.pkgs) + assert.Len(t, gotPkgs, tt.wantPkgs) + assert.Len(t, gotRels, tt.wantRels) + }) + } +} + +func Test_stdlibPackageAndRelationships_values(t *testing.T) { + loc := file.NewLocation("/bin/my-app") + locSet := file.NewLocationSet(loc) + p := pkg.Package{ + Name: "github.com/something/go", + Version: "1.0.0", + Locations: locSet, + Metadata: pkg.GolangBinaryBuildinfoEntry{ + GoCompiledVersion: "go1.22.2", + MainModule: "github.com/something/go", + }, + } + p.SetID() + + expectedPkg := pkg.Package{ + Name: "stdlib", + Version: "go1.22.2", + PURL: packageURL("stdlib", "1.22.2"), + Language: pkg.Go, + Type: pkg.GoModulePkg, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("BSD-3-Clause")), + CPEs: []cpe.CPE{ + { + Attributes: cpe.MustAttributes("cpe:2.3:a:golang:go:1.22.2:-:*:*:*:*:*:*"), + Source: "syft-generated", + }, + }, + Locations: locSet, + Metadata: pkg.GolangBinaryBuildinfoEntry{ + GoCompiledVersion: "go1.22.2", + }, + } + + expectedPkg.SetID() + + expectedRel := artifact.Relationship{ + From: expectedPkg, + To: p, + Type: artifact.DependencyOfRelationship, + } + + gotPkgs, gotRels := stdlibPackageAndRelationships([]pkg.Package{p}) + require.Len(t, gotPkgs, 1) + + gotPkg := gotPkgs[0] + if d := cmp.Diff(expectedPkg, gotPkg, cmptest.DefaultCommonOptions()...); d != "" { + t.Errorf("unexpected package (-want +got): %s", d) + } + + require.Len(t, gotRels, 1) + gotRel := gotRels[0] + + if d := cmp.Diff(expectedRel, gotRel, cmptest.DefaultCommonOptions()...); d != "" { + t.Errorf("unexpected relationship (-want +got): %s", d) + } + +} diff --git a/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/.gitignore b/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/.gitignore new file mode 100644 index 000000000..0158cf7ba --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/.gitignore @@ -0,0 +1 @@ +/run-me \ No newline at end of file diff --git a/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/Dockerfile b/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/Dockerfile new file mode 100644 index 000000000..38b26c721 --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/Dockerfile @@ -0,0 +1,25 @@ +FROM --platform=linux/amd64 golang:1.22 AS builder + +RUN mkdir /app +WORKDIR /app + +COPY go.mod go.sum ./ +RUN go mod download +COPY main.go main.go + +# building with "." vs "main.go" is a difference in the buildinfo section +# specifically with main.go the buildinfo section will contain the following: +# +# path command-line-arguments +# +# instead of +# +# mod anchore.io/not/real +# +RUN CGO_ENABLED=0 GOOS=linux go build -o run-me main.go + + +FROM scratch + +COPY --from=builder /app/run-me /run-me +ENTRYPOINT ["/run-me"] \ No newline at end of file diff --git a/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/go.mod b/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/go.mod new file mode 100644 index 000000000..83808c4b9 --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/go.mod @@ -0,0 +1,17 @@ +module anchore.io/not/real + +go 1.22.1 + +require github.com/mholt/archiver/v3 v3.5.1 + +require ( + github.com/andybalholm/brotli v1.0.1 // indirect + github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect + github.com/golang/snappy v0.0.2 // indirect + github.com/klauspost/compress v1.11.4 // indirect + github.com/klauspost/pgzip v1.2.5 // indirect + github.com/nwaples/rardecode v1.1.0 // indirect + github.com/pierrec/lz4/v4 v4.1.2 // indirect + github.com/ulikunitz/xz v0.5.9 // indirect + github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect +) diff --git a/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/go.sum b/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/go.sum new file mode 100644 index 000000000..f132d7176 --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/go.sum @@ -0,0 +1,26 @@ +github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc= +github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY= +github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= +github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= +github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw= +github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.11.4 h1:kz40R/YWls3iqT9zX9AHN3WoVsrAWVyui5sxuLqiXqU= +github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= +github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= +github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= +github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ= +github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM= +github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I= +github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/main.go b/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/main.go new file mode 100644 index 000000000..ffff01e89 --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/main.go @@ -0,0 +1,19 @@ +package main + +import "github.com/mholt/archiver/v3" + +func main() { + + z := archiver.Zip{ + MkdirAll: true, + SelectiveCompression: true, + ContinueOnError: false, + OverwriteExisting: false, + ImplicitTopLevelFolder: false, + } + + err := z.Archive([]string{"main.go"}, "test.zip") + if err != nil { + panic(err) + } +} diff --git a/syft/pkg/cataloger/golang/test-fixtures/image-small/.gitignore b/syft/pkg/cataloger/golang/test-fixtures/image-small/.gitignore new file mode 100644 index 000000000..0158cf7ba --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/image-small/.gitignore @@ -0,0 +1 @@ +/run-me \ No newline at end of file diff --git a/syft/pkg/cataloger/golang/test-fixtures/image-small/Dockerfile b/syft/pkg/cataloger/golang/test-fixtures/image-small/Dockerfile new file mode 100644 index 000000000..cf78c974b --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/image-small/Dockerfile @@ -0,0 +1,16 @@ +FROM --platform=linux/amd64 golang:1.22 AS builder + +RUN mkdir /app +WORKDIR /app + +COPY go.mod go.sum ./ +RUN go mod download +COPY main.go main.go + +RUN CGO_ENABLED=0 GOOS=linux go build -o run-me . + + +FROM scratch + +COPY --from=builder /app/run-me /run-me +ENTRYPOINT ["/run-me"] \ No newline at end of file diff --git a/syft/pkg/cataloger/golang/test-fixtures/image-small/go.mod b/syft/pkg/cataloger/golang/test-fixtures/image-small/go.mod new file mode 100644 index 000000000..83808c4b9 --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/image-small/go.mod @@ -0,0 +1,17 @@ +module anchore.io/not/real + +go 1.22.1 + +require github.com/mholt/archiver/v3 v3.5.1 + +require ( + github.com/andybalholm/brotli v1.0.1 // indirect + github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect + github.com/golang/snappy v0.0.2 // indirect + github.com/klauspost/compress v1.11.4 // indirect + github.com/klauspost/pgzip v1.2.5 // indirect + github.com/nwaples/rardecode v1.1.0 // indirect + github.com/pierrec/lz4/v4 v4.1.2 // indirect + github.com/ulikunitz/xz v0.5.9 // indirect + github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect +) diff --git a/syft/pkg/cataloger/golang/test-fixtures/image-small/go.sum b/syft/pkg/cataloger/golang/test-fixtures/image-small/go.sum new file mode 100644 index 000000000..f132d7176 --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/image-small/go.sum @@ -0,0 +1,26 @@ +github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc= +github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY= +github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= +github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= +github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw= +github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.11.4 h1:kz40R/YWls3iqT9zX9AHN3WoVsrAWVyui5sxuLqiXqU= +github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= +github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= +github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= +github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ= +github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM= +github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I= +github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/syft/pkg/cataloger/golang/test-fixtures/image-small/main.go b/syft/pkg/cataloger/golang/test-fixtures/image-small/main.go new file mode 100644 index 000000000..ffff01e89 --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/image-small/main.go @@ -0,0 +1,19 @@ +package main + +import "github.com/mholt/archiver/v3" + +func main() { + + z := archiver.Zip{ + MkdirAll: true, + SelectiveCompression: true, + ContinueOnError: false, + OverwriteExisting: false, + ImplicitTopLevelFolder: false, + } + + err := z.Archive([]string{"main.go"}, "test.zip") + if err != nil { + panic(err) + } +} diff --git a/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go b/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go index 4384e3e21..a3cf11dec 100644 --- a/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go +++ b/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go @@ -2,8 +2,10 @@ package pkgtest import ( "context" + "fmt" "io" "os" + "sort" "strings" "testing" @@ -40,6 +42,7 @@ type CatalogTester struct { compareOptions []cmp.Option locationComparer cmptest.LocationComparer licenseComparer cmptest.LicenseComparer + packageStringer func(pkg.Package) string customAssertions []func(t *testing.T, pkgs []pkg.Package, relationships []artifact.Relationship) } @@ -48,6 +51,7 @@ func NewCatalogTester() *CatalogTester { wantErr: require.NoError, locationComparer: cmptest.DefaultLocationComparer, licenseComparer: cmptest.DefaultLicenseComparer, + packageStringer: stringPackage, ignoreUnfulfilledPathResponses: map[string][]string{ "FilesByPath": { // most catalogers search for a linux release, which will not be fulfilled in testing @@ -187,6 +191,23 @@ func (p *CatalogTester) Expects(pkgs []pkg.Package, relationships []artifact.Rel return p } +func (p *CatalogTester) WithPackageStringer(fn func(pkg.Package) string) *CatalogTester { + p.packageStringer = fn + return p +} + +func (p *CatalogTester) ExpectsPackageStrings(expected []string) *CatalogTester { + return p.ExpectsAssertion(func(t *testing.T, pkgs []pkg.Package, _ []artifact.Relationship) { + diffPackages(t, expected, pkgs, p.packageStringer) + }) +} + +func (p *CatalogTester) ExpectsRelationshipStrings(expected []string) *CatalogTester { + return p.ExpectsAssertion(func(t *testing.T, pkgs []pkg.Package, relationships []artifact.Relationship) { + diffRelationships(t, expected, relationships, pkgs, p.packageStringer) + }) +} + func (p *CatalogTester) ExpectsResolverPathResponses(locations []string) *CatalogTester { p.expectedPathResponses = locations return p @@ -347,3 +368,70 @@ func AssertPackagesEqual(t *testing.T, a, b pkg.Package) { t.Errorf("unexpected packages from parsing (-expected +actual)\n%s", diff) } } + +func diffPackages(t *testing.T, expected []string, actual []pkg.Package, pkgStringer func(pkg.Package) string) { + t.Helper() + sort.Strings(expected) + if d := cmp.Diff(expected, stringPackages(actual, pkgStringer)); d != "" { + t.Errorf("unexpected package strings (-want, +got): %s", d) + } +} + +func diffRelationships(t *testing.T, expected []string, actual []artifact.Relationship, pkgs []pkg.Package, pkgStringer func(pkg.Package) string) { + t.Helper() + pkgsByID := make(map[artifact.ID]pkg.Package) + for _, p := range pkgs { + pkgsByID[p.ID()] = p + } + sort.Strings(expected) + if d := cmp.Diff(expected, stringRelationships(actual, pkgsByID, pkgStringer)); d != "" { + t.Errorf("unexpected relationship strings (-want, +got): %s", d) + } +} + +func stringRelationships(relationships []artifact.Relationship, nameLookup map[artifact.ID]pkg.Package, pkgStringer func(pkg.Package) string) []string { + var result []string + for _, r := range relationships { + var fromName, toName string + { + fromPkg, ok := nameLookup[r.From.ID()] + if !ok { + fromName = string(r.From.ID()) + } else { + fromName = pkgStringer(fromPkg) + } + } + + { + toPkg, ok := nameLookup[r.To.ID()] + if !ok { + toName = string(r.To.ID()) + } else { + toName = pkgStringer(toPkg) + } + } + + result = append(result, fromName+" ["+string(r.Type)+"] "+toName) + } + sort.Strings(result) + return result +} + +func stringPackages(pkgs []pkg.Package, pkgStringer func(pkg.Package) string) []string { + var result []string + for _, p := range pkgs { + result = append(result, pkgStringer(p)) + } + sort.Strings(result) + return result +} + +func stringPackage(p pkg.Package) string { + locs := p.Locations.ToSlice() + var loc string + if len(locs) > 0 { + loc = p.Locations.ToSlice()[0].RealPath + } + + return fmt.Sprintf("%s @ %s (%s)", p.Name, p.Version, loc) +} diff --git a/syft/pkg/cataloger/python/cataloger_test.go b/syft/pkg/cataloger/python/cataloger_test.go index ed12fbb7f..df30307ca 100644 --- a/syft/pkg/cataloger/python/cataloger_test.go +++ b/syft/pkg/cataloger/python/cataloger_test.go @@ -4,13 +4,10 @@ import ( "context" "fmt" "path" - "sort" "testing" - "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/require" - "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" @@ -482,52 +479,20 @@ func Test_PackageCataloger_SitePackageRelationships(t *testing.T) { t.Run(test.name, func(t *testing.T) { pkgtest.NewCatalogTester(). WithImageResolver(t, test.fixture). - ExpectsAssertion(func(t *testing.T, pkgs []pkg.Package, relationships []artifact.Relationship) { - diffRelationships(t, test.expectedRelationships, relationships, pkgs) - }). + WithPackageStringer(stringPackage). + ExpectsRelationshipStrings(test.expectedRelationships). TestCataloger(t, NewInstalledPackageCataloger()) }) } } -func diffRelationships(t *testing.T, expected []string, actual []artifact.Relationship, pkgs []pkg.Package) { - pkgsByID := make(map[artifact.ID]pkg.Package) - for _, p := range pkgs { - pkgsByID[p.ID()] = p +func stringPackage(p pkg.Package) string { + locs := p.Locations.ToSlice() + var loc string + if len(locs) > 0 { + // we want the location of the site-packages, not the metadata file + loc = path.Dir(path.Dir(p.Locations.ToSlice()[0].RealPath)) } - sort.Strings(expected) - if d := cmp.Diff(expected, stringRelationships(actual, pkgsByID)); d != "" { - t.Errorf("unexpected relationships (-want, +got): %s", d) - } -} - -func stringRelationships(relationships []artifact.Relationship, nameLookup map[artifact.ID]pkg.Package) []string { - var result []string - for _, r := range relationships { - var fromName, toName string - { - fromPkg, ok := nameLookup[r.From.ID()] - if !ok { - fromName = string(r.From.ID()) - } else { - loc := path.Dir(path.Dir(fromPkg.Locations.ToSlice()[0].RealPath)) - fromName = fmt.Sprintf("%s @ %s (%s)", fromPkg.Name, fromPkg.Version, loc) - } - } - - { - toPkg, ok := nameLookup[r.To.ID()] - if !ok { - toName = string(r.To.ID()) - } else { - loc := path.Dir(path.Dir(toPkg.Locations.ToSlice()[0].RealPath)) - toName = fmt.Sprintf("%s @ %s (%s)", toPkg.Name, toPkg.Version, loc) - } - } - - result = append(result, fromName+" ["+string(r.Type)+"] "+toName) - } - sort.Strings(result) - return result + return fmt.Sprintf("%s @ %s (%s)", p.Name, p.Version, loc) } From 5cf8cc9bc347ce409bc9619fdae0e680f6d7aa27 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Thu, 30 May 2024 11:37:31 -0400 Subject: [PATCH 002/284] chore(deps): update tools to latest versions (#2913) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index 020c72611..cdedcf26b 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -111,7 +111,7 @@ tools: # used for triggering a release - name: gh version: - want: v2.49.2 + want: v2.50.0 method: github-release with: repo: cli/cli From eeb4193d4ac5aaed480fea3f82e653bbbb03b790 Mon Sep 17 00:00:00 2001 From: Laurent Goderre Date: Thu, 30 May 2024 11:38:45 -0400 Subject: [PATCH 003/284] Lua: Add support for more advanced syntax (#2908) * Add lua/rocksepc support for variables substitution * Lua: Skip expressions in rockspec packages * Lua: Add support for concatenation of string and variables * Lua: Skip expressions in local * Lua: Skip build sections in Rockspec files * Lua: skip function blocks in Rockspec * Lua: Add support for multi variable per line --------- Signed-off-by: Laurent Goderre --- syft/pkg/cataloger/lua/parse_rockspec_test.go | 21 ++ syft/pkg/cataloger/lua/rockspec_parser.go | 293 ++++++++++++++++-- .../pkg/cataloger/lua/rockspec_parser_test.go | 95 ++++++ .../rockspec/luasyslog-2.0.1-1.rockspec | 36 +++ 4 files changed, 422 insertions(+), 23 deletions(-) create mode 100644 syft/pkg/cataloger/lua/test-fixtures/rockspec/luasyslog-2.0.1-1.rockspec diff --git a/syft/pkg/cataloger/lua/parse_rockspec_test.go b/syft/pkg/cataloger/lua/parse_rockspec_test.go index f40bfdd7c..f429a9dc7 100644 --- a/syft/pkg/cataloger/lua/parse_rockspec_test.go +++ b/syft/pkg/cataloger/lua/parse_rockspec_test.go @@ -76,6 +76,27 @@ func TestParseRockspec(t *testing.T) { }, }, }, + { + Fixture: "test-fixtures/rockspec/luasyslog-2.0.1-1.rockspec", + ExpectedPkg: pkg.Package{ + Name: "luasyslog", + Version: "2.0.1-1", + PURL: "pkg:luarocks/luasyslog@2.0.1-1", + Type: pkg.LuaRocksPkg, + Language: pkg.Lua, + Licenses: pkg.NewLicenseSet( + pkg.NewLicenseFromLocations("MIT/X11", file.NewLocation("test-fixtures/rockspec/luasyslog-2.0.1-1.rockspec")), + ), + Metadata: pkg.LuaRocksPackage{ + Name: "luasyslog", + Version: "2.0.1-1", + License: "MIT/X11", + Homepage: "https://github.com/lunarmodules/luasyslog", + Description: "Syslog logging for Lua", + URL: "git://github.com/lunarmodules/luasyslog.git", + }, + }, + }, } for _, test := range tests { diff --git a/syft/pkg/cataloger/lua/rockspec_parser.go b/syft/pkg/cataloger/lua/rockspec_parser.go index 68c178fe7..e8d5f5c42 100644 --- a/syft/pkg/cataloger/lua/rockspec_parser.go +++ b/syft/pkg/cataloger/lua/rockspec_parser.go @@ -45,7 +45,8 @@ func parseRockspecData(reader io.Reader) (rockspec, error) { } i := 0 - blocks, err := parseRockspecBlock(data, &i) + locals := make(map[string]string) + blocks, err := parseRockspecBlock(data, &i, locals) if err != nil { return noReturn, err @@ -56,9 +57,9 @@ func parseRockspecData(reader io.Reader) (rockspec, error) { }, nil } -func parseRockspecBlock(data []byte, i *int) ([]rockspecNode, error) { +func parseRockspecBlock(data []byte, i *int, locals map[string]string) ([]rockspecNode, error) { var out []rockspecNode - var iterator func(data []byte, i *int) (*rockspecNode, error) + var iterator func(data []byte, i *int, locals map[string]string) (*rockspecNode, error) parsing.SkipWhitespace(data, i) @@ -67,6 +68,14 @@ func parseRockspecBlock(data []byte, i *int) ([]rockspecNode, error) { } c := data[*i] + + // Block starting with a comment + if c == '-' { + parseComment(data, i) + parsing.SkipWhitespace(data, i) + c = data[*i] + } + switch { case c == '"' || c == '\'': iterator = parseRockspecListItem @@ -77,7 +86,7 @@ func parseRockspecBlock(data []byte, i *int) ([]rockspecNode, error) { } for *i < len(data) { - item, err := iterator(data, i) + item, err := iterator(data, i, locals) if err != nil { return nil, fmt.Errorf("%w\n%s", err, parsing.PrintError(data, *i)) } @@ -99,7 +108,7 @@ func parseRockspecBlock(data []byte, i *int) ([]rockspecNode, error) { } //nolint:funlen, gocognit -func parseRockspecNode(data []byte, i *int) (*rockspecNode, error) { +func parseRockspecNode(data []byte, i *int, locals map[string]string) (*rockspecNode, error) { parsing.SkipWhitespace(data, i) if *i >= len(data) { @@ -136,7 +145,7 @@ func parseRockspecNode(data []byte, i *int) (*rockspecNode, error) { return nil, fmt.Errorf("invalid literal character: %s", string(c)) } - key, err := parseRockspecLiteral(data, i) + key, err := parseRockspecLiteral(data, i, locals) if err != nil { return nil, err } @@ -147,6 +156,16 @@ func parseRockspecNode(data []byte, i *int) (*rockspecNode, error) { return nil, fmt.Errorf("unexpected end of node at %d", *i) } + if key == "local" { + err := parseLocal(data, i, locals) + if err != nil { + return nil, err + } + return &rockspecNode{ + key: ",", + }, nil + } + c = data[*i] if c != '=' { return nil, fmt.Errorf("unexpected character: %s", string(c)) @@ -159,6 +178,14 @@ func parseRockspecNode(data []byte, i *int) (*rockspecNode, error) { return nil, fmt.Errorf("unexpected end of node at %d", *i) } + if key == "build" { + skipBuildNode(data, i) + + return &rockspecNode{ + key: ",", + }, nil + } + c = data[*i] switch c { @@ -180,7 +207,7 @@ func parseRockspecNode(data []byte, i *int) (*rockspecNode, error) { parsing.SkipWhitespace(data, i) - obj, err := parseRockspecBlock(data, i) + obj, err := parseRockspecBlock(data, i, locals) if err != nil { return nil, err @@ -190,16 +217,10 @@ func parseRockspecNode(data []byte, i *int) (*rockspecNode, error) { return &rockspecNode{ key, value, }, nil - case '"', '\'': - str, err := parseRockspecString(data, i) - - if err != nil { - return nil, err - } - value := str.value - + case '(': + skipExpression(data, i) return &rockspecNode{ - key, value, + key: ",", }, nil case '[': offset := *i + 1 @@ -214,7 +235,7 @@ func parseRockspecNode(data []byte, i *int) (*rockspecNode, error) { *i++ - str, err := parseRockspecString(data, i) + str, err := parseRockspecString(data, i, locals) if err != nil { return nil, err @@ -234,10 +255,18 @@ func parseRockspecNode(data []byte, i *int) (*rockspecNode, error) { }, nil } - return nil, nil + value, err := parseRockspecValue(data, i, locals, "") + + if err != nil { + return nil, err + } + + return &rockspecNode{ + key, value, + }, nil } -func parseRockspecListItem(data []byte, i *int) (*rockspecNode, error) { +func parseRockspecListItem(data []byte, i *int, locals map[string]string) (*rockspecNode, error) { parsing.SkipWhitespace(data, i) if *i >= len(data) { @@ -269,14 +298,70 @@ func parseRockspecListItem(data []byte, i *int) (*rockspecNode, error) { }, nil } - str, err := parseRockspecString(data, i) + str, err := parseRockspecString(data, i, locals) if err != nil { return nil, err } return str, nil } -func parseRockspecLiteral(data []byte, i *int) (string, error) { +func parseRockspecValue(data []byte, i *int, locals map[string]string, initialValue string) (string, error) { + c := data[*i] + + var value string + + switch c { + case '"', '\'': + str, err := parseRockspecString(data, i, locals) + + if err != nil { + return "", err + } + value = str.value.(string) + default: + local, err := parseRockspecLiteral(data, i, locals) + + if err != nil { + return "", err + } + + l, ok := locals[local] + + if !ok { + return "", fmt.Errorf("unknown local: %s", local) + } + + value = l + } + + value = fmt.Sprintf("%s%s", initialValue, value) + + skipWhitespaceNoNewLine(data, i) + + if len(data) > *i+2 { + if data[*i] == '.' && data[*i+1] == '.' { + *i += 2 + + skipWhitespaceNoNewLine(data, i) + + if *i >= len(data) { + return "", fmt.Errorf("unexpected end of expression at %d", *i) + } + + v, err := parseRockspecValue(data, i, locals, value) + + if err != nil { + return "", err + } + + value = v + } + } + + return value, nil +} + +func parseRockspecLiteral(data []byte, i *int, locals map[string]string) (string, error) { var buf bytes.Buffer out: for *i < len(data) { @@ -284,7 +369,7 @@ out: switch { case c == '[': *i++ - nested, err := parseRockspecString(data, i) + nested, err := parseRockspecString(data, i, locals) if err != nil { return "", err } @@ -303,7 +388,7 @@ out: return buf.String(), nil } -func parseRockspecString(data []byte, i *int) (*rockspecNode, error) { +func parseRockspecString(data []byte, i *int, _ map[string]string) (*rockspecNode, error) { delim := data[*i] var endDelim byte switch delim { @@ -344,9 +429,171 @@ func parseComment(data []byte, i *int) { } } +//nolint:funlen +func parseLocal(data []byte, i *int, locals map[string]string) error { + keys := []string{} + values := []string{} + +keys: + for { + parsing.SkipWhitespace(data, i) + + key, err := parseRockspecLiteral(data, i, locals) + if err != nil { + return err + } + + if key == "function" { + err := skipFunction(data, i) + if err != nil { + return err + } + return nil + } + + keys = append(keys, key) + + parsing.SkipWhitespace(data, i) + + c := data[*i] + + switch c { + case ',': + *i++ + continue + case '=': + *i++ + break keys + default: + return fmt.Errorf("unexpected character: %s", string(c)) + } + } + +values: + for { + skipWhitespaceNoNewLine(data, i) + + c := data[*i] + + switch c { + case '"', '\'': + value, err := parseRockspecString(data, i, locals) + + if err != nil { + return err + } + values = append(values, value.value.(string)) + default: + ref, err := parseRockspecLiteral(data, i, locals) + if err != nil { + return err + } + + // Skip if it's an expression + skipWhitespaceNoNewLine(data, i) + c := data[*i] + + var value string + + if c != '\n' && c != '\r' { + skipExpression(data, i) + value = "" + } else { + value = locals[ref] + } + + values = append(values, value) + } + + skipWhitespaceNoNewLine(data, i) + + c = data[*i] + + switch c { + case ',': + *i++ + continue + case '\n', '\r': + parsing.SkipWhitespace(data, i) + break values + } + } + + if len(keys) != len(values) { + return fmt.Errorf("expected %d values got %d", len(keys), len(values)) + } + + for i := 0; i < len(keys); i++ { + locals[keys[i]] = values[i] + } + + return nil +} + +func skipBuildNode(data []byte, i *int) { + bracesCount := 0 + + for *i < len(data) { + c := data[*i] + + switch c { + case '{': + bracesCount++ + case '}': + bracesCount-- + } + + if bracesCount == 0 { + return + } + + *i++ + } +} + +func skipFunction(data []byte, i *int) error { + blocks := 1 + + for *i < len(data)-5 { + if parsing.IsWhitespace(data[*i]) { + switch { + case string(data[*i+1:*i+3]) == "if" && parsing.IsWhitespace(data[*i+3]): + blocks++ + *i += 3 + case string(data[*i+1:*i+4]) == "end" && parsing.IsWhitespace(data[*i+4]): + blocks-- + *i += 4 + + if blocks == 0 { + return nil + } + default: + *i++ + } + } else { + *i++ + } + } + + return fmt.Errorf("unterminated function at %d", *i) +} + +func skipExpression(data []byte, i *int) { + parseComment(data, i) +} + +func skipWhitespaceNoNewLine(data []byte, i *int) { + for *i < len(data) && (data[*i] == ' ' || data[*i] == '\t') { + *i++ + } +} + func isLiteral(c byte) bool { if c == '[' || c == ']' { return true } + if c == '.' { + return false + } return parsing.IsLiteral(c) } diff --git a/syft/pkg/cataloger/lua/rockspec_parser_test.go b/syft/pkg/cataloger/lua/rockspec_parser_test.go index dfd5264a4..63cbde502 100644 --- a/syft/pkg/cataloger/lua/rockspec_parser_test.go +++ b/syft/pkg/cataloger/lua/rockspec_parser_test.go @@ -60,6 +60,49 @@ multiline = [[ a multiline string ]] +`, + }, + { + name: "variables", + content: ` +local foo = "bar" +local baz = foo + +hello = baz +`, + }, + { + name: "multiple variables in one line", + content: ` +local foo, bar = "hello", "world" +baz = foo +test = bar +`, + }, + { + name: "skip expressions", + content: ` +test = (hello == "world") and "foo" or "bar" +baz = "123" +`, + }, + { + name: "skip expressions in locals", + content: ` +local var1 = "foo" +local var2 = var1 == "foo" and "true" or ("false") + +foo = "bar" +`, + }, + { + name: "concatenation", + content: ` +local foo = "bar" +local baz = "123" +hello = "world"..baz +baz = foo.." "..baz +test = foo .. baz `, }, { @@ -80,6 +123,17 @@ object = { hello = "world" -- this is another comment } +`, + }, + { + name: "content start with comment", + content: ` +foo = "bar" +-- this is a comment +object = { + -- this is another comment + hello = "world" +} `, }, { @@ -91,6 +145,33 @@ list = { -- "baz" "hello" } +`, + }, + { + name: "skip build section", + content: ` +foo = "bar" +build = { + a = { + { + content + } + } +} +bar = "baz" +`, + }, + { + name: "skip functions", + content: ` +local function test + if foo == bar then + if hello = world then + blah + end + end +end +test = "blah" `, }, { @@ -153,6 +234,20 @@ list = { "bar", -`, }, + { + name: "undefined local", + wantErr: require.Error, + content: ` +test = hello + `, + }, + { + name: "unterminated concatenation", + wantErr: require.Error, + content: ` +local foo = "123" +hello = foo.. `, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { diff --git a/syft/pkg/cataloger/lua/test-fixtures/rockspec/luasyslog-2.0.1-1.rockspec b/syft/pkg/cataloger/lua/test-fixtures/rockspec/luasyslog-2.0.1-1.rockspec new file mode 100644 index 000000000..13b1276b8 --- /dev/null +++ b/syft/pkg/cataloger/lua/test-fixtures/rockspec/luasyslog-2.0.1-1.rockspec @@ -0,0 +1,36 @@ +local package_name = "luasyslog" +local package_version = "2.0.1" +local rockspec_revision = "1" +local github_account_name = "lunarmodules" +local github_repo_name = package_name + + +package = package_name +version = package_version.."-"..rockspec_revision +source = { + url = "git://github.com/"..github_account_name.."/"..github_repo_name..".git", + branch = (package_version == "dev") and "main" or nil, + tag = (package_version ~= "dev") and package_version or nil, +} +description = { + summary = "Syslog logging for Lua", + detailed = [[ + Addon for LuaLogging to log to the system log on unix systems. + Can also be used without LuaLogging to directly write to syslog. + ]], + license = "MIT/X11", + homepage = "https://github.com/"..github_account_name.."/"..github_repo_name, +} +dependencies = { + "lua >= 5.1", + "lualogging >= 1.4.0, < 2.0.0", +} +build = { + type = "builtin", + modules = { + lsyslog = { + sources = "lsyslog.c", + }, + ["logging.syslog"] = "syslog.lua", + } +} From aafa161ff683a9ac050e30a45f0baef076bb39b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 May 2024 10:20:00 -0400 Subject: [PATCH 004/284] chore(deps): bump github.com/charmbracelet/bubbletea (#2917) Bumps [github.com/charmbracelet/bubbletea](https://github.com/charmbracelet/bubbletea) from 0.26.3 to 0.26.4. - [Release notes](https://github.com/charmbracelet/bubbletea/releases) - [Commits](https://github.com/charmbracelet/bubbletea/compare/v0.26.3...v0.26.4) --- updated-dependencies: - dependency-name: github.com/charmbracelet/bubbletea dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 0c9f7dddd..ffcfc9e07 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 github.com/bmatcuk/doublestar/v4 v4.6.1 github.com/charmbracelet/bubbles v0.18.0 - github.com/charmbracelet/bubbletea v0.26.3 + github.com/charmbracelet/bubbletea v0.26.4 github.com/charmbracelet/lipgloss v0.11.0 github.com/dave/jennifer v1.7.0 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da @@ -106,7 +106,7 @@ require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/becheran/wildmatch-go v1.0.0 // indirect github.com/charmbracelet/harmonica v0.2.0 // indirect - github.com/charmbracelet/x/ansi v0.1.1 // indirect + github.com/charmbracelet/x/ansi v0.1.2 // indirect github.com/charmbracelet/x/input v0.1.0 // indirect github.com/charmbracelet/x/term v0.1.1 // indirect github.com/charmbracelet/x/windows v0.1.0 // indirect diff --git a/go.sum b/go.sum index 39afa2f86..07b94a98c 100644 --- a/go.sum +++ b/go.sum @@ -155,14 +155,14 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0= github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw= -github.com/charmbracelet/bubbletea v0.26.3 h1:iXyGvI+FfOWqkB2V07m1DF3xxQijxjY2j8PqiXYqasg= -github.com/charmbracelet/bubbletea v0.26.3/go.mod h1:bpZHfDHTYJC5g+FBK+ptJRCQotRC+Dhh3AoMxa/2+3Q= +github.com/charmbracelet/bubbletea v0.26.4 h1:2gDkkzLZaTjMl/dQBpNVtnvcCxsh/FCkimep7FC9c40= +github.com/charmbracelet/bubbletea v0.26.4/go.mod h1:P+r+RRA5qtI1DOHNFn0otoNwB4rn+zNAzSj/EXz6xU0= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v0.11.0 h1:UoAcbQ6Qml8hDwSWs0Y1cB5TEQuZkDPH/ZqwWWYTG4g= github.com/charmbracelet/lipgloss v0.11.0/go.mod h1:1UdRTH9gYgpcdNN5oBtjbu/IzNKtzVtb7sqN1t9LNn8= -github.com/charmbracelet/x/ansi v0.1.1 h1:CGAduulr6egay/YVbGc8Hsu8deMg1xZ/bkaXTPi1JDk= -github.com/charmbracelet/x/ansi v0.1.1/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/x/ansi v0.1.2 h1:6+LR39uG8DE6zAmbu023YlqjJHkYXDF1z36ZwzO4xZY= +github.com/charmbracelet/x/ansi v0.1.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/input v0.1.0 h1:TEsGSfZYQyOtp+STIjyBq6tpRaorH0qpwZUj8DavAhQ= github.com/charmbracelet/x/input v0.1.0/go.mod h1:ZZwaBxPF7IG8gWWzPUVqHEtWhc1+HXJPNuerJGRGZ28= github.com/charmbracelet/x/term v0.1.1 h1:3cosVAiPOig+EV4X9U+3LDgtwwAoEzJjNdwbXDjF6yI= From b04bc0fbfe5742a970aa3f06594b1e82c87eb4a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 May 2024 11:17:21 -0400 Subject: [PATCH 005/284] chore(deps): bump github/codeql-action from 3.25.6 to 3.25.7 (#2916) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.6 to 3.25.7. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/9fdb3e49720b44c48891d036bb502feb25684276...f079b8493333aace61c81488f8bd40919487bd9f) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 5b16da69a..4d3d88a3a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@9fdb3e49720b44c48891d036bb502feb25684276 #v3.25.6 + uses: github/codeql-action/init@f079b8493333aace61c81488f8bd40919487bd9f #v3.25.7 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@9fdb3e49720b44c48891d036bb502feb25684276 #v3.25.6 + uses: github/codeql-action/autobuild@f079b8493333aace61c81488f8bd40919487bd9f #v3.25.7 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@9fdb3e49720b44c48891d036bb502feb25684276 #v3.25.6 + uses: github/codeql-action/analyze@f079b8493333aace61c81488f8bd40919487bd9f #v3.25.7 From 24262b9e31ec3f56b4d05d14121a4f08befc1752 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 09:59:33 -0400 Subject: [PATCH 006/284] chore(deps): bump modernc.org/sqlite from 1.29.10 to 1.30.0 (#2921) Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.29.10 to 1.30.0. - [Commits](https://gitlab.com/cznic/sqlite/compare/v1.29.10...v1.30.0) --- updated-dependencies: - dependency-name: modernc.org/sqlite dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index ffcfc9e07..fccab6a05 100644 --- a/go.mod +++ b/go.mod @@ -81,7 +81,7 @@ require ( golang.org/x/mod v0.17.0 golang.org/x/net v0.25.0 gopkg.in/yaml.v3 v3.0.1 - modernc.org/sqlite v1.29.10 + modernc.org/sqlite v1.30.0 ) require google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect @@ -240,7 +240,7 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect - modernc.org/libc v1.49.3 // indirect + modernc.org/libc v1.50.9 // indirect modernc.org/mathutil v1.6.0 // indirect modernc.org/memory v1.8.0 // indirect modernc.org/strutil v1.2.0 // indirect diff --git a/go.sum b/go.sum index 07b94a98c..dbc546f18 100644 --- a/go.sum +++ b/go.sum @@ -1357,18 +1357,18 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -modernc.org/cc/v4 v4.20.0 h1:45Or8mQfbUqJOG9WaxvlFYOAQO0lQ5RvqBcFCXngjxk= -modernc.org/cc/v4 v4.20.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= -modernc.org/ccgo/v4 v4.16.0 h1:ofwORa6vx2FMm0916/CkZjpFPSR70VwTjUCe2Eg5BnA= -modernc.org/ccgo/v4 v4.16.0/go.mod h1:dkNyWIjFrVIZ68DTo36vHK+6/ShBn4ysU61So6PIqCI= +modernc.org/cc/v4 v4.21.2 h1:dycHFB/jDc3IyacKipCNSDrjIC0Lm1hyoWOZTRR20Lk= +modernc.org/cc/v4 v4.21.2/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= +modernc.org/ccgo/v4 v4.17.8 h1:yyWBf2ipA0Y9GGz/MmCmi3EFpKgeS7ICrAFes+suEbs= +modernc.org/ccgo/v4 v4.17.8/go.mod h1:buJnJ6Fn0tyAdP/dqePbrrvLyr6qslFfTbFrCuaYvtA= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= -modernc.org/libc v1.49.3 h1:j2MRCRdwJI2ls/sGbeSk0t2bypOG/uvPZUsGQFDulqg= -modernc.org/libc v1.49.3/go.mod h1:yMZuGkn7pXbKfoT/M35gFJOAEdSKdxL0q64sF7KqCDo= +modernc.org/libc v1.50.9 h1:hIWf1uz55lorXQhfoEoezdUHjxzuO6ceshET/yWjSjk= +modernc.org/libc v1.50.9/go.mod h1:15P6ublJ9FJR8YQCGy8DeQ2Uwur7iW9Hserr/T3OFZE= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= @@ -1377,8 +1377,8 @@ modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= -modernc.org/sqlite v1.29.10 h1:3u93dz83myFnMilBGCOLbr+HjklS6+5rJLx4q86RDAg= -modernc.org/sqlite v1.29.10/go.mod h1:ItX2a1OVGgNsFh6Dv60JQvGfJfTPHPVpV6DF59akYOA= +modernc.org/sqlite v1.30.0 h1:8YhPUs/HTnlEgErn/jSYQTwHN/ex8CjHHjg+K9iG7LM= +modernc.org/sqlite v1.30.0/go.mod h1:cgkTARJ9ugeXSNaLBPK3CqbOe7Ec7ZhWPoMFGldEYEw= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= From 3ac95bfbd0c0e615f405c464492b366fde868b9d Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 10:00:30 -0400 Subject: [PATCH 007/284] chore(deps): update CPE dictionary index (#2919) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: wagoodman <590471+wagoodman@users.noreply.github.com> --- .../internal/cpegenerate/dictionary/data/cpe-index.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index 75fa5285b..5a72a546a 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -10,6 +10,9 @@ "github.com/SimonWaldherr/zplgfa": [ "cpe:2.3:a:simonwaldherr:zplgfa:*:*:*:*:*:go:*:*" ], + "github.com/anchore/stereoscope": [ + "cpe:2.3:a:anchore:stereoscope:*:*:*:*:*:go:*:*" + ], "github.com/apptainer/apptainer": [ "cpe:2.3:a:lfprojects:apptainer:*:*:*:*:*:go:*:*" ], From 29d601d1f1f4b7669aeef707cbf75a4373b58ec8 Mon Sep 17 00:00:00 2001 From: dufucun Date: Mon, 3 Jun 2024 23:10:39 +0900 Subject: [PATCH 008/284] chore: fix some comments (#2920) Signed-off-by: dufucun Co-authored-by: dufucun --- test/install/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/install/Makefile b/test/install/Makefile index d6ec4052d..fd8588418 100644 --- a/test/install/Makefile +++ b/test/install/Makefile @@ -88,7 +88,7 @@ ubuntu-20.04: ## ALPINE ####################################################### -# note: unit tests cannot be run with sh (alpine dosn't have bash by default) +# note: unit tests cannot be run with sh (alpine doesn't have bash by default) .PHONY: acceptance-alpine-3.6 acceptance-alpine-3.6: alpine-3.6 @@ -103,7 +103,7 @@ alpine-3.6: ## BUSYBOX ####################################################### -# note: unit tests cannot be run with sh (busybox dosn't have bash by default) +# note: unit tests cannot be run with sh (busybox doesn't have bash by default) # note: busybox by default will not have cacerts, so you will get TLS warnings (we want to test under these conditions) From 8a7f08e2c8508642c7cc862715cd1bbb0f6e6759 Mon Sep 17 00:00:00 2001 From: Ralph Bean Date: Mon, 3 Jun 2024 10:18:52 -0400 Subject: [PATCH 009/284] Use redhat as namespace for redhat rpms (#2914) The namespace value of `redhat` signifies this as an RPM package produced and distributed by Red Hat. Using "rhel" in the namespace is not correct. Signed-off-by: Ralph Bean --- syft/pkg/cataloger/redhat/package.go | 3 +++ syft/pkg/cataloger/redhat/package_test.go | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/syft/pkg/cataloger/redhat/package.go b/syft/pkg/cataloger/redhat/package.go index 23954991a..8bbcfe9a0 100644 --- a/syft/pkg/cataloger/redhat/package.go +++ b/syft/pkg/cataloger/redhat/package.go @@ -89,6 +89,9 @@ func packageURL(name, arch string, epoch *int, srpm string, version, release str if distro != nil { namespace = distro.ID } + if namespace == "rhel" { + namespace = "redhat" + } qualifiers := map[string]string{} diff --git a/syft/pkg/cataloger/redhat/package_test.go b/syft/pkg/cataloger/redhat/package_test.go index b5459717a..cc24d7d48 100644 --- a/syft/pkg/cataloger/redhat/package_test.go +++ b/syft/pkg/cataloger/redhat/package_test.go @@ -28,7 +28,7 @@ func Test_packageURL(t *testing.T) { Release: "r", Epoch: nil, }, - expected: "pkg:rpm/rhel/p@v-r?distro=rhel-8.4", + expected: "pkg:rpm/redhat/p@v-r?distro=rhel-8.4", }, { name: "with arch and epoch", @@ -67,7 +67,7 @@ func Test_packageURL(t *testing.T) { Release: "r", SourceRpm: "sourcerpm", }, - expected: "pkg:rpm/rhel/p@v-r?upstream=sourcerpm&distro=rhel-8.4", + expected: "pkg:rpm/redhat/p@v-r?upstream=sourcerpm&distro=rhel-8.4", }, } From fe0b78b7fe73b92ad76deed288d3b9b091a14d27 Mon Sep 17 00:00:00 2001 From: William Tang Date: Mon, 3 Jun 2024 22:42:13 +0800 Subject: [PATCH 010/284] fix: close sql driver after testing sqlite availability (#2922) Signed-off-by: William Tang --- syft/pkg/cataloger/redhat/cataloger.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/syft/pkg/cataloger/redhat/cataloger.go b/syft/pkg/cataloger/redhat/cataloger.go index f6c7080ac..addd8aaf2 100644 --- a/syft/pkg/cataloger/redhat/cataloger.go +++ b/syft/pkg/cataloger/redhat/cataloger.go @@ -48,6 +48,10 @@ func NewArchiveCataloger() pkg.Cataloger { } func isSqliteDriverAvailable() bool { - _, err := sql.Open("sqlite", ":memory:") - return err == nil + db, err := sql.Open("sqlite", ":memory:") + if err != nil { + return false + } + _ = db.Close() + return true } From 2f39322f8153650787ca45ebd4ca24d5a5a2b669 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Tue, 4 Jun 2024 13:31:29 -0400 Subject: [PATCH 011/284] use dco tool during gh app outage (#2926) Signed-off-by: Alex Goodman --- .github/workflows/dco.yaml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/dco.yaml diff --git a/.github/workflows/dco.yaml b/.github/workflows/dco.yaml new file mode 100644 index 000000000..9f94b6b77 --- /dev/null +++ b/.github/workflows/dco.yaml @@ -0,0 +1,23 @@ +name: DCO +on: + pull_request: + push: + branches: + - main +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Python 3.x + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Check DCO + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + pip3 install -U dco-check + dco-check --verbose --exclude-pattern 'dependabot\[bot\]@users\.noreply\.github\.com' \ No newline at end of file From cb09dd9e190b1550707f2be6d3f5683330045e39 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Tue, 4 Jun 2024 13:34:22 -0400 Subject: [PATCH 012/284] match existing DCO GH check name Signed-off-by: Alex Goodman --- .github/workflows/dco.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dco.yaml b/.github/workflows/dco.yaml index 9f94b6b77..cf759c79b 100644 --- a/.github/workflows/dco.yaml +++ b/.github/workflows/dco.yaml @@ -5,7 +5,7 @@ on: branches: - main jobs: - check: + DCO: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 From 557ad73ee60b009388a213b38730858da344c25e Mon Sep 17 00:00:00 2001 From: William Murphy Date: Tue, 4 Jun 2024 15:21:45 -0400 Subject: [PATCH 013/284] fix: only skip tmpfs mounts for some paths (#2918) * fix: only skip tmpfs mounts for some paths Signed-off-by: Will Murphy * refactor and add tests Signed-off-by: Alex Goodman * add regression test for archive processing Signed-off-by: Alex Goodman * bump to golang 1.22 Signed-off-by: Alex Goodman * remove rule 1 and add more tests Signed-off-by: Alex Goodman --------- Signed-off-by: Will Murphy Signed-off-by: Alex Goodman Co-authored-by: Alex Goodman --- .github/actions/bootstrap/action.yaml | 2 +- go.mod | 2 +- .../fileresolver/directory_indexer.go | 56 +-- .../fileresolver/directory_indexer_test.go | 143 ------- syft/internal/fileresolver/path_skipper.go | 157 +++++++ .../fileresolver/path_skipper_test.go | 395 ++++++++++++++++++ test/cli/archive_test.go | 60 +++ .../test-fixtures/archive/dist-info/METADATA | 47 +++ .../test-fixtures/archive/dist-info/RECORD | 5 + .../archive/dist-info/top_level.txt | 1 + 10 files changed, 669 insertions(+), 199 deletions(-) create mode 100644 syft/internal/fileresolver/path_skipper.go create mode 100644 syft/internal/fileresolver/path_skipper_test.go create mode 100644 test/cli/archive_test.go create mode 100644 test/cli/test-fixtures/archive/dist-info/METADATA create mode 100644 test/cli/test-fixtures/archive/dist-info/RECORD create mode 100644 test/cli/test-fixtures/archive/dist-info/top_level.txt diff --git a/.github/actions/bootstrap/action.yaml b/.github/actions/bootstrap/action.yaml index d0a5ee678..e351c8392 100644 --- a/.github/actions/bootstrap/action.yaml +++ b/.github/actions/bootstrap/action.yaml @@ -5,7 +5,7 @@ inputs: go-version: description: "Go version to install" required: true - default: "1.21.x" + default: "1.22.x" go-dependencies: description: "Download go dependencies" required: true diff --git a/go.mod b/go.mod index fccab6a05..6a5fbf45f 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/anchore/syft -go 1.21.0 +go 1.22.0 require ( github.com/CycloneDX/cyclonedx-go v0.8.0 diff --git a/syft/internal/fileresolver/directory_indexer.go b/syft/internal/fileresolver/directory_indexer.go index 92495ab77..2d9101999 100644 --- a/syft/internal/fileresolver/directory_indexer.go +++ b/syft/internal/fileresolver/directory_indexer.go @@ -9,13 +9,11 @@ import ( "path/filepath" "strings" - "github.com/moby/sys/mountinfo" "github.com/wagoodman/go-partybus" "github.com/wagoodman/go-progress" "github.com/anchore/stereoscope/pkg/file" "github.com/anchore/stereoscope/pkg/filetree" - "github.com/anchore/syft/internal" "github.com/anchore/syft/internal/bus" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/event" @@ -43,7 +41,8 @@ func newDirectoryIndexer(path, base string, visitors ...PathIndexVisitor) *direc []PathIndexVisitor{ requireFileInfo, disallowByFileType, - newUnixSystemMountFinder().disallowUnixSystemRuntimePath}, + skipPathsByMountTypeAndName(path), + }, visitors..., ), errPaths: make(map[string]error), @@ -450,57 +449,6 @@ func (r *directoryIndexer) disallowRevisitingVisitor(_, path string, _ os.FileIn return nil } -type unixSystemMountFinder struct { - disallowedMountPaths []string -} - -func newUnixSystemMountFinder() unixSystemMountFinder { - infos, err := mountinfo.GetMounts(nil) - if err != nil { - log.WithFields("error", err).Warnf("unable to get system mounts") - return unixSystemMountFinder{} - } - - return unixSystemMountFinder{ - disallowedMountPaths: keepUnixSystemMountPaths(infos), - } -} - -func keepUnixSystemMountPaths(infos []*mountinfo.Info) []string { - var mountPaths []string - for _, info := range infos { - if info == nil { - continue - } - // we're only interested in ignoring the logical filesystems typically found at these mount points: - // - /proc - // - procfs - // - proc - // - /sys - // - sysfs - // - /dev - // - devfs - BSD/darwin flavored systems and old linux systems - // - devtmpfs - driver core maintained /dev tmpfs - // - udev - userspace implementation that replaced devfs - // - tmpfs - used for /dev in special instances (within a container) - - switch info.FSType { - case "proc", "procfs", "sysfs", "devfs", "devtmpfs", "udev", "tmpfs": - log.WithFields("mountpoint", info.Mountpoint).Debug("ignoring system mountpoint") - - mountPaths = append(mountPaths, info.Mountpoint) - } - } - return mountPaths -} - -func (f unixSystemMountFinder) disallowUnixSystemRuntimePath(_, path string, _ os.FileInfo, _ error) error { - if internal.HasAnyOfPrefixes(path, f.disallowedMountPaths...) { - return fs.SkipDir - } - return nil -} - func disallowByFileType(_, _ string, info os.FileInfo, _ error) error { if info == nil { // we can't filter out by filetype for non-existent files diff --git a/syft/internal/fileresolver/directory_indexer_test.go b/syft/internal/fileresolver/directory_indexer_test.go index f30925d00..3b736b667 100644 --- a/syft/internal/fileresolver/directory_indexer_test.go +++ b/syft/internal/fileresolver/directory_indexer_test.go @@ -10,7 +10,6 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/moby/sys/mountinfo" "github.com/scylladb/go-set/strset" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -462,145 +461,3 @@ func relativePath(basePath, givenPath string) string { return relPath } - -func Test_disallowUnixSystemRuntimePath(t *testing.T) { - unixSubject := unixSystemMountFinder{ - // mock out detecting the mount points - disallowedMountPaths: []string{"/proc", "/sys", "/dev"}, - } - - tests := []struct { - name string - path string - base string - expected error - }{ - { - name: "relative path to proc is allowed", - path: "proc/place", - }, - { - name: "relative path within proc is not allowed", - path: "/proc/place", - expected: fs.SkipDir, - }, - { - name: "path exactly to proc is not allowed", - path: "/proc", - expected: fs.SkipDir, - }, - { - name: "similar to proc", - path: "/pro/c", - }, - { - name: "similar to proc", - path: "/pro", - }, - { - name: "dev is not allowed", - path: "/dev", - expected: fs.SkipDir, - }, - { - name: "sys is not allowed", - path: "/sys", - expected: fs.SkipDir, - }, - { - name: "unrelated allowed path", - path: "/something/sys", - }, - { - name: "do not consider base when matching paths (non-matching)", - base: "/a/b/c", - path: "/a/b/c/dev", - }, - { - name: "do not consider base when matching paths (matching)", - base: "/a/b/c", - path: "/dev", - expected: fs.SkipDir, - }, - } - for _, test := range tests { - t.Run(test.path, func(t *testing.T) { - assert.Equal(t, test.expected, unixSubject.disallowUnixSystemRuntimePath(test.base, test.path, nil, nil)) - }) - } -} - -func Test_keepUnixSystemMountPaths(t *testing.T) { - - tests := []struct { - name string - infos []*mountinfo.Info - want []string - }{ - { - name: "all valid filesystems", - infos: []*mountinfo.Info{ - { - Mountpoint: "/etc/hostname", - FSType: "/dev/vda1", - }, - { - Mountpoint: "/sys/fs/cgroup", - FSType: "cgroup", - }, - { - Mountpoint: "/", - FSType: "overlay", - }, - }, - want: nil, - }, - { - name: "no valid filesystems", - infos: []*mountinfo.Info{ - { - Mountpoint: "/proc", - FSType: "proc", - }, - { - Mountpoint: "/proc-2", - FSType: "procfs", - }, - { - Mountpoint: "/sys", - FSType: "sysfs", - }, - { - Mountpoint: "/dev", - FSType: "devfs", - }, - { - Mountpoint: "/dev-u", - FSType: "udev", - }, - { - Mountpoint: "/dev-tmp", - FSType: "devtmpfs", - }, - { - Mountpoint: "/run", - FSType: "tmpfs", - }, - }, - want: []string{ - "/proc", - "/proc-2", - "/sys", - "/dev", - "/dev-u", - "/dev-tmp", - "/run", - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.want, keepUnixSystemMountPaths(tt.infos)) - }) - } -} diff --git a/syft/internal/fileresolver/path_skipper.go b/syft/internal/fileresolver/path_skipper.go new file mode 100644 index 000000000..4ae9bb361 --- /dev/null +++ b/syft/internal/fileresolver/path_skipper.go @@ -0,0 +1,157 @@ +package fileresolver + +import ( + "io/fs" + "os" + "sort" + "strings" + + "github.com/moby/sys/mountinfo" + + "github.com/anchore/syft/internal/log" +) + +type pathSkipper struct { + // scanTarget is the root path that is being scanned (without any base-path logic applied). + scanTarget string + + // ignorableMountTypes is a set of mount types that should be ignored. Optionally a list of paths (the map values) + // can be provided that this mount type should be ignored at. For example in some containers /dev is mounted + // as a tmpfs and should be ignored, but /tmp should not be ignored. An empty list of paths means that paths + // within the mount type should always be ignored. + ignorableMountTypes map[string][]string + + // current mount paths for the current system + mounts []*mountinfo.Info + mountsByType map[string][]*mountinfo.Info +} + +// skipPathsByMountTypeAndName accepts the root path and returns a PathIndexVisitor that will skip paths based +// the filesystem type, the mountpoint, and configured blocklist paths for each filesystem type. +// This will help syft dodge filesystem topologies that have the potential to make the search space much bigger in +// areas known to not traditionally contain files of interest (installed software). It is meant to allow scanning +// "/" on a unix host to succeed, while also not causing any files in a narrow directory scan to be skipped unnecessarily. +func skipPathsByMountTypeAndName(root string) PathIndexVisitor { + infos, err := mountinfo.GetMounts(nil) + if err != nil { + log.WithFields("error", err).Warnf("unable to get system mounts") + return func(_ string, _ string, _ os.FileInfo, _ error) error { + return nil + } + } + + return newPathSkipperFromMounts(root, infos).pathIndexVisitor +} + +func newPathSkipperFromMounts(root string, infos []*mountinfo.Info) pathSkipper { + // we're only interested in ignoring the logical filesystems typically found at these mount points: + // - /proc + // - procfs + // - proc + // - /sys + // - sysfs + // - /dev + // - devfs - BSD/darwin flavored systems and old linux systems + // - devtmpfs - driver core maintained /dev tmpfs + // - udev - userspace implementation that replaced devfs + // - tmpfs - used for /dev in special instances (within a container) + ignorableMountTypes := map[string][]string{ + "proc": nil, + "procfs": nil, + "sysfs": nil, + "devfs": nil, + "devtmpfs": nil, + "udev": nil, + // note: there should be no order required (e.g. search /sys/thing before /sys) since that would imply that + // we could not ignore a nested path within a path that would be ignored anyway. + "tmpfs": {"/run", "/dev", "/var/run", "/var/lock", "/sys"}, + } + + // The longest path is the most specific path, e.g. + // if / is mounted as tmpfs, but /home/syft/permanent is mounted as ext4, + // then the mount type for /home/syft/permanent/foo is ext4, and the mount info + // stating that /home/syft/permanent is ext4 has the longer mount point. + sort.Slice(infos, func(i, j int) bool { + return len(infos[i].Mountpoint) > len(infos[j].Mountpoint) + }) + + mountsByType := make(map[string][]*mountinfo.Info) + + for _, mi := range infos { + mountsByType[mi.FSType] = append(mountsByType[mi.FSType], mi) + } + + return pathSkipper{ + scanTarget: root, + ignorableMountTypes: ignorableMountTypes, + mounts: infos, + mountsByType: mountsByType, + } +} + +func (ps pathSkipper) pathIndexVisitor(_ string, givenPath string, _ os.FileInfo, _ error) error { + for _, mi := range ps.mounts { + conditionalPaths, ignorable := ps.ignorableMountTypes[mi.FSType] + + if len(conditionalPaths) == 0 { + // Rule 1: ignore any path within a mount point that is of the given filesystem type unconditionally + if !containsPath(givenPath, mi.Mountpoint) { + continue + } + + if !ignorable { + // we've matched on the most specific path at this point, which means we should stop searching + // mount points for this path + break + } + + log.WithFields( + "path", givenPath, + "mountpoint", mi.Mountpoint, + "fs", mi.FSType, + ).Debug("ignoring path based on mountpoint filesystem type") + + return fs.SkipDir + } + + // Rule 2: ignore any path within a mount point that is of the given filesystem type, only if + // the path is on a known blocklist of paths for that filesystem type. + // For example: /dev can be mounted as a tmpfs, which should always be skipped. + for _, conditionalPath := range conditionalPaths { + if !containsPath(givenPath, conditionalPath) { + continue + } + + log.WithFields( + "path", givenPath, + "mountpoint", mi.Mountpoint, + "fs", mi.FSType, + "condition", conditionalPath, + ).Debug("ignoring path based on mountpoint filesystem type") + + return fs.SkipDir + } + } + + return nil +} + +func containsPath(p1, p2 string) bool { + p1Clean := simpleClean(p1) + p2Clean := simpleClean(p2) + if p1Clean == p2Clean { + return true + } + return strings.HasPrefix(p1Clean, p2Clean+"/") +} + +func simpleClean(p string) string { + p = strings.TrimSpace(p) + if p == "" { + return "." + } + if p == "/" { + return "/" + } + return strings.TrimSuffix(p, "/") +} diff --git a/syft/internal/fileresolver/path_skipper_test.go b/syft/internal/fileresolver/path_skipper_test.go new file mode 100644 index 000000000..d4e501eca --- /dev/null +++ b/syft/internal/fileresolver/path_skipper_test.go @@ -0,0 +1,395 @@ +package fileresolver + +import ( + "io/fs" + "testing" + + "github.com/moby/sys/mountinfo" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_newPathSkipper(t *testing.T) { + type expect struct { + path string + wantErr assert.ErrorAssertionFunc + } + unixSubject := []*mountinfo.Info{ + { + Mountpoint: "/proc", + FSType: "procfs", + }, + { + Mountpoint: "/sys", + FSType: "sysfs", + }, + { + Mountpoint: "/dev", + FSType: "devfs", + }, + { + Mountpoint: "/", + FSType: "/dev/disk3s1s1", + }, + { + Mountpoint: "/dev/shm", + FSType: "shm", + }, + { + Mountpoint: "/tmp", + FSType: "tmpfs", + }, + } + + tests := []struct { + name string + root string + base string + mounts []*mountinfo.Info + want []expect + }{ + { + name: "happy path", + root: "/somewhere", + mounts: []*mountinfo.Info{ + { + Mountpoint: "/home/somewhere/else", + FSType: "/dev/disk3s6", + }, + { + Mountpoint: "/somewhere", + FSType: "/dev/disk3s7", + }, + }, + want: []expect{ + { + // within a known mountpoint with valid type (1) + path: "/somewhere/dev", + }, + { + // is a known mountpoint with valid type + path: "/somewhere", + }, + { + // within a known mountpoint with valid type (2) + path: "/home/somewhere/else/too", + }, + { + // outside of any known mountpoint should not be an error + path: "/bogus", + }, + }, + }, + { + name: "ignore paths within a scan target", + root: "/somewhere", + mounts: []*mountinfo.Info{ + { + Mountpoint: "/somewhere/doesnt/matter/proc", + FSType: "procfs", + }, + { + Mountpoint: "/somewhere", + FSType: "/dev/disk3s7", + }, + }, + want: []expect{ + { + // within a known mountpoint with valid type (1) + path: "/somewhere/dev", + }, + { + // is a known mountpoint with valid type + path: "/somewhere", + }, + { + // mountpoint that should be ignored + path: "/somewhere/doesnt/matter/proc", + wantErr: assertSkipErr(), + }, + { + // within a mountpoint that should be ignored + path: "/somewhere/doesnt/matter/proc", + wantErr: assertSkipErr(), + }, + }, + }, + { + name: "nested mountpoints behave correctly", + root: "/somewhere", + mounts: []*mountinfo.Info{ + { + Mountpoint: "/somewhere/dev", + FSType: "devfs", + }, + { + Mountpoint: "/somewhere/dev/includeme", + FSType: "/dev/disk3s7", + }, + }, + want: []expect{ + { + // is a known mountpoint with valid type + path: "/somewhere/dev", + wantErr: assertSkipErr(), + }, + { + // is a known mountpoint with valid type + path: "/somewhere/dev/includeme", + }, + { + // within a known mountpoint with valid type + path: "/somewhere/dev/includeme/too!", + }, + }, + }, + { + name: "keep some tmpfs mounts conditionally", + root: "/", + mounts: []*mountinfo.Info{ + { + Mountpoint: "/run/somewhere", + FSType: "tmpfs", + }, + { + Mountpoint: "/run/terrafirma", + FSType: "/dev/disk3s8", + }, + { + Mountpoint: "/tmp", + FSType: "tmpfs", + }, + { + Mountpoint: "/else/othertmp", + FSType: "tmpfs", + }, + { + Mountpoint: "/else/othertmp/includeme", + FSType: "/dev/disk3s7", + }, + }, + want: []expect{ + { + // since /run is explicitly ignored, this should be skipped + path: "/run/somewhere/else", + wantErr: assertSkipErr(), + }, + { + path: "/run/terrafirma", + }, + { + path: "/run/terrafirma/nested", + }, + { + path: "/tmp", + }, + { + path: "/else/othertmp/includeme", + }, + { + path: "/else/othertmp/includeme/nested", + }, + { + // no mount path, so we should include it + path: "/somewhere/dev/includeme", + }, + { + // keep additional tmpfs mounts that are not explicitly ignored + path: "/else/othertmp", + }, + }, + }, + { + name: "ignore known trixy tmpfs paths", + root: "/", + mounts: []*mountinfo.Info{ + { + Mountpoint: "/", + FSType: "/dev/disk3s7", + }, + { + Mountpoint: "/dev", + FSType: "tmpfs", + }, + { + Mountpoint: "/run", + FSType: "tmpfs", + }, + { + Mountpoint: "/var/run", + FSType: "tmpfs", + }, + { + Mountpoint: "/var/lock", + FSType: "tmpfs", + }, + { + Mountpoint: "/sys", + FSType: "tmpfs", + }, + { + Mountpoint: "/tmp", + FSType: "tmpfs", + }, + }, + want: []expect{ + { + path: "/dev", + wantErr: assertSkipErr(), + }, + { + path: "/run", + wantErr: assertSkipErr(), + }, + { + path: "/var/run", + wantErr: assertSkipErr(), + }, + { + path: "/var/lock", + wantErr: assertSkipErr(), + }, + { + path: "/sys", + wantErr: assertSkipErr(), + }, + // show that we honor ignoring nested paths + { + path: "/sys/nested", + wantErr: assertSkipErr(), + }, + // show that paths outside of the known mountpoints are not skipped + { + path: "/stuff", + }, + // show that we allow other tmpfs paths that are not on the blocklist + { + path: "/tmp/allowed", + }, + // show sibling paths with same prefix (e.g. /sys vs /system) to that of not allowed paths are not skipped + { + path: "/system", + }, + }, + }, + { + name: "test unix paths", + mounts: unixSubject, + root: "/", + want: []expect{ + { + // relative path to proc is allowed + path: "proc/place", + }, + { + // relative path within proc is not allowed + path: "/proc/place", + wantErr: assertSkipErr(), + }, + { + // path exactly to proc is not allowed + path: "/proc", + wantErr: assertSkipErr(), + }, + { + // similar to proc + path: "/pro/c", + }, + { + // similar to proc + path: "/pro", + }, + { + // dev is not allowed + path: "/dev", + wantErr: assertSkipErr(), + }, + { + // sys is not allowed + path: "/sys", + wantErr: assertSkipErr(), + }, + }, + }, + { + name: "test unix paths with base", + mounts: unixSubject, + root: "/", + base: "/a/b/c", + want: []expect{ + { + // do not consider base when matching paths (non-matching) + path: "/a/b/c/dev", + }, + { + // do not consider base when matching paths (matching) + path: "/dev", + wantErr: assertSkipErr(), + }, + }, + }, + { + name: "mimic nixos setup", + root: "/", + mounts: []*mountinfo.Info{ + { + Mountpoint: "/", + FSType: "tmpfs", // this is an odd setup, but valid + }, + { + Mountpoint: "/home", + FSType: "/dev/disk3s7", + }, + }, + want: []expect{ + { + path: "/home/somewhere", + }, + { + path: "/home", + }, + { + path: "/somewhere", + }, + { + // still not allowed... + path: "/run", + wantErr: assertSkipErr(), + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.base == "" { + tt.base = tt.root + } + + require.NotEmpty(t, tt.want) + ps := newPathSkipperFromMounts(tt.root, tt.mounts) + + for _, exp := range tt.want { + t.Run(exp.path, func(t *testing.T) { + + got := ps.pathIndexVisitor(tt.base, exp.path, nil, nil) + if exp.wantErr == nil { + assert.NoError(t, got) + return + } + exp.wantErr(t, got) + + }) + } + }) + } +} + +func assertSkipErr() assert.ErrorAssertionFunc { + return assertErrorIs(fs.SkipDir) +} + +func assertErrorIs(want error) assert.ErrorAssertionFunc { + return func(t assert.TestingT, got error, msgAndArgs ...interface{}) bool { + return assert.ErrorIs(t, got, want, msgAndArgs...) + } +} diff --git a/test/cli/archive_test.go b/test/cli/archive_test.go new file mode 100644 index 000000000..a35b4ead2 --- /dev/null +++ b/test/cli/archive_test.go @@ -0,0 +1,60 @@ +package cli + +import ( + "archive/tar" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestArchiveScan(t *testing.T) { + tests := []struct { + name string + args []string + archiveFixture string + env map[string]string + assertions []traitAssertion + }{ + { + name: "scan an archive within the temp dir", + args: []string{ + "scan", + "-o", + "json", + "file:" + createArchive(t, "test-fixtures/archive", t.TempDir()), + }, + assertions: []traitAssertion{ + assertSuccessfulReturnCode, + assertJsonReport, + assertPackageCount(1), + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + cmd, stdout, stderr := runSyft(t, test.env, test.args...) + for _, traitAssertionFn := range test.assertions { + traitAssertionFn(t, stdout, stderr, cmd.ProcessState.ExitCode()) + } + logOutputOnFailure(t, cmd, stdout, stderr) + }) + } +} + +func createArchive(t *testing.T, path string, destDir string) string { + // create a tarball of the test fixtures (not by shelling out) + archivePath := filepath.Join(destDir, "test.tar") + + fh, err := os.Create(archivePath) + require.NoError(t, err) + defer fh.Close() + + writer := tar.NewWriter(fh) + require.NoError(t, writer.AddFS(os.DirFS(path))) + require.NoError(t, writer.Close()) + + return archivePath +} diff --git a/test/cli/test-fixtures/archive/dist-info/METADATA b/test/cli/test-fixtures/archive/dist-info/METADATA new file mode 100644 index 000000000..924780dfd --- /dev/null +++ b/test/cli/test-fixtures/archive/dist-info/METADATA @@ -0,0 +1,47 @@ +Metadata-Version: 2.1 +Name: Pygments +Version: 2.6.1 +Summary: Pygments is a syntax highlighting package written in Python. +Home-page: https://pygments.org/ +Author: Georg Brandl +Author-email: georg@python.org +License: BSD License +Keywords: syntax highlighting +Platform: any +Classifier: License :: OSI Approved :: BSD License +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: End Users/Desktop +Classifier: Intended Audience :: System Administrators +Classifier: Development Status :: 6 - Mature +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Operating System :: OS Independent +Classifier: Topic :: Text Processing :: Filters +Classifier: Topic :: Utilities +Requires-Python: >=3.5 + + +Pygments +~~~~~~~~ + +Pygments is a syntax highlighting package written in Python. + +It is a generic syntax highlighter suitable for use in code hosting, forums, +wikis or other applications that need to prettify source code. Highlights +are: + +* a wide range of over 500 languages and other text formats is supported +* special attention is paid to details, increasing quality by a fair amount +* support for new languages and formats are added easily +* a number of output formats, presently HTML, LaTeX, RTF, SVG, all image formats that PIL supports and ANSI sequences +* it is usable as a command-line tool and as a library + +:copyright: Copyright 2006-2019 by the Pygments team, see AUTHORS. +:license: BSD, see LICENSE for details. + diff --git a/test/cli/test-fixtures/archive/dist-info/RECORD b/test/cli/test-fixtures/archive/dist-info/RECORD new file mode 100644 index 000000000..af233f390 --- /dev/null +++ b/test/cli/test-fixtures/archive/dist-info/RECORD @@ -0,0 +1,5 @@ +../../../bin/pygmentize,sha256=dDhv_U2jiCpmFQwIRHpFRLAHUO4R1jIJPEvT_QYTFp8,220 +Pygments-2.6.1.dist-info/AUTHORS,sha256=PVpa2_Oku6BGuiUvutvuPnWGpzxqFy2I8-NIrqCvqUY,8449 +Pygments-2.6.1.dist-info/RECORD,, +pygments/__pycache__/__init__.cpython-38.pyc,, +pygments/util.py,sha256=586xXHiJGGZxqk5PMBu3vBhE68DLuAe5MBARWrSPGxA,10778 \ No newline at end of file diff --git a/test/cli/test-fixtures/archive/dist-info/top_level.txt b/test/cli/test-fixtures/archive/dist-info/top_level.txt new file mode 100644 index 000000000..1e09fdb90 --- /dev/null +++ b/test/cli/test-fixtures/archive/dist-info/top_level.txt @@ -0,0 +1 @@ +top-level-pkg \ No newline at end of file From 4bdbd1aa2ad1d821e26408b34e96f444dd2828be Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Tue, 4 Jun 2024 15:22:49 -0400 Subject: [PATCH 014/284] remove unused test fixtures and empty dirs (#2924) Signed-off-by: Alex Goodman --- test/cli/test-fixtures/image-secrets-dir/Dockerfile | 2 -- test/cli/test-fixtures/image-secrets-dir/api-key.txt | 1 - test/cli/test-fixtures/image-secrets/Dockerfile | 2 -- test/cli/test-fixtures/image-secrets/api-key.txt | 1 - 4 files changed, 6 deletions(-) delete mode 100644 test/cli/test-fixtures/image-secrets-dir/Dockerfile delete mode 100644 test/cli/test-fixtures/image-secrets-dir/api-key.txt delete mode 100644 test/cli/test-fixtures/image-secrets/Dockerfile delete mode 100644 test/cli/test-fixtures/image-secrets/api-key.txt diff --git a/test/cli/test-fixtures/image-secrets-dir/Dockerfile b/test/cli/test-fixtures/image-secrets-dir/Dockerfile deleted file mode 100644 index 28a283a0b..000000000 --- a/test/cli/test-fixtures/image-secrets-dir/Dockerfile +++ /dev/null @@ -1,2 +0,0 @@ -FROM scratch -ADD api-key.txt . \ No newline at end of file diff --git a/test/cli/test-fixtures/image-secrets-dir/api-key.txt b/test/cli/test-fixtures/image-secrets-dir/api-key.txt deleted file mode 100644 index 6cbbd99e3..000000000 --- a/test/cli/test-fixtures/image-secrets-dir/api-key.txt +++ /dev/null @@ -1 +0,0 @@ -some_ApI-kEy = "12345A7a901b345678901234567890123456789012345678901234567890" diff --git a/test/cli/test-fixtures/image-secrets/Dockerfile b/test/cli/test-fixtures/image-secrets/Dockerfile deleted file mode 100644 index 28a283a0b..000000000 --- a/test/cli/test-fixtures/image-secrets/Dockerfile +++ /dev/null @@ -1,2 +0,0 @@ -FROM scratch -ADD api-key.txt . \ No newline at end of file diff --git a/test/cli/test-fixtures/image-secrets/api-key.txt b/test/cli/test-fixtures/image-secrets/api-key.txt deleted file mode 100644 index 6cbbd99e3..000000000 --- a/test/cli/test-fixtures/image-secrets/api-key.txt +++ /dev/null @@ -1 +0,0 @@ -some_ApI-kEy = "12345A7a901b345678901234567890123456789012345678901234567890" From 3472b48177fa19aaec5072a14396b37d3d56b580 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Tue, 4 Jun 2024 16:00:05 -0400 Subject: [PATCH 015/284] Add relationships for python poetry packages (#2906) * [wip] add initial poetry.lock relationship support Signed-off-by: Alex Goodman * provide generic set for basic types Signed-off-by: Alex Goodman * dependency resolver should allow for conditional deps Signed-off-by: Alex Goodman * add tests for poetry lock relationship additions Signed-off-by: Alex Goodman * update schema with python poetry dependency refs Signed-off-by: Alex Goodman * dep specification data structure should not be recursive in nature Signed-off-by: Alex Goodman --------- Signed-off-by: Alex Goodman --- internal/constants.go | 2 +- internal/set.go | 68 + internal/set_test.go | 146 + internal/stringset.go | 61 - schema/json/schema-16.0.13.json | 2525 +++++++++++++++++ schema/json/schema-latest.json | 63 +- syft/pkg/cataloger/alpine/dependency.go | 6 +- syft/pkg/cataloger/alpine/dependency_test.go | 18 +- syft/pkg/cataloger/arch/dependency.go | 6 +- syft/pkg/cataloger/arch/dependency_test.go | 18 +- syft/pkg/cataloger/debian/dependency.go | 6 +- syft/pkg/cataloger/debian/dependency_test.go | 18 +- .../cataloger/internal/dependency/resolver.go | 78 +- .../internal/dependency/resolver_test.go | 40 +- syft/pkg/cataloger/python/cataloger_test.go | 195 ++ syft/pkg/cataloger/python/dependency.go | 88 +- syft/pkg/cataloger/python/dependency_test.go | 274 ++ .../pkg/cataloger/python/parse_poetry_lock.go | 137 +- .../python/parse_poetry_lock_test.go | 27 +- .../conflicting-with-extras/poetry.lock | 444 +++ .../conflicting-with-extras/pyproject.toml | 17 + .../poetry/{ => dev-deps}/poetry.lock | 0 .../poetry/multiple-extras/poetry.lock | 373 +++ .../poetry/multiple-extras/pyproject.toml | 14 + .../poetry/nested-extras/poetry.lock | 1114 ++++++++ .../poetry/nested-extras/pyproject.toml | 14 + .../poetry/simple-deps/poetry.lock | 166 ++ .../poetry/simple-deps/pyproject.toml | 14 + syft/pkg/cataloger/redhat/dependency.go | 6 +- syft/pkg/cataloger/redhat/dependency_test.go | 18 +- syft/pkg/python.go | 17 +- 31 files changed, 5817 insertions(+), 156 deletions(-) create mode 100644 internal/set.go create mode 100644 internal/set_test.go delete mode 100644 internal/stringset.go create mode 100644 schema/json/schema-16.0.13.json create mode 100644 syft/pkg/cataloger/python/test-fixtures/poetry/conflicting-with-extras/poetry.lock create mode 100644 syft/pkg/cataloger/python/test-fixtures/poetry/conflicting-with-extras/pyproject.toml rename syft/pkg/cataloger/python/test-fixtures/poetry/{ => dev-deps}/poetry.lock (100%) create mode 100644 syft/pkg/cataloger/python/test-fixtures/poetry/multiple-extras/poetry.lock create mode 100644 syft/pkg/cataloger/python/test-fixtures/poetry/multiple-extras/pyproject.toml create mode 100644 syft/pkg/cataloger/python/test-fixtures/poetry/nested-extras/poetry.lock create mode 100644 syft/pkg/cataloger/python/test-fixtures/poetry/nested-extras/pyproject.toml create mode 100644 syft/pkg/cataloger/python/test-fixtures/poetry/simple-deps/poetry.lock create mode 100644 syft/pkg/cataloger/python/test-fixtures/poetry/simple-deps/pyproject.toml diff --git a/internal/constants.go b/internal/constants.go index f53b47ce7..37079fd78 100644 --- a/internal/constants.go +++ b/internal/constants.go @@ -3,5 +3,5 @@ package internal const ( // JSONSchemaVersion is the current schema version output by the JSON encoder // This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment. - JSONSchemaVersion = "16.0.12" + JSONSchemaVersion = "16.0.13" ) diff --git a/internal/set.go b/internal/set.go new file mode 100644 index 000000000..2d15bee92 --- /dev/null +++ b/internal/set.go @@ -0,0 +1,68 @@ +package internal + +import ( + "fmt" + "sort" +) + +// Set represents a generic set type. +type Set[T comparable] map[T]struct{} + +// NewSet creates a new empty Set. +func NewSet[T comparable](start ...T) Set[T] { + ret := make(Set[T]) + for _, v := range start { + ret.Add(v) + } + return ret +} + +// Add adds elements to the set. +func (s Set[T]) Add(elements ...T) { + for _, e := range elements { + s[e] = struct{}{} + } +} + +// Remove removes an element from the set. +func (s Set[T]) Remove(element T) { + delete(s, element) +} + +// Contains checks if an element is in the set. +func (s Set[T]) Contains(element T) bool { + _, ok := s[element] + return ok +} + +// ToSlice returns a sorted slice of elements in the set. +func (s Set[T]) ToSlice() []T { + ret := make([]T, len(s)) + idx := 0 + for v := range s { + ret[idx] = v + idx++ + } + sort.Slice(ret, func(i, j int) bool { + return fmt.Sprintf("%v", ret[i]) < fmt.Sprintf("%v", ret[j]) + }) + return ret +} + +// Equals checks if two sets are equal. +func (s Set[T]) Equals(o Set[T]) bool { + if len(s) != len(o) { + return false + } + for k := range s { + if !o.Contains(k) { + return false + } + } + return true +} + +// Empty checks if the set is empty. +func (s Set[T]) Empty() bool { + return len(s) == 0 +} diff --git a/internal/set_test.go b/internal/set_test.go new file mode 100644 index 000000000..d92107f76 --- /dev/null +++ b/internal/set_test.go @@ -0,0 +1,146 @@ +package internal + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNewSet(t *testing.T) { + tests := []struct { + name string + start []int + result Set[int] + }{ + {"empty set", []int{}, NewSet[int]()}, + {"non-empty set", []int{1, 2, 3}, NewSet(1, 2, 3)}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := NewSet(tt.start...) + require.Equal(t, tt.result, s) + }) + } +} + +func TestAdd(t *testing.T) { + tests := []struct { + name string + input []int + add []int + result Set[int] + }{ + {"add to empty set", []int{}, []int{1, 2, 3}, NewSet(1, 2, 3)}, + {"add to non-empty set", []int{1}, []int{2, 3}, NewSet(1, 2, 3)}, + {"add existing elements", []int{1, 2}, []int{2, 3}, NewSet(1, 2, 3)}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := NewSet(tt.input...) + s.Add(tt.add...) + assert.Equal(t, tt.result, s) + }) + } +} + +func TestRemove(t *testing.T) { + tests := []struct { + name string + input []int + remove int + result Set[int] + }{ + {"remove from non-empty set", []int{1, 2, 3}, 2, NewSet(1, 3)}, + {"remove non-existent element", []int{1, 2}, 3, NewSet(1, 2)}, + {"remove from single-element set", []int{1}, 1, NewSet[int]()}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := NewSet(tt.input...) + s.Remove(tt.remove) + assert.Equal(t, tt.result, s) + }) + } +} + +func TestContains(t *testing.T) { + tests := []struct { + name string + input []int + contains int + result bool + }{ + {"element in set", []int{1, 2, 3}, 2, true}, + {"element not in set", []int{1, 2}, 3, false}, + {"empty set", []int{}, 1, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := NewSet(tt.input...) + assert.Equal(t, tt.result, s.Contains(tt.contains)) + }) + } +} + +func TestToSlice(t *testing.T) { + tests := []struct { + name string + input []int + result []int + }{ + {"non-empty set", []int{3, 1, 2}, []int{1, 2, 3}}, + {"empty set", []int{}, []int{}}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := NewSet(tt.input...) + assert.Equal(t, tt.result, s.ToSlice()) + }) + } +} + +func TestEquals(t *testing.T) { + tests := []struct { + name string + set1 []int + set2 []int + result bool + }{ + {"equal sets", []int{1, 2, 3}, []int{3, 2, 1}, true}, + {"different sets", []int{1, 2}, []int{2, 3}, false}, + {"empty sets", []int{}, []int{}, true}, + {"one empty set", []int{1, 2}, []int{}, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s1 := NewSet(tt.set1...) + s2 := NewSet(tt.set2...) + assert.Equal(t, tt.result, s1.Equals(s2)) + }) + } +} + +func TestEmpty(t *testing.T) { + tests := []struct { + name string + input []int + result bool + }{ + {"non-empty set", []int{1}, false}, + {"empty set", []int{}, true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := NewSet(tt.input...) + assert.Equal(t, tt.result, s.Empty()) + }) + } +} diff --git a/internal/stringset.go b/internal/stringset.go deleted file mode 100644 index 1d44652ec..000000000 --- a/internal/stringset.go +++ /dev/null @@ -1,61 +0,0 @@ -package internal - -import "sort" - -// StringSet represents a set of string types. -type StringSet map[string]struct{} - -// NewStringSet creates a new empty StringSet. -func NewStringSet(start ...string) StringSet { - ret := make(StringSet) - for _, s := range start { - ret.Add(s) - } - return ret -} - -// Add a string to the set. -func (s StringSet) Add(i ...string) { - for _, str := range i { - s[str] = struct{}{} - } -} - -// Remove a string from the set. -func (s StringSet) Remove(i string) { - delete(s, i) -} - -// Contains indicates if the given string is contained within the set. -func (s StringSet) Contains(i string) bool { - _, ok := s[i] - return ok -} - -// ToSlice returns a sorted slice of strings that are contained within the set. -func (s StringSet) ToSlice() []string { - ret := make([]string, len(s)) - idx := 0 - for v := range s { - ret[idx] = v - idx++ - } - sort.Strings(ret) - return ret -} - -func (s StringSet) Equals(o StringSet) bool { - if len(s) != len(o) { - return false - } - for k := range s { - if !o.Contains(k) { - return false - } - } - return true -} - -func (s StringSet) Empty() bool { - return len(s) < 1 -} diff --git a/schema/json/schema-16.0.13.json b/schema/json/schema-16.0.13.json new file mode 100644 index 000000000..fc873ed1d --- /dev/null +++ b/schema/json/schema-16.0.13.json @@ -0,0 +1,2525 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "anchore.io/schema/syft/json/16.0.13/document", + "$ref": "#/$defs/Document", + "$defs": { + "AlpmDbEntry": { + "properties": { + "basepackage": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "packager": { + "type": "string" + }, + "url": { + "type": "string" + }, + "validation": { + "type": "string" + }, + "reason": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "backup": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "basepackage", + "package", + "version", + "description", + "architecture", + "size", + "packager", + "url", + "validation", + "reason", + "files", + "backup" + ] + }, + "AlpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "type": { + "type": "string" + }, + "uid": { + "type": "string" + }, + "gid": { + "type": "string" + }, + "time": { + "type": "string", + "format": "date-time" + }, + "size": { + "type": "string" + }, + "link": { + "type": "string" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object" + }, + "ApkDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "originPackage": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "version": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "url": { + "type": "string" + }, + "description": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "installedSize": { + "type": "integer" + }, + "pullDependencies": { + "items": { + "type": "string" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "pullChecksum": { + "type": "string" + }, + "gitCommitOfApkPort": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/ApkFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "originPackage", + "maintainer", + "version", + "architecture", + "url", + "description", + "size", + "installedSize", + "pullDependencies", + "provides", + "pullChecksum", + "gitCommitOfApkPort", + "files" + ] + }, + "ApkFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "ownerUid": { + "type": "string" + }, + "ownerGid": { + "type": "string" + }, + "permissions": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "BinarySignature": { + "properties": { + "matches": { + "items": { + "$ref": "#/$defs/ClassifierMatch" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "matches" + ] + }, + "CConanFileEntry": { + "properties": { + "ref": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanInfoEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "build_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "py_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "options": { + "$ref": "#/$defs/KeyValues" + }, + "path": { + "type": "string" + }, + "context": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockV2Entry": { + "properties": { + "ref": { + "type": "string" + }, + "packageID": { + "type": "string" + }, + "username": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "recipeRevision": { + "type": "string" + }, + "packageRevision": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CPE": { + "properties": { + "cpe": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "cpe" + ] + }, + "ClassifierMatch": { + "properties": { + "classifier": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Location" + } + }, + "type": "object", + "required": [ + "classifier", + "location" + ] + }, + "CocoaPodfileLockEntry": { + "properties": { + "checksum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "checksum" + ] + }, + "Coordinates": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "DartPubspecLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hosted_url": { + "type": "string" + }, + "vcs_url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Descriptor": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "configuration": true + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Digest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "Document": { + "properties": { + "artifacts": { + "items": { + "$ref": "#/$defs/Package" + }, + "type": "array" + }, + "artifactRelationships": { + "items": { + "$ref": "#/$defs/Relationship" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/File" + }, + "type": "array" + }, + "source": { + "$ref": "#/$defs/Source" + }, + "distro": { + "$ref": "#/$defs/LinuxRelease" + }, + "descriptor": { + "$ref": "#/$defs/Descriptor" + }, + "schema": { + "$ref": "#/$defs/Schema" + } + }, + "type": "object", + "required": [ + "artifacts", + "artifactRelationships", + "source", + "distro", + "descriptor", + "schema" + ] + }, + "DotnetDepsEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "path": { + "type": "string" + }, + "sha512": { + "type": "string" + }, + "hashPath": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "path", + "sha512", + "hashPath" + ] + }, + "DotnetPortableExecutableEntry": { + "properties": { + "assemblyVersion": { + "type": "string" + }, + "legalCopyright": { + "type": "string" + }, + "comments": { + "type": "string" + }, + "internalName": { + "type": "string" + }, + "companyName": { + "type": "string" + }, + "productName": { + "type": "string" + }, + "productVersion": { + "type": "string" + } + }, + "type": "object", + "required": [ + "assemblyVersion", + "legalCopyright", + "companyName", + "productName", + "productVersion" + ] + }, + "DpkgDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ] + }, + "DpkgFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "isConfigFile": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "path", + "isConfigFile" + ] + }, + "ELFSecurityFeatures": { + "properties": { + "symbolTableStripped": { + "type": "boolean" + }, + "stackCanary": { + "type": "boolean" + }, + "nx": { + "type": "boolean" + }, + "relRO": { + "type": "string" + }, + "pie": { + "type": "boolean" + }, + "dso": { + "type": "boolean" + }, + "safeStack": { + "type": "boolean" + }, + "cfi": { + "type": "boolean" + }, + "fortify": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "symbolTableStripped", + "nx", + "relRO", + "pie", + "dso" + ] + }, + "ElfBinaryPackageNoteJsonPayload": { + "properties": { + "type": { + "type": "string" + }, + "vendor": { + "type": "string" + }, + "system": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "commit": { + "type": "string" + } + }, + "type": "object" + }, + "ElixirMixLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "ErlangRebarLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "Executable": { + "properties": { + "format": { + "type": "string" + }, + "hasExports": { + "type": "boolean" + }, + "hasEntrypoint": { + "type": "boolean" + }, + "importedLibraries": { + "items": { + "type": "string" + }, + "type": "array" + }, + "elfSecurityFeatures": { + "$ref": "#/$defs/ELFSecurityFeatures" + } + }, + "type": "object", + "required": [ + "format", + "hasExports", + "hasEntrypoint", + "importedLibraries" + ] + }, + "File": { + "properties": { + "id": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Coordinates" + }, + "metadata": { + "$ref": "#/$defs/FileMetadataEntry" + }, + "contents": { + "type": "string" + }, + "digests": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/FileLicense" + }, + "type": "array" + }, + "executable": { + "$ref": "#/$defs/Executable" + } + }, + "type": "object", + "required": [ + "id", + "location" + ] + }, + "FileLicense": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "evidence": { + "$ref": "#/$defs/FileLicenseEvidence" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type" + ] + }, + "FileLicenseEvidence": { + "properties": { + "confidence": { + "type": "integer" + }, + "offset": { + "type": "integer" + }, + "extent": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "confidence", + "offset", + "extent" + ] + }, + "FileMetadataEntry": { + "properties": { + "mode": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "linkDestination": { + "type": "string" + }, + "userID": { + "type": "integer" + }, + "groupID": { + "type": "integer" + }, + "mimeType": { + "type": "string" + }, + "size": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "mode", + "type", + "userID", + "groupID", + "mimeType", + "size" + ] + }, + "GoModuleBuildinfoEntry": { + "properties": { + "goBuildSettings": { + "$ref": "#/$defs/KeyValues" + }, + "goCompiledVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "h1Digest": { + "type": "string" + }, + "mainModule": { + "type": "string" + }, + "goCryptoSettings": { + "items": { + "type": "string" + }, + "type": "array" + }, + "goExperiments": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "goCompiledVersion", + "architecture" + ] + }, + "GoModuleEntry": { + "properties": { + "h1Digest": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackEntry": { + "properties": { + "pkgHash": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackLockEntry": { + "properties": { + "pkgHash": { + "type": "string" + }, + "snapshotURL": { + "type": "string" + } + }, + "type": "object" + }, + "IDLikes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "JavaArchive": { + "properties": { + "virtualPath": { + "type": "string" + }, + "manifest": { + "$ref": "#/$defs/JavaManifest" + }, + "pomProperties": { + "$ref": "#/$defs/JavaPomProperties" + }, + "pomProject": { + "$ref": "#/$defs/JavaPomProject" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "virtualPath" + ] + }, + "JavaManifest": { + "properties": { + "main": { + "$ref": "#/$defs/KeyValues" + }, + "sections": { + "items": { + "$ref": "#/$defs/KeyValues" + }, + "type": "array" + } + }, + "type": "object" + }, + "JavaPomParent": { + "properties": { + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object", + "required": [ + "groupId", + "artifactId", + "version" + ] + }, + "JavaPomProject": { + "properties": { + "path": { + "type": "string" + }, + "parent": { + "$ref": "#/$defs/JavaPomParent" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "groupId", + "artifactId", + "version", + "name" + ] + }, + "JavaPomProperties": { + "properties": { + "path": { + "type": "string" + }, + "name": { + "type": "string" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "extraFields": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "name", + "groupId", + "artifactId", + "version" + ] + }, + "JavascriptNpmPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "private": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "homepage", + "description", + "url", + "private" + ] + }, + "JavascriptNpmPackageLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "JavascriptYarnLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "KeyValue": { + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "key", + "value" + ] + }, + "KeyValues": { + "items": { + "$ref": "#/$defs/KeyValue" + }, + "type": "array" + }, + "License": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "urls": { + "items": { + "type": "string" + }, + "type": "array" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type", + "urls", + "locations" + ] + }, + "LinuxKernelArchive": { + "properties": { + "name": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "version": { + "type": "string" + }, + "extendedVersion": { + "type": "string" + }, + "buildTime": { + "type": "string" + }, + "author": { + "type": "string" + }, + "format": { + "type": "string" + }, + "rwRootFS": { + "type": "boolean" + }, + "swapDevice": { + "type": "integer" + }, + "rootDevice": { + "type": "integer" + }, + "videoMode": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "architecture", + "version" + ] + }, + "LinuxKernelModule": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "path": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "license": { + "type": "string" + }, + "kernelVersion": { + "type": "string" + }, + "versionMagic": { + "type": "string" + }, + "parameters": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/LinuxKernelModuleParameter" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "LinuxKernelModuleParameter": { + "properties": { + "type": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "type": "object" + }, + "LinuxRelease": { + "properties": { + "prettyName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" + }, + "idLike": { + "$ref": "#/$defs/IDLikes" + }, + "version": { + "type": "string" + }, + "versionID": { + "type": "string" + }, + "versionCodename": { + "type": "string" + }, + "buildID": { + "type": "string" + }, + "imageID": { + "type": "string" + }, + "imageVersion": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "variantID": { + "type": "string" + }, + "homeURL": { + "type": "string" + }, + "supportURL": { + "type": "string" + }, + "bugReportURL": { + "type": "string" + }, + "privacyPolicyURL": { + "type": "string" + }, + "cpeName": { + "type": "string" + }, + "supportEnd": { + "type": "string" + } + }, + "type": "object" + }, + "Location": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + }, + "accessPath": { + "type": "string" + }, + "annotations": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "accessPath" + ] + }, + "LuarocksPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "dependencies": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "name", + "version", + "license", + "homepage", + "description", + "url", + "dependencies" + ] + }, + "MicrosoftKbPatch": { + "properties": { + "product_id": { + "type": "string" + }, + "kb": { + "type": "string" + } + }, + "type": "object", + "required": [ + "product_id", + "kb" + ] + }, + "NixStoreEntry": { + "properties": { + "outputHash": { + "type": "string" + }, + "output": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "outputHash", + "files" + ] + }, + "Package": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "foundBy": { + "type": "string" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "licenses": { + "$ref": "#/$defs/licenses" + }, + "language": { + "type": "string" + }, + "cpes": { + "$ref": "#/$defs/cpes" + }, + "purl": { + "type": "string" + }, + "metadataType": { + "type": "string" + }, + "metadata": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/AlpmDbEntry" + }, + { + "$ref": "#/$defs/ApkDbEntry" + }, + { + "$ref": "#/$defs/BinarySignature" + }, + { + "$ref": "#/$defs/CConanFileEntry" + }, + { + "$ref": "#/$defs/CConanInfoEntry" + }, + { + "$ref": "#/$defs/CConanLockEntry" + }, + { + "$ref": "#/$defs/CConanLockV2Entry" + }, + { + "$ref": "#/$defs/CocoaPodfileLockEntry" + }, + { + "$ref": "#/$defs/DartPubspecLockEntry" + }, + { + "$ref": "#/$defs/DotnetDepsEntry" + }, + { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + }, + { + "$ref": "#/$defs/DpkgDbEntry" + }, + { + "$ref": "#/$defs/ElfBinaryPackageNoteJsonPayload" + }, + { + "$ref": "#/$defs/ElixirMixLockEntry" + }, + { + "$ref": "#/$defs/ErlangRebarLockEntry" + }, + { + "$ref": "#/$defs/GoModuleBuildinfoEntry" + }, + { + "$ref": "#/$defs/GoModuleEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackLockEntry" + }, + { + "$ref": "#/$defs/JavaArchive" + }, + { + "$ref": "#/$defs/JavascriptNpmPackage" + }, + { + "$ref": "#/$defs/JavascriptNpmPackageLockEntry" + }, + { + "$ref": "#/$defs/JavascriptYarnLockEntry" + }, + { + "$ref": "#/$defs/LinuxKernelArchive" + }, + { + "$ref": "#/$defs/LinuxKernelModule" + }, + { + "$ref": "#/$defs/LuarocksPackage" + }, + { + "$ref": "#/$defs/MicrosoftKbPatch" + }, + { + "$ref": "#/$defs/NixStoreEntry" + }, + { + "$ref": "#/$defs/PhpComposerInstalledEntry" + }, + { + "$ref": "#/$defs/PhpComposerLockEntry" + }, + { + "$ref": "#/$defs/PhpPeclEntry" + }, + { + "$ref": "#/$defs/PortageDbEntry" + }, + { + "$ref": "#/$defs/PythonPackage" + }, + { + "$ref": "#/$defs/PythonPipRequirementsEntry" + }, + { + "$ref": "#/$defs/PythonPipfileLockEntry" + }, + { + "$ref": "#/$defs/PythonPoetryLockEntry" + }, + { + "$ref": "#/$defs/RDescription" + }, + { + "$ref": "#/$defs/RpmArchive" + }, + { + "$ref": "#/$defs/RpmDbEntry" + }, + { + "$ref": "#/$defs/RubyGemspec" + }, + { + "$ref": "#/$defs/RustCargoAuditEntry" + }, + { + "$ref": "#/$defs/RustCargoLockEntry" + }, + { + "$ref": "#/$defs/SwiftPackageManagerLockEntry" + }, + { + "$ref": "#/$defs/WordpressPluginEntry" + } + ] + } + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "foundBy", + "locations", + "licenses", + "language", + "cpes", + "purl" + ] + }, + "PhpComposerAuthors": { + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name" + ] + }, + "PhpComposerExternalReference": { + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "shasum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "type", + "url", + "reference" + ] + }, + "PhpComposerInstalledEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpComposerLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpPeclEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "PortageDbEntry": { + "properties": { + "installedSize": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/PortageFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "installedSize", + "files" + ] + }, + "PortageFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonDirectURLOriginInfo": { + "properties": { + "url": { + "type": "string" + }, + "commitId": { + "type": "string" + }, + "vcs": { + "type": "string" + } + }, + "type": "object", + "required": [ + "url" + ] + }, + "PythonFileDigest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "PythonFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/PythonFileDigest" + }, + "size": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/PythonFileRecord" + }, + "type": "array" + }, + "sitePackagesRootPath": { + "type": "string" + }, + "topLevelPackages": { + "items": { + "type": "string" + }, + "type": "array" + }, + "directUrlOrigin": { + "$ref": "#/$defs/PythonDirectURLOriginInfo" + }, + "requiresPython": { + "type": "string" + }, + "requiresDist": { + "items": { + "type": "string" + }, + "type": "array" + }, + "providesExtra": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "platform", + "sitePackagesRootPath" + ] + }, + "PythonPipRequirementsEntry": { + "properties": { + "name": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + }, + "versionConstraint": { + "type": "string" + }, + "url": { + "type": "string" + }, + "markers": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "versionConstraint" + ] + }, + "PythonPipfileLockEntry": { + "properties": { + "hashes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "index": { + "type": "string" + } + }, + "type": "object", + "required": [ + "hashes", + "index" + ] + }, + "PythonPoetryLockDependencyEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "optional": { + "type": "boolean" + }, + "markers": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "optional" + ] + }, + "PythonPoetryLockEntry": { + "properties": { + "index": { + "type": "string" + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonPoetryLockDependencyEntry" + }, + "type": "array" + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonPoetryLockExtraEntry" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ] + }, + "PythonPoetryLockExtraEntry": { + "properties": { + "name": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ] + }, + "RDescription": { + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "url": { + "items": { + "type": "string" + }, + "type": "array" + }, + "repository": { + "type": "string" + }, + "built": { + "type": "string" + }, + "needsCompilation": { + "type": "boolean" + }, + "imports": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "suggests": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "Relationship": { + "properties": { + "parent": { + "type": "string" + }, + "child": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "parent", + "child", + "type" + ] + }, + "RpmArchive": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmDbEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "mode": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "userName": { + "type": "string" + }, + "groupName": { + "type": "string" + }, + "flags": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "mode", + "size", + "digest", + "userName", + "groupName", + "flags" + ] + }, + "RubyGemspec": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "RustCargoAuditEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source" + ] + }, + "RustCargoLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + }, + "checksum": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "checksum", + "dependencies" + ] + }, + "Schema": { + "properties": { + "version": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "version", + "url" + ] + }, + "Source": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "metadata" + ] + }, + "SwiftPackageManagerLockEntry": { + "properties": { + "revision": { + "type": "string" + } + }, + "type": "object", + "required": [ + "revision" + ] + }, + "WordpressPluginEntry": { + "properties": { + "pluginInstallDirectory": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorUri": { + "type": "string" + } + }, + "type": "object", + "required": [ + "pluginInstallDirectory" + ] + }, + "cpes": { + "items": { + "$ref": "#/$defs/CPE" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/License" + }, + "type": "array" + } + } +} diff --git a/schema/json/schema-latest.json b/schema/json/schema-latest.json index 724e0bab8..fc873ed1d 100644 --- a/schema/json/schema-latest.json +++ b/schema/json/schema-latest.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "anchore.io/schema/syft/json/16.0.12/document", + "$id": "anchore.io/schema/syft/json/16.0.13/document", "$ref": "#/$defs/Document", "$defs": { "AlpmDbEntry": { @@ -2051,15 +2051,74 @@ "index" ] }, + "PythonPoetryLockDependencyEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "optional": { + "type": "boolean" + }, + "markers": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "optional" + ] + }, "PythonPoetryLockEntry": { "properties": { "index": { "type": "string" + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonPoetryLockDependencyEntry" + }, + "type": "array" + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonPoetryLockExtraEntry" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ] + }, + "PythonPoetryLockExtraEntry": { + "properties": { + "name": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" } }, "type": "object", "required": [ - "index" + "name", + "dependencies" ] }, "RDescription": { diff --git a/syft/pkg/cataloger/alpine/dependency.go b/syft/pkg/cataloger/alpine/dependency.go index ea63f36bb..ff1360d12 100644 --- a/syft/pkg/cataloger/alpine/dependency.go +++ b/syft/pkg/cataloger/alpine/dependency.go @@ -22,8 +22,10 @@ func dbEntryDependencySpecifier(p pkg.Package) dependency.Specification { provides = append(provides, stripVersionSpecifiers(meta.Provides)...) return dependency.Specification{ - Provides: provides, - Requires: stripVersionSpecifiers(meta.Dependencies), + ProvidesRequires: dependency.ProvidesRequires{ + Provides: provides, + Requires: stripVersionSpecifiers(meta.Dependencies), + }, } } diff --git a/syft/pkg/cataloger/alpine/dependency_test.go b/syft/pkg/cataloger/alpine/dependency_test.go index a55cba4cb..3ff3c6dd6 100644 --- a/syft/pkg/cataloger/alpine/dependency_test.go +++ b/syft/pkg/cataloger/alpine/dependency_test.go @@ -25,8 +25,10 @@ func Test_dbEntryDependencySpecifier(t *testing.T) { }, }, want: dependency.Specification{ - Provides: []string{"package-c", "a-thing"}, - Requires: []string{"b-thing"}, + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"package-c", "a-thing"}, + Requires: []string{"b-thing"}, + }, }, }, { @@ -39,8 +41,10 @@ func Test_dbEntryDependencySpecifier(t *testing.T) { }, }, want: dependency.Specification{ - Provides: []string{"package-a", "so:libc.musl-x86_64.so.1"}, - Requires: []string{"so:libc.musl-x86_64.so.2"}, + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"package-a", "so:libc.musl-x86_64.so.1"}, + Requires: []string{"so:libc.musl-x86_64.so.2"}, + }, }, }, { @@ -53,8 +57,10 @@ func Test_dbEntryDependencySpecifier(t *testing.T) { }, }, want: dependency.Specification{ - Provides: []string{"package-a"}, - Requires: nil, + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"package-a"}, + Requires: nil, + }, }, }, } diff --git a/syft/pkg/cataloger/arch/dependency.go b/syft/pkg/cataloger/arch/dependency.go index 796a61e1b..cabb6eac8 100644 --- a/syft/pkg/cataloger/arch/dependency.go +++ b/syft/pkg/cataloger/arch/dependency.go @@ -34,8 +34,10 @@ func dbEntryDependencySpecifier(p pkg.Package) dependency.Specification { } return dependency.Specification{ - Provides: provides, - Requires: requires, + ProvidesRequires: dependency.ProvidesRequires{ + Provides: provides, + Requires: requires, + }, } } diff --git a/syft/pkg/cataloger/arch/dependency_test.go b/syft/pkg/cataloger/arch/dependency_test.go index e4eafae81..98f62d7bf 100644 --- a/syft/pkg/cataloger/arch/dependency_test.go +++ b/syft/pkg/cataloger/arch/dependency_test.go @@ -25,8 +25,10 @@ func Test_dbEntryDependencySpecifier(t *testing.T) { }, }, want: dependency.Specification{ - Provides: []string{"package-c", "a-thing", "a-thing"}, // note: gets deduplicated downstream - Requires: []string{"b-thing"}, + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"package-c", "a-thing", "a-thing"}, // note: gets deduplicated downstream + Requires: []string{"b-thing"}, + }, }, }, { @@ -39,8 +41,10 @@ func Test_dbEntryDependencySpecifier(t *testing.T) { }, }, want: dependency.Specification{ - Provides: []string{"package-a", "libtree-sitter.so.me=1-64", "libtree-sitter.so.me"}, - Requires: []string{"libtree-sitter.so.thing=2-64"}, + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"package-a", "libtree-sitter.so.me=1-64", "libtree-sitter.so.me"}, + Requires: []string{"libtree-sitter.so.thing=2-64"}, + }, }, }, { @@ -53,8 +57,10 @@ func Test_dbEntryDependencySpecifier(t *testing.T) { }, }, want: dependency.Specification{ - Provides: []string{"package-a"}, - Requires: nil, + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"package-a"}, + Requires: nil, + }, }, }, } diff --git a/syft/pkg/cataloger/debian/dependency.go b/syft/pkg/cataloger/debian/dependency.go index 9fe39899e..fdebdf603 100644 --- a/syft/pkg/cataloger/debian/dependency.go +++ b/syft/pkg/cataloger/debian/dependency.go @@ -38,8 +38,10 @@ func dbEntryDependencySpecifier(p pkg.Package) dependency.Specification { } return dependency.Specification{ - Provides: provides, - Requires: requires, + ProvidesRequires: dependency.ProvidesRequires{ + Provides: provides, + Requires: requires, + }, } } diff --git a/syft/pkg/cataloger/debian/dependency_test.go b/syft/pkg/cataloger/debian/dependency_test.go index 5e2225748..05d7abfb6 100644 --- a/syft/pkg/cataloger/debian/dependency_test.go +++ b/syft/pkg/cataloger/debian/dependency_test.go @@ -25,8 +25,10 @@ func Test_dbEntryDependencySpecifier(t *testing.T) { }, }, want: dependency.Specification{ - Provides: []string{"package-c", "a-thing"}, - Requires: []string{"b-thing"}, + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"package-c", "a-thing"}, + Requires: []string{"b-thing"}, + }, }, }, { @@ -39,8 +41,10 @@ func Test_dbEntryDependencySpecifier(t *testing.T) { }, }, want: dependency.Specification{ - Provides: []string{"package-a", "foo"}, - Requires: []string{"libgmp10", "default-mta", "mail-transport-agent"}, + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"package-a", "foo"}, + Requires: []string{"libgmp10", "default-mta", "mail-transport-agent"}, + }, }, }, { @@ -53,8 +57,10 @@ func Test_dbEntryDependencySpecifier(t *testing.T) { }, }, want: dependency.Specification{ - Provides: []string{"package-a"}, - Requires: nil, + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"package-a"}, + Requires: nil, + }, }, }, } diff --git a/syft/pkg/cataloger/internal/dependency/resolver.go b/syft/pkg/cataloger/internal/dependency/resolver.go index d60e3bb3c..c7074df79 100644 --- a/syft/pkg/cataloger/internal/dependency/resolver.go +++ b/syft/pkg/cataloger/internal/dependency/resolver.go @@ -5,6 +5,7 @@ import ( "github.com/scylladb/go-set/strset" + "github.com/anchore/syft/internal" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/generic" @@ -14,6 +15,14 @@ import ( // requires for itself. These strings can represent anything from file paths, package names, or any other concept // that is useful for dependency resolution within that packing ecosystem. type Specification struct { + ProvidesRequires + + // Variants allows for specifying multiple sets of provides/requires for a single package. This is useful + // in cases when you have conditional optional dependencies for a package. + Variants []ProvidesRequires +} + +type ProvidesRequires struct { // Provides holds a list of abstract resources that this package provides for other packages. Provides []string @@ -37,53 +46,68 @@ func Processor(s Specifier) generic.Processor { } } - rels = append(rels, resolve(s, pkgs)...) + rels = append(rels, Resolve(s, pkgs)...) return pkgs, rels, err } } -// resolve will create relationships between packages based on the dependency claims of each package. -func resolve(specifier Specifier, pkgs []pkg.Package) (relationships []artifact.Relationship) { - pkgsProvidingResource := make(map[string][]artifact.ID) +// Resolve will create relationships between packages based on the dependency claims of each package. +func Resolve(specifier Specifier, pkgs []pkg.Package) (relationships []artifact.Relationship) { + pkgsProvidingResource := make(map[string]internal.Set[artifact.ID]) pkgsByID := make(map[artifact.ID]pkg.Package) - specsByPkg := make(map[artifact.ID]Specification) + specsByPkg := make(map[artifact.ID][]ProvidesRequires) for _, p := range pkgs { id := p.ID() pkgsByID[id] = p - specsByPkg[id] = specifier(p) - for _, resource := range deduplicate(specifier(p).Provides) { - pkgsProvidingResource[resource] = append(pkgsProvidingResource[resource], id) - } + specsByPkg[id] = allProvides(pkgsProvidingResource, id, specifier(p)) } seen := strset.New() for _, dependantPkg := range pkgs { - spec := specsByPkg[dependantPkg.ID()] - for _, resource := range deduplicate(spec.Requires) { - for _, providingPkgID := range pkgsProvidingResource[resource] { - // prevent creating duplicate relationships - pairKey := string(providingPkgID) + "-" + string(dependantPkg.ID()) - if seen.Has(pairKey) { - continue + specs := specsByPkg[dependantPkg.ID()] + for _, spec := range specs { + for _, resource := range deduplicate(spec.Requires) { + for providingPkgID := range pkgsProvidingResource[resource] { + // prevent creating duplicate relationships + pairKey := string(providingPkgID) + "-" + string(dependantPkg.ID()) + if seen.Has(pairKey) { + continue + } + + providingPkg := pkgsByID[providingPkgID] + + relationships = append(relationships, + artifact.Relationship{ + From: providingPkg, + To: dependantPkg, + Type: artifact.DependencyOfRelationship, + }, + ) + + seen.Add(pairKey) } + } + } + } + return relationships +} - providingPkg := pkgsByID[providingPkgID] - - relationships = append(relationships, - artifact.Relationship{ - From: providingPkg, - To: dependantPkg, - Type: artifact.DependencyOfRelationship, - }, - ) +func allProvides(pkgsProvidingResource map[string]internal.Set[artifact.ID], id artifact.ID, spec Specification) []ProvidesRequires { + prs := []ProvidesRequires{spec.ProvidesRequires} + prs = append(prs, spec.Variants...) - seen.Add(pairKey) + for _, pr := range prs { + for _, resource := range deduplicate(pr.Provides) { + if pkgsProvidingResource[resource] == nil { + pkgsProvidingResource[resource] = internal.NewSet[artifact.ID]() } + pkgsProvidingResource[resource].Add(id) } } - return relationships + + return prs } func deduplicate(ss []string) []string { diff --git a/syft/pkg/cataloger/internal/dependency/resolver_test.go b/syft/pkg/cataloger/internal/dependency/resolver_test.go index c6690d958..d887decc0 100644 --- a/syft/pkg/cataloger/internal/dependency/resolver_test.go +++ b/syft/pkg/cataloger/internal/dependency/resolver_test.go @@ -44,6 +44,19 @@ func Test_resolve(t *testing.T) { "b": /* depends on */ {"a"}, }, }, + { + name: "find relationships between packages with variants", + s: newSpecifierBuilder(). + WithProvides(a /* provides */, "a-resource"). + WithRequires(b /* requires */, "a[variant]"). + WithProvides(c /* provides */, "c-resource"). + WithVariant(a /* provides */, "variant" /* which requires */, "c-resource"). + Specifier(), + want: map[string][]string{ + "b":/* depends on */ {"a"}, + "a":/* depends on */ {"c"}, + }, + }, { name: "deduplicates provider keys", s: newSpecifierBuilder(). @@ -71,7 +84,7 @@ func Test_resolve(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - relationships := resolve(tt.s, subjects) + relationships := Resolve(tt.s, subjects) if d := cmp.Diff(tt.want, abstractRelationships(t, relationships)); d != "" { t.Errorf("unexpected relationships (-want +got):\n%s", d) } @@ -82,12 +95,14 @@ func Test_resolve(t *testing.T) { type specifierBuilder struct { provides map[string][]string requires map[string][]string + variants map[string]map[string][]string } func newSpecifierBuilder() *specifierBuilder { return &specifierBuilder{ provides: make(map[string][]string), requires: make(map[string][]string), + variants: make(map[string]map[string][]string), } } @@ -101,11 +116,30 @@ func (m *specifierBuilder) WithRequires(p pkg.Package, requires ...string) *spec return m } +func (m *specifierBuilder) WithVariant(p pkg.Package, variantName string, requires ...string) *specifierBuilder { + if _, ok := m.variants[p.Name]; !ok { + m.variants[p.Name] = make(map[string][]string) + } + m.variants[p.Name][variantName] = append(m.variants[p.Name][variantName], requires...) + return m +} + func (m specifierBuilder) Specifier() Specifier { return func(p pkg.Package) Specification { + var prs []ProvidesRequires + for variantName, requires := range m.variants[p.Name] { + prs = append(prs, ProvidesRequires{ + Provides: []string{p.Name + "[" + variantName + "]"}, + Requires: requires, + }) + } + return Specification{ - Provides: m.provides[p.Name], - Requires: m.requires[p.Name], + ProvidesRequires: ProvidesRequires{ + Provides: m.provides[p.Name], + Requires: m.requires[p.Name], + }, + Variants: prs, } } } diff --git a/syft/pkg/cataloger/python/cataloger_test.go b/syft/pkg/cataloger/python/cataloger_test.go index df30307ca..e1093a55a 100644 --- a/syft/pkg/cataloger/python/cataloger_test.go +++ b/syft/pkg/cataloger/python/cataloger_test.go @@ -382,6 +382,201 @@ func Test_PackageCataloger_Globs(t *testing.T) { } } +func Test_PoetryLockCataloger_Relationships(t *testing.T) { + tests := []struct { + name string + fixture string + expectedRelationships []string + }{ + { + name: "no dependencies", + fixture: "test-fixtures/poetry/dev-deps", + expectedRelationships: nil, + }, + { + name: "simple dependencies", + fixture: "test-fixtures/poetry/simple-deps", + expectedRelationships: []string{ + "certifi @ 2024.2.2 (.) [dependency-of] requests @ 2.32.2 (.)", + "charset-normalizer @ 3.3.2 (.) [dependency-of] requests @ 2.32.2 (.)", + "idna @ 3.7 (.) [dependency-of] requests @ 2.32.2 (.)", + "urllib3 @ 2.2.1 (.) [dependency-of] requests @ 2.32.2 (.)", + }, + }, + { + name: "multiple extras", + fixture: "test-fixtures/poetry/multiple-extras", + expectedRelationships: []string{ + "anyio @ 4.3.0 (.) [dependency-of] anyio @ 4.3.0 (.)", + "anyio @ 4.3.0 (.) [dependency-of] httpcore @ 1.0.5 (.)", + "anyio @ 4.3.0 (.) [dependency-of] httpx @ 0.27.0 (.)", + "brotli @ 1.1.0 (.) [dependency-of] httpx @ 0.27.0 (.)", + "brotlicffi @ 1.1.0.0 (.) [dependency-of] httpx @ 0.27.0 (.)", + "certifi @ 2024.2.2 (.) [dependency-of] httpcore @ 1.0.5 (.)", + "certifi @ 2024.2.2 (.) [dependency-of] httpx @ 0.27.0 (.)", + "cffi @ 1.16.0 (.) [dependency-of] brotlicffi @ 1.1.0.0 (.)", + "h11 @ 0.14.0 (.) [dependency-of] httpcore @ 1.0.5 (.)", + "h2 @ 4.1.0 (.) [dependency-of] httpcore @ 1.0.5 (.)", + "h2 @ 4.1.0 (.) [dependency-of] httpx @ 0.27.0 (.)", + "hpack @ 4.0.0 (.) [dependency-of] h2 @ 4.1.0 (.)", + "httpcore @ 1.0.5 (.) [dependency-of] httpx @ 0.27.0 (.)", + "hyperframe @ 6.0.1 (.) [dependency-of] h2 @ 4.1.0 (.)", + "idna @ 3.7 (.) [dependency-of] anyio @ 4.3.0 (.)", + "idna @ 3.7 (.) [dependency-of] httpx @ 0.27.0 (.)", + "pycparser @ 2.22 (.) [dependency-of] cffi @ 1.16.0 (.)", + "sniffio @ 1.3.1 (.) [dependency-of] anyio @ 4.3.0 (.)", + "sniffio @ 1.3.1 (.) [dependency-of] httpx @ 0.27.0 (.)", + "socksio @ 1.0.0 (.) [dependency-of] httpcore @ 1.0.5 (.)", + "socksio @ 1.0.0 (.) [dependency-of] httpx @ 0.27.0 (.)", + }, + }, + { + name: "nested extras", + fixture: "test-fixtures/poetry/nested-extras", + expectedRelationships: []string{ + "annotated-types @ 0.7.0 (.) [dependency-of] pydantic @ 2.7.1 (.)", + "anyio @ 4.3.0 (.) [dependency-of] anyio @ 4.3.0 (.)", + "anyio @ 4.3.0 (.) [dependency-of] httpcore @ 1.0.5 (.)", + "anyio @ 4.3.0 (.) [dependency-of] httpx @ 0.27.0 (.)", + "anyio @ 4.3.0 (.) [dependency-of] starlette @ 0.37.2 (.)", + "anyio @ 4.3.0 (.) [dependency-of] watchfiles @ 0.21.0 (.)", + "certifi @ 2024.2.2 (.) [dependency-of] httpcore @ 1.0.5 (.)", + "certifi @ 2024.2.2 (.) [dependency-of] httpx @ 0.27.0 (.)", + "click @ 8.1.7 (.) [dependency-of] httpx @ 0.27.0 (.)", + "click @ 8.1.7 (.) [dependency-of] python-dotenv @ 1.0.1 (.)", + "click @ 8.1.7 (.) [dependency-of] typer @ 0.12.3 (.)", + "click @ 8.1.7 (.) [dependency-of] uvicorn @ 0.29.0 (.)", + "colorama @ 0.4.6 (.) [dependency-of] click @ 8.1.7 (.)", + "colorama @ 0.4.6 (.) [dependency-of] pygments @ 2.18.0 (.)", + "colorama @ 0.4.6 (.) [dependency-of] uvicorn @ 0.29.0 (.)", // proof of uvicorn[standard] + "dnspython @ 2.6.1 (.) [dependency-of] email-validator @ 2.1.1 (.)", + "email-validator @ 2.1.1 (.) [dependency-of] pydantic @ 2.7.1 (.)", + "fastapi @ 0.111.0 (.) [dependency-of] fastapi-cli @ 0.0.4 (.)", + "fastapi-cli @ 0.0.4 (.) [dependency-of] fastapi @ 0.111.0 (.)", + "h11 @ 0.14.0 (.) [dependency-of] httpcore @ 1.0.5 (.)", + "h11 @ 0.14.0 (.) [dependency-of] uvicorn @ 0.29.0 (.)", + "httpcore @ 1.0.5 (.) [dependency-of] dnspython @ 2.6.1 (.)", + "httpcore @ 1.0.5 (.) [dependency-of] httpx @ 0.27.0 (.)", + "httptools @ 0.6.1 (.) [dependency-of] uvicorn @ 0.29.0 (.)", // proof of uvicorn[standard] + "httpx @ 0.27.0 (.) [dependency-of] dnspython @ 2.6.1 (.)", + "httpx @ 0.27.0 (.) [dependency-of] fastapi @ 0.111.0 (.)", + "httpx @ 0.27.0 (.) [dependency-of] starlette @ 0.37.2 (.)", + "idna @ 3.7 (.) [dependency-of] anyio @ 4.3.0 (.)", + "idna @ 3.7 (.) [dependency-of] dnspython @ 2.6.1 (.)", + "idna @ 3.7 (.) [dependency-of] email-validator @ 2.1.1 (.)", + "idna @ 3.7 (.) [dependency-of] httpx @ 0.27.0 (.)", + "itsdangerous @ 2.2.0 (.) [dependency-of] fastapi @ 0.111.0 (.)", + "itsdangerous @ 2.2.0 (.) [dependency-of] starlette @ 0.37.2 (.)", + "jinja2 @ 3.1.4 (.) [dependency-of] fastapi @ 0.111.0 (.)", + "jinja2 @ 3.1.4 (.) [dependency-of] starlette @ 0.37.2 (.)", + "markdown-it-py @ 3.0.0 (.) [dependency-of] rich @ 13.7.1 (.)", + "mdurl @ 0.1.2 (.) [dependency-of] markdown-it-py @ 3.0.0 (.)", + "orjson @ 3.10.3 (.) [dependency-of] fastapi @ 0.111.0 (.)", + "pydantic @ 2.7.1 (.) [dependency-of] fastapi @ 0.111.0 (.)", + "pydantic @ 2.7.1 (.) [dependency-of] pydantic-extra-types @ 2.7.0 (.)", + "pydantic @ 2.7.1 (.) [dependency-of] pydantic-settings @ 2.2.1 (.)", + "pydantic-core @ 2.18.2 (.) [dependency-of] pydantic @ 2.7.1 (.)", + "pydantic-extra-types @ 2.7.0 (.) [dependency-of] fastapi @ 0.111.0 (.)", + "pydantic-settings @ 2.2.1 (.) [dependency-of] fastapi @ 0.111.0 (.)", + "pygments @ 2.18.0 (.) [dependency-of] httpx @ 0.27.0 (.)", + "pygments @ 2.18.0 (.) [dependency-of] rich @ 13.7.1 (.)", + "python-dotenv @ 1.0.1 (.) [dependency-of] pydantic-settings @ 2.2.1 (.)", + "python-dotenv @ 1.0.1 (.) [dependency-of] uvicorn @ 0.29.0 (.)", // proof of uvicorn[standard] + "python-multipart @ 0.0.9 (.) [dependency-of] fastapi @ 0.111.0 (.)", + "python-multipart @ 0.0.9 (.) [dependency-of] starlette @ 0.37.2 (.)", + "pyyaml @ 6.0.1 (.) [dependency-of] fastapi @ 0.111.0 (.)", + "pyyaml @ 6.0.1 (.) [dependency-of] markdown-it-py @ 3.0.0 (.)", + "pyyaml @ 6.0.1 (.) [dependency-of] pydantic-settings @ 2.2.1 (.)", + "pyyaml @ 6.0.1 (.) [dependency-of] python-multipart @ 0.0.9 (.)", + "pyyaml @ 6.0.1 (.) [dependency-of] starlette @ 0.37.2 (.)", + "pyyaml @ 6.0.1 (.) [dependency-of] uvicorn @ 0.29.0 (.)", // proof of uvicorn[standard] + "rich @ 13.7.1 (.) [dependency-of] httpx @ 0.27.0 (.)", + "rich @ 13.7.1 (.) [dependency-of] typer @ 0.12.3 (.)", + "shellingham @ 1.5.4 (.) [dependency-of] typer @ 0.12.3 (.)", + "sniffio @ 1.3.1 (.) [dependency-of] anyio @ 4.3.0 (.)", + "sniffio @ 1.3.1 (.) [dependency-of] httpx @ 0.27.0 (.)", + "starlette @ 0.37.2 (.) [dependency-of] fastapi @ 0.111.0 (.)", + "typer @ 0.12.3 (.) [dependency-of] fastapi-cli @ 0.0.4 (.)", + "typing-extensions @ 4.12.0 (.) [dependency-of] fastapi @ 0.111.0 (.)", + "typing-extensions @ 4.12.0 (.) [dependency-of] pydantic @ 2.7.1 (.)", + "typing-extensions @ 4.12.0 (.) [dependency-of] pydantic-core @ 2.18.2 (.)", + "typing-extensions @ 4.12.0 (.) [dependency-of] typer @ 0.12.3 (.)", + "ujson @ 5.10.0 (.) [dependency-of] fastapi @ 0.111.0 (.)", + "uvicorn @ 0.29.0 (.) [dependency-of] fastapi @ 0.111.0 (.)", + "uvicorn @ 0.29.0 (.) [dependency-of] fastapi-cli @ 0.0.4 (.)", + "uvloop @ 0.19.0 (.) [dependency-of] anyio @ 4.3.0 (.)", + "uvloop @ 0.19.0 (.) [dependency-of] uvicorn @ 0.29.0 (.)", // proof of uvicorn[standard] + "watchfiles @ 0.21.0 (.) [dependency-of] uvicorn @ 0.29.0 (.)", // proof of uvicorn[standard] + "websockets @ 12.0 (.) [dependency-of] uvicorn @ 0.29.0 (.)", // proof of uvicorn[standard] + }, + }, + { + name: "conflicting extras", + fixture: "test-fixtures/poetry/conflicting-with-extras", + expectedRelationships: []string{ + "anyio @ 4.3.0 (.) [dependency-of] anyio @ 4.3.0 (.)", + "anyio @ 4.3.0 (.) [dependency-of] httpcore @ 1.0.5 (.)", + "anyio @ 4.3.0 (.) [dependency-of] httpx @ 0.27.0 (.)", + "brotli @ 1.1.0 (.) [dependency-of] httpx @ 0.27.0 (.)", + "brotlicffi @ 1.1.0.0 (.) [dependency-of] httpx @ 0.27.0 (.)", + "certifi @ 2024.2.2 (.) [dependency-of] httpcore @ 1.0.5 (.)", + "certifi @ 2024.2.2 (.) [dependency-of] httpx @ 0.27.0 (.)", + "cffi @ 1.16.0 (.) [dependency-of] brotlicffi @ 1.1.0.0 (.)", + "colorama @ 0.4.6 (.) [dependency-of] rich @ 0.3.3 (.)", + "h11 @ 0.14.0 (.) [dependency-of] httpcore @ 1.0.5 (.)", + "h2 @ 4.1.0 (.) [dependency-of] httpcore @ 1.0.5 (.)", + "h2 @ 4.1.0 (.) [dependency-of] httpx @ 0.27.0 (.)", + "hpack @ 4.0.0 (.) [dependency-of] h2 @ 4.1.0 (.)", + "httpcore @ 1.0.5 (.) [dependency-of] httpx @ 0.27.0 (.)", + "hyperframe @ 6.0.1 (.) [dependency-of] h2 @ 4.1.0 (.)", + "idna @ 3.7 (.) [dependency-of] anyio @ 4.3.0 (.)", + "idna @ 3.7 (.) [dependency-of] httpx @ 0.27.0 (.)", + "pprintpp @ 0.4.0 (.) [dependency-of] rich @ 0.3.3 (.)", + "pycparser @ 2.22 (.) [dependency-of] cffi @ 1.16.0 (.)", + "sniffio @ 1.3.1 (.) [dependency-of] anyio @ 4.3.0 (.)", + "sniffio @ 1.3.1 (.) [dependency-of] httpx @ 0.27.0 (.)", + "socksio @ 1.0.0 (.) [dependency-of] httpcore @ 1.0.5 (.)", + "socksio @ 1.0.0 (.) [dependency-of] httpx @ 0.27.0 (.)", + "typing-extensions @ 3.10.0.2 (.) [dependency-of] rich @ 0.3.3 (.)", + + // ideally we should NOT see these dependencies. However, they are technically installed in the environment + // and an import is present in httpx for each of these, so in theory they are actually dependencies even + // though our pyproject.toml looks like this: + // + // [tool.poetry.dependencies] + // python = "^3.11" + // httpx = {extras = ["brotli", "http2", "socks"], version = "^0.27.0"} + // pygments = "1.6" + // click = "<8" + // rich = "<10" + // + // note that pygments, click, and rich are installed outside of the allowable ranges for the given + // httpx package version constraints, per the poetry.lock: + // + // # for package httpx + // [package.extras] + // cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] + // + // note: the pyproject.toml and poetry.lock state are consistent with each other (just with + // "poetry install" and "poetry lock", and nothing was forced!) + "click @ 7.1.2 (.) [dependency-of] httpx @ 0.27.0 (.)", + "pygments @ 1.6 (.) [dependency-of] httpx @ 0.27.0 (.)", + "rich @ 0.3.3 (.) [dependency-of] httpx @ 0.27.0 (.)", + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + pkgtest.NewCatalogTester(). + FromDirectory(t, test.fixture). + WithPackageStringer(stringPackage). + ExpectsRelationshipStrings(test.expectedRelationships). + TestCataloger(t, NewPackageCataloger(DefaultCatalogerConfig())) + }) + } +} + func Test_PackageCataloger_SitePackageRelationships(t *testing.T) { tests := []struct { name string diff --git a/syft/pkg/cataloger/python/dependency.go b/syft/pkg/cataloger/python/dependency.go index e0ec872df..7479649d0 100644 --- a/syft/pkg/cataloger/python/dependency.go +++ b/syft/pkg/cataloger/python/dependency.go @@ -15,7 +15,72 @@ import ( "github.com/anchore/syft/syft/pkg/cataloger/internal/dependency" ) -var _ dependency.Specifier = wheelEggDependencySpecifier +func poetryLockDependencySpecifier(p pkg.Package) dependency.Specification { + meta, ok := p.Metadata.(pkg.PythonPoetryLockEntry) + if !ok { + log.Tracef("cataloger failed to extract poetry lock metadata for package %+v", p.Name) + return dependency.Specification{} + } + + // this package reference always includes the package name and no extras + provides := []string{packageRef(p.Name, "")} + + var requires []string + // add required dependencies (those which a marker is not present indicating it is explicitly optional or needs an extra marker) + for _, dep := range meta.Dependencies { + if isDependencyForExtra(dep) { + continue + } + + // we always have the base package requirement without any extras to get base dependencies + requires = append(requires, packageRef(dep.Name, "")) + + // if there are extras, we need to add a requirement for each extra individually + // for example: + // uvicorn = {version = ">=0.12.0", extras = ["standard", "else"]} + // then we must install uvicorn with the extras "standard" and "else" to satisfy the requirement + for _, extra := range dep.Extras { + // always refer to extras with the package name (e.g. name[extra]) + // note: this must always be done independent of other extras (e.g. name[extra1] and name[extra2] separately + // is correct and name[extra1,extra2] will result in dependency resolution failure) + requires = append(requires, packageRef(dep.Name, extra)) + } + } + + var variants []dependency.ProvidesRequires + for _, extra := range meta.Extras { + variants = append(variants, + dependency.ProvidesRequires{ + // always refer to extras with the package name (e.g. name[extra]) + // note: this must always be done independent of other extras (e.g. name[extra1] and name[extra2] separately + // is correct and name[extra1,extra2] will result in dependency resolution failure) + Provides: []string{packageRef(p.Name, extra.Name)}, + Requires: extractPackageNames(extra.Dependencies), + }, + ) + } + + return dependency.Specification{ + ProvidesRequires: dependency.ProvidesRequires{ + Provides: provides, + Requires: requires, + }, + Variants: variants, + } +} + +func isDependencyForExtra(dep pkg.PythonPoetryLockDependencyEntry) bool { + return strings.Contains(dep.Markers, "extra ==") +} + +func packageRef(name, extra string) string { + cleanExtra := strings.TrimSpace(extra) + cleanName := strings.TrimSpace(name) + if cleanExtra == "" { + return cleanName + } + return cleanName + "[" + cleanExtra + "]" +} func wheelEggDependencySpecifier(p pkg.Package) dependency.Specification { meta, ok := p.Metadata.(pkg.PythonPackage) @@ -35,7 +100,7 @@ func wheelEggDependencySpecifier(p pkg.Package) dependency.Specification { // how extras function, where there tends to be a try/except around imports as an indication if that extra // functionality should be executed or not (there isn't a package declaration to reference at runtime). for _, depSpecifier := range meta.RequiresDist { - depSpecifier = extractPackageNameFromRequiresDest(depSpecifier) + depSpecifier = extractPackageName(depSpecifier) if depSpecifier == "" { continue } @@ -43,20 +108,29 @@ func wheelEggDependencySpecifier(p pkg.Package) dependency.Specification { } return dependency.Specification{ - Provides: provides, - Requires: requires, + ProvidesRequires: dependency.ProvidesRequires{ + Provides: provides, + Requires: requires, + }, } } -// extractPackageNameFromRequiresDest removes any extras or version constraints from a given Requires-Dist field value, -// leaving only the package name. -func extractPackageNameFromRequiresDest(s string) string { +// extractPackageName removes any extras or version constraints from a given Requires-Dist field value (and +// semantically similar fields), leaving only the package name. +func extractPackageName(s string) string { // examples: // html5lib ; extra == 'html5lib' --> html5lib // soupsieve (>1.2) --> soupsieve return strings.TrimSpace(internal.SplitAny(s, "(;")[0]) } +func extractPackageNames(ss []string) []string { + var names []string + for _, s := range ss { + names = append(names, extractPackageName(s)) + } + return names +} func wheelEggRelationships(ctx context.Context, resolver file.Resolver, pkgs []pkg.Package, rels []artifact.Relationship, err error) ([]pkg.Package, []artifact.Relationship, error) { if err != nil { diff --git a/syft/pkg/cataloger/python/dependency_test.go b/syft/pkg/cataloger/python/dependency_test.go index c0303531a..a3b520755 100644 --- a/syft/pkg/cataloger/python/dependency_test.go +++ b/syft/pkg/cataloger/python/dependency_test.go @@ -1 +1,275 @@ package python + +import ( + "os" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/internal/dependency" +) + +func Test_poetryLockDependencySpecifier(t *testing.T) { + + tests := []struct { + name string + p pkg.Package + want dependency.Specification + }{ + { + name: "no dependencies", + p: pkg.Package{ + Name: "foo", + Metadata: pkg.PythonPoetryLockEntry{ + Dependencies: []pkg.PythonPoetryLockDependencyEntry{}, + }, + }, + want: dependency.Specification{ + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"foo"}, + }, + }, + }, + { + name: "with required dependencies", + p: pkg.Package{ + Name: "foo", + Metadata: pkg.PythonPoetryLockEntry{ + Dependencies: []pkg.PythonPoetryLockDependencyEntry{ + { + Name: "bar", + Version: "1.2.3", + }, + }, + }, + }, + want: dependency.Specification{ + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"foo"}, + Requires: []string{"bar"}, + }, + }, + }, + { + name: "with optional dependencies (explicit)", + p: pkg.Package{ + Name: "foo", + Metadata: pkg.PythonPoetryLockEntry{ + Dependencies: []pkg.PythonPoetryLockDependencyEntry{ + { + Name: "bar", + Version: "1.2.3", + Optional: true, + }, + }, + }, + }, + want: dependency.Specification{ + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"foo"}, + Requires: []string{"bar"}, + }, + }, + }, + { + name: "without dependencies for non-required extra", + p: pkg.Package{ + Name: "foo", + Metadata: pkg.PythonPoetryLockEntry{ + Dependencies: []pkg.PythonPoetryLockDependencyEntry{ + { + Name: "bar", + Version: "1.2.3", + Optional: true, + Markers: "extra == 'baz'", + }, + }, + // note: there is no "baz" extra defined + }, + }, + want: dependency.Specification{ + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"foo"}, + Requires: nil, // no requirements for non-required extra + }, + }, + }, + { + name: "package with extra", + p: pkg.Package{ + Name: "foo", + Metadata: pkg.PythonPoetryLockEntry{ + Dependencies: []pkg.PythonPoetryLockDependencyEntry{ + { + Name: "bar", // note: we NEVER reference this, the extras section is the source of truth here + Version: "1.2.3", + Optional: true, + Markers: "extra == 'baz'", + }, + }, + Extras: []pkg.PythonPoetryLockExtraEntry{ + { + Name: "baz", + Dependencies: []string{ + "qux", + }, + }, + }, + }, + }, + want: dependency.Specification{ + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"foo"}, + Requires: nil, // no requirements for non-required extra + }, + Variants: []dependency.ProvidesRequires{ + { + Provides: []string{"foo[baz]"}, + Requires: []string{"qux"}, + }, + }, + }, + }, + { + name: "package using extra", + p: pkg.Package{ + Name: "foo", + Metadata: pkg.PythonPoetryLockEntry{ + Dependencies: []pkg.PythonPoetryLockDependencyEntry{ + { + Name: "starlette", + Version: ">=0.37.2,<0.38.0", + }, + { + Name: "bar", + Version: "1.2.3", + Extras: []string{"standard", "things"}, // note multiple extras needed when installing + }, + }, + Extras: []pkg.PythonPoetryLockExtraEntry{ + { + Name: "baz", + Dependencies: []string{ + "qux (>=2.0.0)", // should strip version constraint + }, + }, + }, + }, + }, + want: dependency.Specification{ + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"foo"}, + Requires: []string{ + "starlette", + // note: we break out the package and extra requirements separately + // and extras are never combined + "bar", + "bar[standard]", + "bar[things]", + }, + }, + Variants: []dependency.ProvidesRequires{ + { + Provides: []string{"foo[baz]"}, + Requires: []string{"qux"}, + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.want, poetryLockDependencySpecifier(tt.p)) + }) + } +} + +func Test_poetryLockDependencySpecifier_againstPoetryLock(t *testing.T) { + tests := []struct { + name string + fixture string + want []dependency.Specification + }{ + { + name: "simple dependencies with extras", + fixture: "test-fixtures/poetry/simple-deps/poetry.lock", + want: []dependency.Specification{ + { + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"certifi"}, + }, + }, + { + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"charset-normalizer"}, + }, + }, + { + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"idna"}, + }, + }, + { + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"requests"}, + Requires: []string{"certifi", "charset-normalizer", "idna", "urllib3"}, + }, + Variants: []dependency.ProvidesRequires{ + { + Provides: []string{"requests[socks]"}, + Requires: []string{"PySocks"}, + }, + { + Provides: []string{"requests[use-chardet-on-py3]"}, + Requires: []string{"chardet"}, + }, + }, + }, + { + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"urllib3"}, + }, + Variants: []dependency.ProvidesRequires{ + { + Provides: []string{"urllib3[brotli]"}, + Requires: []string{"brotli", "brotlicffi"}, + }, + { + Provides: []string{"urllib3[h2]"}, + Requires: []string{"h2"}}, + { + Provides: []string{"urllib3[socks]"}, + Requires: []string{"pysocks"}, + }, + { + Provides: []string{"urllib3[zstd]"}, + Requires: []string{"zstandard"}, + }, + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fh, err := os.Open(tt.fixture) + require.NoError(t, err) + + pkgs, err := poetryLockPackages(file.NewLocationReadCloser(file.NewLocation(tt.fixture), fh)) + require.NoError(t, err) + + var got []dependency.Specification + for _, p := range pkgs { + got = append(got, poetryLockDependencySpecifier(p)) + } + + if d := cmp.Diff(tt.want, got); d != "" { + t.Errorf("wrong result (-want +got):\n%s", d) + } + }) + } +} diff --git a/syft/pkg/cataloger/python/parse_poetry_lock.go b/syft/pkg/cataloger/python/parse_poetry_lock.go index dd7660efd..dbc702d53 100644 --- a/syft/pkg/cataloger/python/parse_poetry_lock.go +++ b/syft/pkg/cataloger/python/parse_poetry_lock.go @@ -3,6 +3,8 @@ package python import ( "context" "fmt" + "sort" + "strings" "github.com/pelletier/go-toml" @@ -10,6 +12,7 @@ import ( "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/generic" + "github.com/anchore/syft/syft/pkg/cataloger/internal/dependency" ) // integrity check @@ -20,48 +23,144 @@ type poetryPackageSource struct { } type poetryPackages struct { - Packages []struct { - Name string `toml:"name"` - Version string `toml:"version"` - Category string `toml:"category"` - Description string `toml:"description"` - Optional bool `toml:"optional"` - Source poetryPackageSource `toml:"source"` - } `toml:"package"` + Packages []poetryPackage `toml:"package"` +} + +type poetryPackage struct { + Name string `toml:"name"` + Version string `toml:"version"` + Category string `toml:"category"` + Description string `toml:"description"` + Optional bool `toml:"optional"` + Source poetryPackageSource `toml:"source"` + Dependencies map[string]poetryPackageDependency `toml:"dependencies"` + Extras map[string][]string `toml:"extras"` +} + +type poetryPackageDependency struct { + Version string `toml:"version"` + Markers string `toml:"markers"` + Optional bool `toml:"optional"` + Extras []string `toml:"extras"` +} + +func (d *poetryPackageDependency) UnmarshalText(data []byte) error { + // attempt to parse as a map first + var dep map[string]interface{} + if err := toml.Unmarshal(data, &dep); err == nil { + if extras, ok := dep["extras"]; ok { + if extrasList, ok := extras.([]string); ok { + d.Extras = extrasList + } + } + + if markers, ok := dep["markers"]; ok { + if markersString, ok := markers.(string); ok { + d.Markers = markersString + } + } + + if version, ok := dep["version"]; ok { + if versionString, ok := version.(string); ok { + d.Version = versionString + } + } + return nil + } + + if strings.ContainsAny(string(data), "[]{}") { + // odds are this is really a malformed toml array or object + return fmt.Errorf("unable to parse poetry dependency: version is malformed array/object: %q", string(data)) + } + + // assume this is a simple version string + d.Version = string(data) + + return nil } // parsePoetryLock is a parser function for poetry.lock contents, returning all python packages discovered. func parsePoetryLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { + pkgs, err := poetryLockPackages(reader) + if err != nil { + return nil, nil, err + } + + // since we would never expect to create relationships for packages across multiple poetry.lock files + // we should do this on a file parser level (each poetry.lock) instead of a cataloger level (across all + // poetry.lock files) + return pkgs, dependency.Resolve(poetryLockDependencySpecifier, pkgs), nil +} + +func poetryLockPackages(reader file.LocationReadCloser) ([]pkg.Package, error) { tree, err := toml.LoadReader(reader) if err != nil { - return nil, nil, fmt.Errorf("unable to load poetry.lock for parsing: %w", err) + return nil, fmt.Errorf("unable to load poetry.lock for parsing: %w", err) } metadata := poetryPackages{} err = tree.Unmarshal(&metadata) if err != nil { - return nil, nil, fmt.Errorf("unable to parse poetry.lock: %w", err) + return nil, fmt.Errorf("unable to parse poetry.lock: %w", err) } var pkgs []pkg.Package for _, p := range metadata.Packages { - var index string - if p.Source.URL != "" { - index = p.Source.URL - } else { - // https://python-poetry.org/docs/repositories/ - index = "https://pypi.org/simple" - } pkgs = append( pkgs, newPackageForIndexWithMetadata( p.Name, p.Version, - pkg.PythonPoetryLockEntry{Index: index}, + newPythonPoetryLockEntry(p), reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) } + return pkgs, nil +} + +func newPythonPoetryLockEntry(p poetryPackage) pkg.PythonPoetryLockEntry { + return pkg.PythonPoetryLockEntry{ + Index: extractIndex(p), + Dependencies: extractPoetryDependencies(p), + Extras: extractPoetryExtras(p), + } +} + +func extractIndex(p poetryPackage) string { + if p.Source.URL != "" { + return p.Source.URL + } + // https://python-poetry.org/docs/repositories/ + return "https://pypi.org/simple" +} - return pkgs, nil, nil +func extractPoetryDependencies(p poetryPackage) []pkg.PythonPoetryLockDependencyEntry { + var deps []pkg.PythonPoetryLockDependencyEntry + for name, dep := range p.Dependencies { + deps = append(deps, pkg.PythonPoetryLockDependencyEntry{ + Name: name, + Version: dep.Version, + Extras: dep.Extras, + Markers: dep.Markers, + }) + } + sort.Slice(deps, func(i, j int) bool { + return deps[i].Name < deps[j].Name + }) + return deps +} + +func extractPoetryExtras(p poetryPackage) []pkg.PythonPoetryLockExtraEntry { + var extras []pkg.PythonPoetryLockExtraEntry + for name, deps := range p.Extras { + extras = append(extras, pkg.PythonPoetryLockExtraEntry{ + Name: name, + Dependencies: deps, + }) + } + sort.Slice(extras, func(i, j int) bool { + return extras[i].Name < extras[j].Name + }) + return extras } diff --git a/syft/pkg/cataloger/python/parse_poetry_lock_test.go b/syft/pkg/cataloger/python/parse_poetry_lock_test.go index 6cc20504f..b590be47f 100644 --- a/syft/pkg/cataloger/python/parse_poetry_lock_test.go +++ b/syft/pkg/cataloger/python/parse_poetry_lock_test.go @@ -10,7 +10,7 @@ import ( ) func TestParsePoetryLock(t *testing.T) { - fixture := "test-fixtures/poetry/poetry.lock" + fixture := "test-fixtures/poetry/dev-deps/poetry.lock" locations := file.NewLocationSet(file.NewLocation(fixture)) expectedPkgs := []pkg.Package{ { @@ -20,7 +20,29 @@ func TestParsePoetryLock(t *testing.T) { Locations: locations, Language: pkg.Python, Type: pkg.PythonPkg, - Metadata: pkg.PythonPoetryLockEntry{Index: "https://test.pypi.org/simple"}, + Metadata: pkg.PythonPoetryLockEntry{ + Index: "https://test.pypi.org/simple", + Dependencies: []pkg.PythonPoetryLockDependencyEntry{ + {Name: "docutils", Version: "*"}, + {Name: "natsort", Version: "*"}, + {Name: "six", Version: "*"}, + {Name: "sphinx", Version: "*"}, + }, + Extras: []pkg.PythonPoetryLockExtraEntry{ + { + Name: "deploy", + Dependencies: []string{"bumpversion", "twine", "wheel"}, + }, + { + Name: "docs", + Dependencies: []string{"sphinx", "sphinx-rtd-theme"}, + }, + { + Name: "test", + Dependencies: []string{"pytest", "pytest-cov", "coveralls", "beautifulsoup4", "hypothesis"}, + }, + }, + }, }, { Name: "alabaster", @@ -51,7 +73,6 @@ func TestParsePoetryLock(t *testing.T) { }, } - // TODO: relationships are not under test var expectedRelationships []artifact.Relationship pkgtest.TestFileParser(t, fixture, parsePoetryLock, expectedPkgs, expectedRelationships) diff --git a/syft/pkg/cataloger/python/test-fixtures/poetry/conflicting-with-extras/poetry.lock b/syft/pkg/cataloger/python/test-fixtures/poetry/conflicting-with-extras/poetry.lock new file mode 100644 index 000000000..a6a43fc44 --- /dev/null +++ b/syft/pkg/cataloger/python/test-fixtures/poetry/conflicting-with-extras/poetry.lock @@ -0,0 +1,444 @@ +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. + +[[package]] +name = "anyio" +version = "4.3.0" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.8" +files = [ + {file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"}, + {file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"}, +] + +[package.dependencies] +idna = ">=2.8" +sniffio = ">=1.1" + +[package.extras] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.23)"] + +[[package]] +name = "brotli" +version = "1.1.0" +description = "Python bindings for the Brotli compression library" +optional = false +python-versions = "*" +files = [ + {file = "Brotli-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e1140c64812cb9b06c922e77f1c26a75ec5e3f0fb2bf92cc8c58720dec276752"}, + {file = "Brotli-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8fd5270e906eef71d4a8d19b7c6a43760c6abcfcc10c9101d14eb2357418de9"}, + {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ae56aca0402a0f9a3431cddda62ad71666ca9d4dc3a10a142b9dce2e3c0cda3"}, + {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43ce1b9935bfa1ede40028054d7f48b5469cd02733a365eec8a329ffd342915d"}, + {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7c4855522edb2e6ae7fdb58e07c3ba9111e7621a8956f481c68d5d979c93032e"}, + {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:38025d9f30cf4634f8309c6874ef871b841eb3c347e90b0851f63d1ded5212da"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e6a904cb26bfefc2f0a6f240bdf5233be78cd2488900a2f846f3c3ac8489ab80"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a37b8f0391212d29b3a91a799c8e4a2855e0576911cdfb2515487e30e322253d"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e84799f09591700a4154154cab9787452925578841a94321d5ee8fb9a9a328f0"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f66b5337fa213f1da0d9000bc8dc0cb5b896b726eefd9c6046f699b169c41b9e"}, + {file = "Brotli-1.1.0-cp310-cp310-win32.whl", hash = "sha256:be36e3d172dc816333f33520154d708a2657ea63762ec16b62ece02ab5e4daf2"}, + {file = "Brotli-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:0c6244521dda65ea562d5a69b9a26120769b7a9fb3db2fe9545935ed6735b128"}, + {file = "Brotli-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a3daabb76a78f829cafc365531c972016e4aa8d5b4bf60660ad8ecee19df7ccc"}, + {file = "Brotli-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c8146669223164fc87a7e3de9f81e9423c67a79d6b3447994dfb9c95da16e2d6"}, + {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30924eb4c57903d5a7526b08ef4a584acc22ab1ffa085faceb521521d2de32dd"}, + {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ceb64bbc6eac5a140ca649003756940f8d6a7c444a68af170b3187623b43bebf"}, + {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a469274ad18dc0e4d316eefa616d1d0c2ff9da369af19fa6f3daa4f09671fd61"}, + {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:524f35912131cc2cabb00edfd8d573b07f2d9f21fa824bd3fb19725a9cf06327"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5b3cc074004d968722f51e550b41a27be656ec48f8afaeeb45ebf65b561481dd"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a1fd8a29719ccce974d523580987b7f8229aeace506952fa9ce1d53a033873c8"}, + {file = "Brotli-1.1.0-cp311-cp311-win32.whl", hash = "sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50"}, + {file = "Brotli-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1"}, + {file = "Brotli-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409"}, + {file = "Brotli-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2"}, + {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451"}, + {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91"}, + {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408"}, + {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966"}, + {file = "Brotli-1.1.0-cp312-cp312-win32.whl", hash = "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0"}, + {file = "Brotli-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951"}, + {file = "Brotli-1.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a090ca607cbb6a34b0391776f0cb48062081f5f60ddcce5d11838e67a01928d1"}, + {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2de9d02f5bda03d27ede52e8cfe7b865b066fa49258cbab568720aa5be80a47d"}, + {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2333e30a5e00fe0fe55903c8832e08ee9c3b1382aacf4db26664a16528d51b4b"}, + {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4d4a848d1837973bf0f4b5e54e3bec977d99be36a7895c61abb659301b02c112"}, + {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:fdc3ff3bfccdc6b9cc7c342c03aa2400683f0cb891d46e94b64a197910dc4064"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:5eeb539606f18a0b232d4ba45adccde4125592f3f636a6182b4a8a436548b914"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:fd5f17ff8f14003595ab414e45fce13d073e0762394f957182e69035c9f3d7c2"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:069a121ac97412d1fe506da790b3e69f52254b9df4eb665cd42460c837193354"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e93dfc1a1165e385cc8239fab7c036fb2cd8093728cbd85097b284d7b99249a2"}, + {file = "Brotli-1.1.0-cp36-cp36m-win32.whl", hash = "sha256:a599669fd7c47233438a56936988a2478685e74854088ef5293802123b5b2460"}, + {file = "Brotli-1.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:d143fd47fad1db3d7c27a1b1d66162e855b5d50a89666af46e1679c496e8e579"}, + {file = "Brotli-1.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:11d00ed0a83fa22d29bc6b64ef636c4552ebafcef57154b4ddd132f5638fbd1c"}, + {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f733d788519c7e3e71f0855c96618720f5d3d60c3cb829d8bbb722dddce37985"}, + {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:929811df5462e182b13920da56c6e0284af407d1de637d8e536c5cd00a7daf60"}, + {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b63b949ff929fbc2d6d3ce0e924c9b93c9785d877a21a1b678877ffbbc4423a"}, + {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d192f0f30804e55db0d0e0a35d83a9fead0e9a359a9ed0285dbacea60cc10a84"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f296c40e23065d0d6650c4aefe7470d2a25fffda489bcc3eb66083f3ac9f6643"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:919e32f147ae93a09fe064d77d5ebf4e35502a8df75c29fb05788528e330fe74"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:23032ae55523cc7bccb4f6a0bf368cd25ad9bcdcc1990b64a647e7bbcce9cb5b"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:224e57f6eac61cc449f498cc5f0e1725ba2071a3d4f48d5d9dffba42db196438"}, + {file = "Brotli-1.1.0-cp37-cp37m-win32.whl", hash = "sha256:587ca6d3cef6e4e868102672d3bd9dc9698c309ba56d41c2b9c85bbb903cdb95"}, + {file = "Brotli-1.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2954c1c23f81c2eaf0b0717d9380bd348578a94161a65b3a2afc62c86467dd68"}, + {file = "Brotli-1.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:efa8b278894b14d6da122a72fefcebc28445f2d3f880ac59d46c90f4c13be9a3"}, + {file = "Brotli-1.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:03d20af184290887bdea3f0f78c4f737d126c74dc2f3ccadf07e54ceca3bf208"}, + {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6172447e1b368dcbc458925e5ddaf9113477b0ed542df258d84fa28fc45ceea7"}, + {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a743e5a28af5f70f9c080380a5f908d4d21d40e8f0e0c8901604d15cfa9ba751"}, + {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0541e747cce78e24ea12d69176f6a7ddb690e62c425e01d31cc065e69ce55b48"}, + {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cdbc1fc1bc0bff1cef838eafe581b55bfbffaed4ed0318b724d0b71d4d377619"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:890b5a14ce214389b2cc36ce82f3093f96f4cc730c1cffdbefff77a7c71f2a97"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ab4fbee0b2d9098c74f3057b2bc055a8bd92ccf02f65944a241b4349229185a"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:141bd4d93984070e097521ed07e2575b46f817d08f9fa42b16b9b5f27b5ac088"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fce1473f3ccc4187f75b4690cfc922628aed4d3dd013d047f95a9b3919a86596"}, + {file = "Brotli-1.1.0-cp38-cp38-win32.whl", hash = "sha256:db85ecf4e609a48f4b29055f1e144231b90edc90af7481aa731ba2d059226b1b"}, + {file = "Brotli-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3d7954194c36e304e1523f55d7042c59dc53ec20dd4e9ea9d151f1b62b4415c0"}, + {file = "Brotli-1.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5fb2ce4b8045c78ebbc7b8f3c15062e435d47e7393cc57c25115cfd49883747a"}, + {file = "Brotli-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7905193081db9bfa73b1219140b3d315831cbff0d8941f22da695832f0dd188f"}, + {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a77def80806c421b4b0af06f45d65a136e7ac0bdca3c09d9e2ea4e515367c7e9"}, + {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dadd1314583ec0bf2d1379f7008ad627cd6336625d6679cf2f8e67081b83acf"}, + {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:901032ff242d479a0efa956d853d16875d42157f98951c0230f69e69f9c09bac"}, + {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:22fc2a8549ffe699bfba2256ab2ed0421a7b8fadff114a3d201794e45a9ff578"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ae15b066e5ad21366600ebec29a7ccbc86812ed267e4b28e860b8ca16a2bc474"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:949f3b7c29912693cee0afcf09acd6ebc04c57af949d9bf77d6101ebb61e388c"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:89f4988c7203739d48c6f806f1e87a1d96e0806d44f0fba61dba81392c9e474d"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:de6551e370ef19f8de1807d0a9aa2cdfdce2e85ce88b122fe9f6b2b076837e59"}, + {file = "Brotli-1.1.0-cp39-cp39-win32.whl", hash = "sha256:f0d8a7a6b5983c2496e364b969f0e526647a06b075d034f3297dc66f3b360c64"}, + {file = "Brotli-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:cdad5b9014d83ca68c25d2e9444e28e967ef16e80f6b436918c700c117a85467"}, + {file = "Brotli-1.1.0.tar.gz", hash = "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724"}, +] + +[[package]] +name = "brotlicffi" +version = "1.1.0.0" +description = "Python CFFI bindings to the Brotli library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "brotlicffi-1.1.0.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9b7ae6bd1a3f0df532b6d67ff674099a96d22bc0948955cb338488c31bfb8851"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19ffc919fa4fc6ace69286e0a23b3789b4219058313cf9b45625016bf7ff996b"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9feb210d932ffe7798ee62e6145d3a757eb6233aa9a4e7db78dd3690d7755814"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84763dbdef5dd5c24b75597a77e1b30c66604725707565188ba54bab4f114820"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-win32.whl", hash = "sha256:1b12b50e07c3911e1efa3a8971543e7648100713d4e0971b13631cce22c587eb"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:994a4f0681bb6c6c3b0925530a1926b7a189d878e6e5e38fae8efa47c5d9c613"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2e4aeb0bd2540cb91b069dbdd54d458da8c4334ceaf2d25df2f4af576d6766ca"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b7b0033b0d37bb33009fb2fef73310e432e76f688af76c156b3594389d81391"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54a07bb2374a1eba8ebb52b6fafffa2afd3c4df85ddd38fcc0511f2bb387c2a8"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7901a7dc4b88f1c1475de59ae9be59799db1007b7d059817948d8e4f12e24e35"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ce01c7316aebc7fce59da734286148b1d1b9455f89cf2c8a4dfce7d41db55c2d"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:246f1d1a90279bb6069de3de8d75a8856e073b8ff0b09dcca18ccc14cec85979"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc4bc5d82bc56ebd8b514fb8350cfac4627d6b0743382e46d033976a5f80fab6"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37c26ecb14386a44b118ce36e546ce307f4810bc9598a6e6cb4f7fca725ae7e6"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca72968ae4eaf6470498d5c2887073f7efe3b1e7d7ec8be11a06a79cc810e990"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:add0de5b9ad9e9aa293c3aa4e9deb2b61e99ad6c1634e01d01d98c03e6a354cc"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9b6068e0f3769992d6b622a1cd2e7835eae3cf8d9da123d7f51ca9c1e9c333e5"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8557a8559509b61e65083f8782329188a250102372576093c88930c875a69838"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a7ae37e5d79c5bdfb5b4b99f2715a6035e6c5bf538c3746abc8e26694f92f33"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391151ec86bb1c683835980f4816272a87eaddc46bb91cbf44f62228b84d8cca"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:2f3711be9290f0453de8eed5275d93d286abe26b08ab4a35d7452caa1fef532f"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1a807d760763e398bbf2c6394ae9da5815901aa93ee0a37bca5efe78d4ee3171"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa8ca0623b26c94fccc3a1fdd895be1743b838f3917300506d04aa3346fd2a14"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3de0cf28a53a3238b252aca9fed1593e9d36c1d116748013339f0949bfc84112"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6be5ec0e88a4925c91f3dea2bb0013b3a2accda6f77238f76a34a1ea532a1cb0"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d9eb71bb1085d996244439154387266fd23d6ad37161f6f52f1cd41dd95a3808"}, + {file = "brotlicffi-1.1.0.0.tar.gz", hash = "sha256:b77827a689905143f87915310b93b273ab17888fd43ef350d4832c4a71083c13"}, +] + +[package.dependencies] +cffi = ">=1.0.0" + +[[package]] +name = "certifi" +version = "2024.2.2" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, +] + +[[package]] +name = "cffi" +version = "1.16.0" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, + {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, + {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, + {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, + {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, + {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, + {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, + {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, + {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, + {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, + {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, + {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, + {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, + {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, +] + +[package.dependencies] +pycparser = "*" + +[[package]] +name = "click" +version = "7.1.2" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, + {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, +] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[[package]] +name = "h2" +version = "4.1.0" +description = "HTTP/2 State-Machine based protocol implementation" +optional = false +python-versions = ">=3.6.1" +files = [ + {file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"}, + {file = "h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb"}, +] + +[package.dependencies] +hpack = ">=4.0,<5" +hyperframe = ">=6.0,<7" + +[[package]] +name = "hpack" +version = "4.0.0" +description = "Pure-Python HPACK header compression" +optional = false +python-versions = ">=3.6.1" +files = [ + {file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"}, + {file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"}, +] + +[[package]] +name = "httpcore" +version = "1.0.5" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, + {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, +] + +[package.dependencies] +certifi = "*" +h11 = ">=0.13,<0.15" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<0.26.0)"] + +[[package]] +name = "httpx" +version = "0.27.0" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, + {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, +] + +[package.dependencies] +anyio = "*" +brotli = {version = "*", optional = true, markers = "platform_python_implementation == \"CPython\" and extra == \"brotli\""} +brotlicffi = {version = "*", optional = true, markers = "platform_python_implementation != \"CPython\" and extra == \"brotli\""} +certifi = "*" +h2 = {version = ">=3,<5", optional = true, markers = "extra == \"http2\""} +httpcore = "==1.*" +idna = "*" +sniffio = "*" +socksio = {version = "==1.*", optional = true, markers = "extra == \"socks\""} + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] + +[[package]] +name = "hyperframe" +version = "6.0.1" +description = "HTTP/2 framing layer for Python" +optional = false +python-versions = ">=3.6.1" +files = [ + {file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"}, + {file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"}, +] + +[[package]] +name = "idna" +version = "3.7" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, + {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, +] + +[[package]] +name = "pprintpp" +version = "0.4.0" +description = "A drop-in replacement for pprint that's actually pretty" +optional = false +python-versions = "*" +files = [ + {file = "pprintpp-0.4.0-py2.py3-none-any.whl", hash = "sha256:b6b4dcdd0c0c0d75e4d7b2f21a9e933e5b2ce62b26e1a54537f9651ae5a5c01d"}, + {file = "pprintpp-0.4.0.tar.gz", hash = "sha256:ea826108e2c7f49dc6d66c752973c3fc9749142a798d6b254e1e301cfdbc6403"}, +] + +[[package]] +name = "pycparser" +version = "2.22" +description = "C parser in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, +] + +[[package]] +name = "pygments" +version = "1.6" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = "*" +files = [ + {file = "Pygments-1.6.tar.gz", hash = "sha256:799ed4caf77516e54440806d8d9cd82a7607dfdf4e4fb643815171a4b5c921c0"}, +] + +[[package]] +name = "rich" +version = "0.3.3" +description = "Render rich text, tables, syntax highlighting, markdown and more to the terminal" +optional = false +python-versions = ">=3.6,<4.0" +files = [ + {file = "rich-0.3.3-py3-none-any.whl", hash = "sha256:04f1016b1aba52499104b594c17b1481504bbc7314f8b9ba1a7a9dbf3e8869c4"}, + {file = "rich-0.3.3.tar.gz", hash = "sha256:604edf76a2a7d40c7ecc9af5ae41cee3da3e99532c8d0aa54cc42e017ee7f63a"}, +] + +[package.dependencies] +colorama = ">=0.4.3,<0.5.0" +pprintpp = ">=0.4.0,<0.5.0" +typing-extensions = ">=3.7.4,<4.0.0" + +[[package]] +name = "sniffio" +version = "1.3.1" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, +] + +[[package]] +name = "socksio" +version = "1.0.0" +description = "Sans-I/O implementation of SOCKS4, SOCKS4A, and SOCKS5." +optional = false +python-versions = ">=3.6" +files = [ + {file = "socksio-1.0.0-py3-none-any.whl", hash = "sha256:95dc1f15f9b34e8d7b16f06d74b8ccf48f609af32ab33c608d08761c5dcbb1f3"}, + {file = "socksio-1.0.0.tar.gz", hash = "sha256:f88beb3da5b5c38b9890469de67d0cb0f9d494b78b106ca1845f96c10b91c4ac"}, +] + +[[package]] +name = "typing-extensions" +version = "3.10.0.2" +description = "Backported and Experimental Type Hints for Python 3.5+" +optional = false +python-versions = "*" +files = [ + {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"}, + {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"}, + {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.11" +content-hash = "a08ffc499b736c19f960d9ba247325d94852c779f10b31ce49976d263e87b24e" diff --git a/syft/pkg/cataloger/python/test-fixtures/poetry/conflicting-with-extras/pyproject.toml b/syft/pkg/cataloger/python/test-fixtures/poetry/conflicting-with-extras/pyproject.toml new file mode 100644 index 000000000..c80a6fb76 --- /dev/null +++ b/syft/pkg/cataloger/python/test-fixtures/poetry/conflicting-with-extras/pyproject.toml @@ -0,0 +1,17 @@ +[tool.poetry] +name = "testpkg" +version = "0.1.0" +description = "" +authors = ["Alex Goodman "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.11" +httpx = {extras = ["brotli", "http2", "socks"], version = "^0.27.0"} +pygments = "1.6" +click = "<8" +rich = "<10" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/syft/pkg/cataloger/python/test-fixtures/poetry/poetry.lock b/syft/pkg/cataloger/python/test-fixtures/poetry/dev-deps/poetry.lock similarity index 100% rename from syft/pkg/cataloger/python/test-fixtures/poetry/poetry.lock rename to syft/pkg/cataloger/python/test-fixtures/poetry/dev-deps/poetry.lock diff --git a/syft/pkg/cataloger/python/test-fixtures/poetry/multiple-extras/poetry.lock b/syft/pkg/cataloger/python/test-fixtures/poetry/multiple-extras/poetry.lock new file mode 100644 index 000000000..cd523e117 --- /dev/null +++ b/syft/pkg/cataloger/python/test-fixtures/poetry/multiple-extras/poetry.lock @@ -0,0 +1,373 @@ +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. + +[[package]] +name = "anyio" +version = "4.3.0" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.8" +files = [ + {file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"}, + {file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"}, +] + +[package.dependencies] +idna = ">=2.8" +sniffio = ">=1.1" + +[package.extras] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.23)"] + +[[package]] +name = "brotli" +version = "1.1.0" +description = "Python bindings for the Brotli compression library" +optional = false +python-versions = "*" +files = [ + {file = "Brotli-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e1140c64812cb9b06c922e77f1c26a75ec5e3f0fb2bf92cc8c58720dec276752"}, + {file = "Brotli-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8fd5270e906eef71d4a8d19b7c6a43760c6abcfcc10c9101d14eb2357418de9"}, + {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ae56aca0402a0f9a3431cddda62ad71666ca9d4dc3a10a142b9dce2e3c0cda3"}, + {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43ce1b9935bfa1ede40028054d7f48b5469cd02733a365eec8a329ffd342915d"}, + {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7c4855522edb2e6ae7fdb58e07c3ba9111e7621a8956f481c68d5d979c93032e"}, + {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:38025d9f30cf4634f8309c6874ef871b841eb3c347e90b0851f63d1ded5212da"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e6a904cb26bfefc2f0a6f240bdf5233be78cd2488900a2f846f3c3ac8489ab80"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a37b8f0391212d29b3a91a799c8e4a2855e0576911cdfb2515487e30e322253d"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e84799f09591700a4154154cab9787452925578841a94321d5ee8fb9a9a328f0"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f66b5337fa213f1da0d9000bc8dc0cb5b896b726eefd9c6046f699b169c41b9e"}, + {file = "Brotli-1.1.0-cp310-cp310-win32.whl", hash = "sha256:be36e3d172dc816333f33520154d708a2657ea63762ec16b62ece02ab5e4daf2"}, + {file = "Brotli-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:0c6244521dda65ea562d5a69b9a26120769b7a9fb3db2fe9545935ed6735b128"}, + {file = "Brotli-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a3daabb76a78f829cafc365531c972016e4aa8d5b4bf60660ad8ecee19df7ccc"}, + {file = "Brotli-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c8146669223164fc87a7e3de9f81e9423c67a79d6b3447994dfb9c95da16e2d6"}, + {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30924eb4c57903d5a7526b08ef4a584acc22ab1ffa085faceb521521d2de32dd"}, + {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ceb64bbc6eac5a140ca649003756940f8d6a7c444a68af170b3187623b43bebf"}, + {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a469274ad18dc0e4d316eefa616d1d0c2ff9da369af19fa6f3daa4f09671fd61"}, + {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:524f35912131cc2cabb00edfd8d573b07f2d9f21fa824bd3fb19725a9cf06327"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5b3cc074004d968722f51e550b41a27be656ec48f8afaeeb45ebf65b561481dd"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a1fd8a29719ccce974d523580987b7f8229aeace506952fa9ce1d53a033873c8"}, + {file = "Brotli-1.1.0-cp311-cp311-win32.whl", hash = "sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50"}, + {file = "Brotli-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1"}, + {file = "Brotli-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409"}, + {file = "Brotli-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2"}, + {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451"}, + {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91"}, + {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408"}, + {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966"}, + {file = "Brotli-1.1.0-cp312-cp312-win32.whl", hash = "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0"}, + {file = "Brotli-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951"}, + {file = "Brotli-1.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a090ca607cbb6a34b0391776f0cb48062081f5f60ddcce5d11838e67a01928d1"}, + {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2de9d02f5bda03d27ede52e8cfe7b865b066fa49258cbab568720aa5be80a47d"}, + {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2333e30a5e00fe0fe55903c8832e08ee9c3b1382aacf4db26664a16528d51b4b"}, + {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4d4a848d1837973bf0f4b5e54e3bec977d99be36a7895c61abb659301b02c112"}, + {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:fdc3ff3bfccdc6b9cc7c342c03aa2400683f0cb891d46e94b64a197910dc4064"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:5eeb539606f18a0b232d4ba45adccde4125592f3f636a6182b4a8a436548b914"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:fd5f17ff8f14003595ab414e45fce13d073e0762394f957182e69035c9f3d7c2"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:069a121ac97412d1fe506da790b3e69f52254b9df4eb665cd42460c837193354"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e93dfc1a1165e385cc8239fab7c036fb2cd8093728cbd85097b284d7b99249a2"}, + {file = "Brotli-1.1.0-cp36-cp36m-win32.whl", hash = "sha256:a599669fd7c47233438a56936988a2478685e74854088ef5293802123b5b2460"}, + {file = "Brotli-1.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:d143fd47fad1db3d7c27a1b1d66162e855b5d50a89666af46e1679c496e8e579"}, + {file = "Brotli-1.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:11d00ed0a83fa22d29bc6b64ef636c4552ebafcef57154b4ddd132f5638fbd1c"}, + {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f733d788519c7e3e71f0855c96618720f5d3d60c3cb829d8bbb722dddce37985"}, + {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:929811df5462e182b13920da56c6e0284af407d1de637d8e536c5cd00a7daf60"}, + {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b63b949ff929fbc2d6d3ce0e924c9b93c9785d877a21a1b678877ffbbc4423a"}, + {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d192f0f30804e55db0d0e0a35d83a9fead0e9a359a9ed0285dbacea60cc10a84"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f296c40e23065d0d6650c4aefe7470d2a25fffda489bcc3eb66083f3ac9f6643"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:919e32f147ae93a09fe064d77d5ebf4e35502a8df75c29fb05788528e330fe74"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:23032ae55523cc7bccb4f6a0bf368cd25ad9bcdcc1990b64a647e7bbcce9cb5b"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:224e57f6eac61cc449f498cc5f0e1725ba2071a3d4f48d5d9dffba42db196438"}, + {file = "Brotli-1.1.0-cp37-cp37m-win32.whl", hash = "sha256:587ca6d3cef6e4e868102672d3bd9dc9698c309ba56d41c2b9c85bbb903cdb95"}, + {file = "Brotli-1.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2954c1c23f81c2eaf0b0717d9380bd348578a94161a65b3a2afc62c86467dd68"}, + {file = "Brotli-1.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:efa8b278894b14d6da122a72fefcebc28445f2d3f880ac59d46c90f4c13be9a3"}, + {file = "Brotli-1.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:03d20af184290887bdea3f0f78c4f737d126c74dc2f3ccadf07e54ceca3bf208"}, + {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6172447e1b368dcbc458925e5ddaf9113477b0ed542df258d84fa28fc45ceea7"}, + {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a743e5a28af5f70f9c080380a5f908d4d21d40e8f0e0c8901604d15cfa9ba751"}, + {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0541e747cce78e24ea12d69176f6a7ddb690e62c425e01d31cc065e69ce55b48"}, + {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cdbc1fc1bc0bff1cef838eafe581b55bfbffaed4ed0318b724d0b71d4d377619"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:890b5a14ce214389b2cc36ce82f3093f96f4cc730c1cffdbefff77a7c71f2a97"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ab4fbee0b2d9098c74f3057b2bc055a8bd92ccf02f65944a241b4349229185a"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:141bd4d93984070e097521ed07e2575b46f817d08f9fa42b16b9b5f27b5ac088"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fce1473f3ccc4187f75b4690cfc922628aed4d3dd013d047f95a9b3919a86596"}, + {file = "Brotli-1.1.0-cp38-cp38-win32.whl", hash = "sha256:db85ecf4e609a48f4b29055f1e144231b90edc90af7481aa731ba2d059226b1b"}, + {file = "Brotli-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3d7954194c36e304e1523f55d7042c59dc53ec20dd4e9ea9d151f1b62b4415c0"}, + {file = "Brotli-1.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5fb2ce4b8045c78ebbc7b8f3c15062e435d47e7393cc57c25115cfd49883747a"}, + {file = "Brotli-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7905193081db9bfa73b1219140b3d315831cbff0d8941f22da695832f0dd188f"}, + {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a77def80806c421b4b0af06f45d65a136e7ac0bdca3c09d9e2ea4e515367c7e9"}, + {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dadd1314583ec0bf2d1379f7008ad627cd6336625d6679cf2f8e67081b83acf"}, + {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:901032ff242d479a0efa956d853d16875d42157f98951c0230f69e69f9c09bac"}, + {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:22fc2a8549ffe699bfba2256ab2ed0421a7b8fadff114a3d201794e45a9ff578"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ae15b066e5ad21366600ebec29a7ccbc86812ed267e4b28e860b8ca16a2bc474"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:949f3b7c29912693cee0afcf09acd6ebc04c57af949d9bf77d6101ebb61e388c"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:89f4988c7203739d48c6f806f1e87a1d96e0806d44f0fba61dba81392c9e474d"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:de6551e370ef19f8de1807d0a9aa2cdfdce2e85ce88b122fe9f6b2b076837e59"}, + {file = "Brotli-1.1.0-cp39-cp39-win32.whl", hash = "sha256:f0d8a7a6b5983c2496e364b969f0e526647a06b075d034f3297dc66f3b360c64"}, + {file = "Brotli-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:cdad5b9014d83ca68c25d2e9444e28e967ef16e80f6b436918c700c117a85467"}, + {file = "Brotli-1.1.0.tar.gz", hash = "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724"}, +] + +[[package]] +name = "brotlicffi" +version = "1.1.0.0" +description = "Python CFFI bindings to the Brotli library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "brotlicffi-1.1.0.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9b7ae6bd1a3f0df532b6d67ff674099a96d22bc0948955cb338488c31bfb8851"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19ffc919fa4fc6ace69286e0a23b3789b4219058313cf9b45625016bf7ff996b"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9feb210d932ffe7798ee62e6145d3a757eb6233aa9a4e7db78dd3690d7755814"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84763dbdef5dd5c24b75597a77e1b30c66604725707565188ba54bab4f114820"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-win32.whl", hash = "sha256:1b12b50e07c3911e1efa3a8971543e7648100713d4e0971b13631cce22c587eb"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:994a4f0681bb6c6c3b0925530a1926b7a189d878e6e5e38fae8efa47c5d9c613"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2e4aeb0bd2540cb91b069dbdd54d458da8c4334ceaf2d25df2f4af576d6766ca"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b7b0033b0d37bb33009fb2fef73310e432e76f688af76c156b3594389d81391"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54a07bb2374a1eba8ebb52b6fafffa2afd3c4df85ddd38fcc0511f2bb387c2a8"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7901a7dc4b88f1c1475de59ae9be59799db1007b7d059817948d8e4f12e24e35"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ce01c7316aebc7fce59da734286148b1d1b9455f89cf2c8a4dfce7d41db55c2d"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:246f1d1a90279bb6069de3de8d75a8856e073b8ff0b09dcca18ccc14cec85979"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc4bc5d82bc56ebd8b514fb8350cfac4627d6b0743382e46d033976a5f80fab6"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37c26ecb14386a44b118ce36e546ce307f4810bc9598a6e6cb4f7fca725ae7e6"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca72968ae4eaf6470498d5c2887073f7efe3b1e7d7ec8be11a06a79cc810e990"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:add0de5b9ad9e9aa293c3aa4e9deb2b61e99ad6c1634e01d01d98c03e6a354cc"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9b6068e0f3769992d6b622a1cd2e7835eae3cf8d9da123d7f51ca9c1e9c333e5"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8557a8559509b61e65083f8782329188a250102372576093c88930c875a69838"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a7ae37e5d79c5bdfb5b4b99f2715a6035e6c5bf538c3746abc8e26694f92f33"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391151ec86bb1c683835980f4816272a87eaddc46bb91cbf44f62228b84d8cca"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:2f3711be9290f0453de8eed5275d93d286abe26b08ab4a35d7452caa1fef532f"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1a807d760763e398bbf2c6394ae9da5815901aa93ee0a37bca5efe78d4ee3171"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa8ca0623b26c94fccc3a1fdd895be1743b838f3917300506d04aa3346fd2a14"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3de0cf28a53a3238b252aca9fed1593e9d36c1d116748013339f0949bfc84112"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6be5ec0e88a4925c91f3dea2bb0013b3a2accda6f77238f76a34a1ea532a1cb0"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d9eb71bb1085d996244439154387266fd23d6ad37161f6f52f1cd41dd95a3808"}, + {file = "brotlicffi-1.1.0.0.tar.gz", hash = "sha256:b77827a689905143f87915310b93b273ab17888fd43ef350d4832c4a71083c13"}, +] + +[package.dependencies] +cffi = ">=1.0.0" + +[[package]] +name = "certifi" +version = "2024.2.2" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, +] + +[[package]] +name = "cffi" +version = "1.16.0" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, + {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, + {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, + {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, + {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, + {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, + {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, + {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, + {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, + {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, + {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, + {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, + {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, + {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, +] + +[package.dependencies] +pycparser = "*" + +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[[package]] +name = "h2" +version = "4.1.0" +description = "HTTP/2 State-Machine based protocol implementation" +optional = false +python-versions = ">=3.6.1" +files = [ + {file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"}, + {file = "h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb"}, +] + +[package.dependencies] +hpack = ">=4.0,<5" +hyperframe = ">=6.0,<7" + +[[package]] +name = "hpack" +version = "4.0.0" +description = "Pure-Python HPACK header compression" +optional = false +python-versions = ">=3.6.1" +files = [ + {file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"}, + {file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"}, +] + +[[package]] +name = "httpcore" +version = "1.0.5" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, + {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, +] + +[package.dependencies] +certifi = "*" +h11 = ">=0.13,<0.15" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<0.26.0)"] + +[[package]] +name = "httpx" +version = "0.27.0" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, + {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, +] + +[package.dependencies] +anyio = "*" +brotli = {version = "*", optional = true, markers = "platform_python_implementation == \"CPython\" and extra == \"brotli\""} +brotlicffi = {version = "*", optional = true, markers = "platform_python_implementation != \"CPython\" and extra == \"brotli\""} +certifi = "*" +h2 = {version = ">=3,<5", optional = true, markers = "extra == \"http2\""} +httpcore = "==1.*" +idna = "*" +sniffio = "*" +socksio = {version = "==1.*", optional = true, markers = "extra == \"socks\""} + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] + +[[package]] +name = "hyperframe" +version = "6.0.1" +description = "HTTP/2 framing layer for Python" +optional = false +python-versions = ">=3.6.1" +files = [ + {file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"}, + {file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"}, +] + +[[package]] +name = "idna" +version = "3.7" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, + {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, +] + +[[package]] +name = "pycparser" +version = "2.22" +description = "C parser in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, +] + +[[package]] +name = "socksio" +version = "1.0.0" +description = "Sans-I/O implementation of SOCKS4, SOCKS4A, and SOCKS5." +optional = false +python-versions = ">=3.6" +files = [ + {file = "socksio-1.0.0-py3-none-any.whl", hash = "sha256:95dc1f15f9b34e8d7b16f06d74b8ccf48f609af32ab33c608d08761c5dcbb1f3"}, + {file = "socksio-1.0.0.tar.gz", hash = "sha256:f88beb3da5b5c38b9890469de67d0cb0f9d494b78b106ca1845f96c10b91c4ac"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.11" +content-hash = "1aa23bf12b27ddd43daba759482256c2f8a0f62d3788f6930123ef5008847f60" diff --git a/syft/pkg/cataloger/python/test-fixtures/poetry/multiple-extras/pyproject.toml b/syft/pkg/cataloger/python/test-fixtures/poetry/multiple-extras/pyproject.toml new file mode 100644 index 000000000..09c70bd63 --- /dev/null +++ b/syft/pkg/cataloger/python/test-fixtures/poetry/multiple-extras/pyproject.toml @@ -0,0 +1,14 @@ +[tool.poetry] +name = "testpkg" +version = "0.1.0" +description = "" +authors = ["Alex Goodman "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.11" +httpx = {extras = ["brotli", "http2", "socks"], version = "^0.27.0"} + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/syft/pkg/cataloger/python/test-fixtures/poetry/nested-extras/poetry.lock b/syft/pkg/cataloger/python/test-fixtures/poetry/nested-extras/poetry.lock new file mode 100644 index 000000000..e199e1bb9 --- /dev/null +++ b/syft/pkg/cataloger/python/test-fixtures/poetry/nested-extras/poetry.lock @@ -0,0 +1,1114 @@ +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. + +[[package]] +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +files = [ + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, +] + +[[package]] +name = "anyio" +version = "4.3.0" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.8" +files = [ + {file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"}, + {file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"}, +] + +[package.dependencies] +idna = ">=2.8" +sniffio = ">=1.1" + +[package.extras] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.23)"] + +[[package]] +name = "certifi" +version = "2024.2.2" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, +] + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "dnspython" +version = "2.6.1" +description = "DNS toolkit" +optional = false +python-versions = ">=3.8" +files = [ + {file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"}, + {file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"}, +] + +[package.extras] +dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "sphinx (>=7.2.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"] +dnssec = ["cryptography (>=41)"] +doh = ["h2 (>=4.1.0)", "httpcore (>=1.0.0)", "httpx (>=0.26.0)"] +doq = ["aioquic (>=0.9.25)"] +idna = ["idna (>=3.6)"] +trio = ["trio (>=0.23)"] +wmi = ["wmi (>=1.5.1)"] + +[[package]] +name = "email-validator" +version = "2.1.1" +description = "A robust email address syntax and deliverability validation library." +optional = false +python-versions = ">=3.8" +files = [ + {file = "email_validator-2.1.1-py3-none-any.whl", hash = "sha256:97d882d174e2a65732fb43bfce81a3a834cbc1bde8bf419e30ef5ea976370a05"}, + {file = "email_validator-2.1.1.tar.gz", hash = "sha256:200a70680ba08904be6d1eef729205cc0d687634399a5924d842533efb824b84"}, +] + +[package.dependencies] +dnspython = ">=2.0.0" +idna = ">=2.0.0" + +[[package]] +name = "fastapi" +version = "0.111.0" +description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fastapi-0.111.0-py3-none-any.whl", hash = "sha256:97ecbf994be0bcbdadedf88c3150252bed7b2087075ac99735403b1b76cc8fc0"}, + {file = "fastapi-0.111.0.tar.gz", hash = "sha256:b9db9dd147c91cb8b769f7183535773d8741dd46f9dc6676cd82eab510228cd7"}, +] + +[package.dependencies] +email_validator = ">=2.0.0" +fastapi-cli = ">=0.0.2" +httpx = ">=0.23.0" +itsdangerous = {version = ">=1.1.0", optional = true, markers = "extra == \"all\""} +jinja2 = ">=2.11.2" +orjson = ">=3.2.1" +pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" +pydantic-extra-types = {version = ">=2.0.0", optional = true, markers = "extra == \"all\""} +pydantic-settings = {version = ">=2.0.0", optional = true, markers = "extra == \"all\""} +python-multipart = ">=0.0.7" +pyyaml = {version = ">=5.3.1", optional = true, markers = "extra == \"all\""} +starlette = ">=0.37.2,<0.38.0" +typing-extensions = ">=4.8.0" +ujson = ">=4.0.1,<4.0.2 || >4.0.2,<4.1.0 || >4.1.0,<4.2.0 || >4.2.0,<4.3.0 || >4.3.0,<5.0.0 || >5.0.0,<5.1.0 || >5.1.0" +uvicorn = {version = ">=0.12.0", extras = ["standard"]} + +[package.extras] +all = ["email_validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] + +[[package]] +name = "fastapi-cli" +version = "0.0.4" +description = "Run and manage FastAPI apps from the command line with FastAPI CLI. 🚀" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fastapi_cli-0.0.4-py3-none-any.whl", hash = "sha256:a2552f3a7ae64058cdbb530be6fa6dbfc975dc165e4fa66d224c3d396e25e809"}, + {file = "fastapi_cli-0.0.4.tar.gz", hash = "sha256:e2e9ffaffc1f7767f488d6da34b6f5a377751c996f397902eb6abb99a67bde32"}, +] + +[package.dependencies] +typer = ">=0.12.3" + +[package.extras] +standard = ["fastapi", "uvicorn[standard] (>=0.15.0)"] + +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[[package]] +name = "httpcore" +version = "1.0.5" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, + {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, +] + +[package.dependencies] +certifi = "*" +h11 = ">=0.13,<0.15" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<0.26.0)"] + +[[package]] +name = "httptools" +version = "0.6.1" +description = "A collection of framework independent HTTP protocol utils." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d2f6c3c4cb1948d912538217838f6e9960bc4a521d7f9b323b3da579cd14532f"}, + {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:00d5d4b68a717765b1fabfd9ca755bd12bf44105eeb806c03d1962acd9b8e563"}, + {file = "httptools-0.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:639dc4f381a870c9ec860ce5c45921db50205a37cc3334e756269736ff0aac58"}, + {file = "httptools-0.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e57997ac7fb7ee43140cc03664de5f268813a481dff6245e0075925adc6aa185"}, + {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0ac5a0ae3d9f4fe004318d64b8a854edd85ab76cffbf7ef5e32920faef62f142"}, + {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3f30d3ce413088a98b9db71c60a6ada2001a08945cb42dd65a9a9fe228627658"}, + {file = "httptools-0.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:1ed99a373e327f0107cb513b61820102ee4f3675656a37a50083eda05dc9541b"}, + {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7a7ea483c1a4485c71cb5f38be9db078f8b0e8b4c4dc0210f531cdd2ddac1ef1"}, + {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:85ed077c995e942b6f1b07583e4eb0a8d324d418954fc6af913d36db7c05a5a0"}, + {file = "httptools-0.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b0bb634338334385351a1600a73e558ce619af390c2b38386206ac6a27fecfc"}, + {file = "httptools-0.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d9ceb2c957320def533671fc9c715a80c47025139c8d1f3797477decbc6edd2"}, + {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4f0f8271c0a4db459f9dc807acd0eadd4839934a4b9b892f6f160e94da309837"}, + {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6a4f5ccead6d18ec072ac0b84420e95d27c1cdf5c9f1bc8fbd8daf86bd94f43d"}, + {file = "httptools-0.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:5cceac09f164bcba55c0500a18fe3c47df29b62353198e4f37bbcc5d591172c3"}, + {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:75c8022dca7935cba14741a42744eee13ba05db00b27a4b940f0d646bd4d56d0"}, + {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:48ed8129cd9a0d62cf4d1575fcf90fb37e3ff7d5654d3a5814eb3d55f36478c2"}, + {file = "httptools-0.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f58e335a1402fb5a650e271e8c2d03cfa7cea46ae124649346d17bd30d59c90"}, + {file = "httptools-0.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93ad80d7176aa5788902f207a4e79885f0576134695dfb0fefc15b7a4648d503"}, + {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9bb68d3a085c2174c2477eb3ffe84ae9fb4fde8792edb7bcd09a1d8467e30a84"}, + {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b512aa728bc02354e5ac086ce76c3ce635b62f5fbc32ab7082b5e582d27867bb"}, + {file = "httptools-0.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:97662ce7fb196c785344d00d638fc9ad69e18ee4bfb4000b35a52efe5adcc949"}, + {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8e216a038d2d52ea13fdd9b9c9c7459fb80d78302b257828285eca1c773b99b3"}, + {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3e802e0b2378ade99cd666b5bffb8b2a7cc8f3d28988685dc300469ea8dd86cb"}, + {file = "httptools-0.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bd3e488b447046e386a30f07af05f9b38d3d368d1f7b4d8f7e10af85393db97"}, + {file = "httptools-0.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe467eb086d80217b7584e61313ebadc8d187a4d95bb62031b7bab4b205c3ba3"}, + {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3c3b214ce057c54675b00108ac42bacf2ab8f85c58e3f324a4e963bbc46424f4"}, + {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8ae5b97f690badd2ca27cbf668494ee1b6d34cf1c464271ef7bfa9ca6b83ffaf"}, + {file = "httptools-0.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:405784577ba6540fa7d6ff49e37daf104e04f4b4ff2d1ac0469eaa6a20fde084"}, + {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:95fb92dd3649f9cb139e9c56604cc2d7c7bf0fc2e7c8d7fbd58f96e35eddd2a3"}, + {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dcbab042cc3ef272adc11220517278519adf8f53fd3056d0e68f0a6f891ba94e"}, + {file = "httptools-0.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cf2372e98406efb42e93bfe10f2948e467edfd792b015f1b4ecd897903d3e8d"}, + {file = "httptools-0.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:678fcbae74477a17d103b7cae78b74800d795d702083867ce160fc202104d0da"}, + {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e0b281cf5a125c35f7f6722b65d8542d2e57331be573e9e88bc8b0115c4a7a81"}, + {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:95658c342529bba4e1d3d2b1a874db16c7cca435e8827422154c9da76ac4e13a"}, + {file = "httptools-0.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ebaec1bf683e4bf5e9fbb49b8cc36da482033596a415b3e4ebab5a4c0d7ec5e"}, + {file = "httptools-0.6.1.tar.gz", hash = "sha256:c6e26c30455600b95d94b1b836085138e82f177351454ee841c148f93a9bad5a"}, +] + +[package.extras] +test = ["Cython (>=0.29.24,<0.30.0)"] + +[[package]] +name = "httpx" +version = "0.27.0" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, + {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, +] + +[package.dependencies] +anyio = "*" +certifi = "*" +httpcore = "==1.*" +idna = "*" +sniffio = "*" + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] + +[[package]] +name = "idna" +version = "3.7" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, + {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, +] + +[[package]] +name = "itsdangerous" +version = "2.2.0" +description = "Safely pass data to untrusted environments and back." +optional = false +python-versions = ">=3.8" +files = [ + {file = "itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef"}, + {file = "itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"}, +] + +[[package]] +name = "jinja2" +version = "3.1.4" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, + {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "markdown-it-py" +version = "3.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.8" +files = [ + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, +] + +[package.dependencies] +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + +[[package]] +name = "markupsafe" +version = "2.1.5" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + +[[package]] +name = "orjson" +version = "3.10.3" +description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" +optional = false +python-versions = ">=3.8" +files = [ + {file = "orjson-3.10.3-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9fb6c3f9f5490a3eb4ddd46fc1b6eadb0d6fc16fb3f07320149c3286a1409dd8"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:252124b198662eee80428f1af8c63f7ff077c88723fe206a25df8dc57a57b1fa"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f3e87733823089a338ef9bbf363ef4de45e5c599a9bf50a7a9b82e86d0228da"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8334c0d87103bb9fbbe59b78129f1f40d1d1e8355bbed2ca71853af15fa4ed3"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1952c03439e4dce23482ac846e7961f9d4ec62086eb98ae76d97bd41d72644d7"}, + {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c0403ed9c706dcd2809f1600ed18f4aae50be263bd7112e54b50e2c2bc3ebd6d"}, + {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:382e52aa4270a037d41f325e7d1dfa395b7de0c367800b6f337d8157367bf3a7"}, + {file = "orjson-3.10.3-cp310-none-win32.whl", hash = "sha256:be2aab54313752c04f2cbaab4515291ef5af8c2256ce22abc007f89f42f49109"}, + {file = "orjson-3.10.3-cp310-none-win_amd64.whl", hash = "sha256:416b195f78ae461601893f482287cee1e3059ec49b4f99479aedf22a20b1098b"}, + {file = "orjson-3.10.3-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:73100d9abbbe730331f2242c1fc0bcb46a3ea3b4ae3348847e5a141265479700"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a12eee96e3ab828dbfcb4d5a0023aa971b27143a1d35dc214c176fdfb29b3"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520de5e2ef0b4ae546bea25129d6c7c74edb43fc6cf5213f511a927f2b28148b"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccaa0a401fc02e8828a5bedfd80f8cd389d24f65e5ca3954d72c6582495b4bcf"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7bc9e8bc11bac40f905640acd41cbeaa87209e7e1f57ade386da658092dc16"}, + {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3582b34b70543a1ed6944aca75e219e1192661a63da4d039d088a09c67543b08"}, + {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c23dfa91481de880890d17aa7b91d586a4746a4c2aa9a145bebdbaf233768d5"}, + {file = "orjson-3.10.3-cp311-none-win32.whl", hash = "sha256:1770e2a0eae728b050705206d84eda8b074b65ee835e7f85c919f5705b006c9b"}, + {file = "orjson-3.10.3-cp311-none-win_amd64.whl", hash = "sha256:93433b3c1f852660eb5abdc1f4dd0ced2be031ba30900433223b28ee0140cde5"}, + {file = "orjson-3.10.3-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a39aa73e53bec8d410875683bfa3a8edf61e5a1c7bb4014f65f81d36467ea098"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0943a96b3fa09bee1afdfccc2cb236c9c64715afa375b2af296c73d91c23eab2"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e852baafceff8da3c9defae29414cc8513a1586ad93e45f27b89a639c68e8176"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18566beb5acd76f3769c1d1a7ec06cdb81edc4d55d2765fb677e3eaa10fa99e0"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bd2218d5a3aa43060efe649ec564ebedec8ce6ae0a43654b81376216d5ebd42"}, + {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cf20465e74c6e17a104ecf01bf8cd3b7b252565b4ccee4548f18b012ff2f8069"}, + {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba7f67aa7f983c4345eeda16054a4677289011a478ca947cd69c0a86ea45e534"}, + {file = "orjson-3.10.3-cp312-none-win32.whl", hash = "sha256:17e0713fc159abc261eea0f4feda611d32eabc35708b74bef6ad44f6c78d5ea0"}, + {file = "orjson-3.10.3-cp312-none-win_amd64.whl", hash = "sha256:4c895383b1ec42b017dd2c75ae8a5b862fc489006afde06f14afbdd0309b2af0"}, + {file = "orjson-3.10.3-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:be2719e5041e9fb76c8c2c06b9600fe8e8584e6980061ff88dcbc2691a16d20d"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0175a5798bdc878956099f5c54b9837cb62cfbf5d0b86ba6d77e43861bcec2"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:978be58a68ade24f1af7758626806e13cff7748a677faf95fbb298359aa1e20d"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16bda83b5c61586f6f788333d3cf3ed19015e3b9019188c56983b5a299210eb5"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ad1f26bea425041e0a1adad34630c4825a9e3adec49079b1fb6ac8d36f8b754"}, + {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9e253498bee561fe85d6325ba55ff2ff08fb5e7184cd6a4d7754133bd19c9195"}, + {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0a62f9968bab8a676a164263e485f30a0b748255ee2f4ae49a0224be95f4532b"}, + {file = "orjson-3.10.3-cp38-none-win32.whl", hash = "sha256:8d0b84403d287d4bfa9bf7d1dc298d5c1c5d9f444f3737929a66f2fe4fb8f134"}, + {file = "orjson-3.10.3-cp38-none-win_amd64.whl", hash = "sha256:8bc7a4df90da5d535e18157220d7915780d07198b54f4de0110eca6b6c11e290"}, + {file = "orjson-3.10.3-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9059d15c30e675a58fdcd6f95465c1522b8426e092de9fff20edebfdc15e1cb0"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d40c7f7938c9c2b934b297412c067936d0b54e4b8ab916fd1a9eb8f54c02294"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4a654ec1de8fdaae1d80d55cee65893cb06494e124681ab335218be6a0691e7"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:831c6ef73f9aa53c5f40ae8f949ff7681b38eaddb6904aab89dca4d85099cb78"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99b880d7e34542db89f48d14ddecbd26f06838b12427d5a25d71baceb5ba119d"}, + {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2e5e176c994ce4bd434d7aafb9ecc893c15f347d3d2bbd8e7ce0b63071c52e25"}, + {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b69a58a37dab856491bf2d3bbf259775fdce262b727f96aafbda359cb1d114d8"}, + {file = "orjson-3.10.3-cp39-none-win32.whl", hash = "sha256:b8d4d1a6868cde356f1402c8faeb50d62cee765a1f7ffcfd6de732ab0581e063"}, + {file = "orjson-3.10.3-cp39-none-win_amd64.whl", hash = "sha256:5102f50c5fc46d94f2033fe00d392588564378260d64377aec702f21a7a22912"}, + {file = "orjson-3.10.3.tar.gz", hash = "sha256:2b166507acae7ba2f7c315dcf185a9111ad5e992ac81f2d507aac39193c2c818"}, +] + +[[package]] +name = "pydantic" +version = "2.7.1" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic-2.7.1-py3-none-any.whl", hash = "sha256:e029badca45266732a9a79898a15ae2e8b14840b1eabbb25844be28f0b33f3d5"}, + {file = "pydantic-2.7.1.tar.gz", hash = "sha256:e9dbb5eada8abe4d9ae5f46b9939aead650cd2b68f249bb3a8139dbe125803cc"}, +] + +[package.dependencies] +annotated-types = ">=0.4.0" +pydantic-core = "2.18.2" +typing-extensions = ">=4.6.1" + +[package.extras] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.18.2" +description = "Core functionality for Pydantic validation and serialization" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic_core-2.18.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:9e08e867b306f525802df7cd16c44ff5ebbe747ff0ca6cf3fde7f36c05a59a81"}, + {file = "pydantic_core-2.18.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f0a21cbaa69900cbe1a2e7cad2aa74ac3cf21b10c3efb0fa0b80305274c0e8a2"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0680b1f1f11fda801397de52c36ce38ef1c1dc841a0927a94f226dea29c3ae3d"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:95b9d5e72481d3780ba3442eac863eae92ae43a5f3adb5b4d0a1de89d42bb250"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fcf5cd9c4b655ad666ca332b9a081112cd7a58a8b5a6ca7a3104bc950f2038"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b5155ff768083cb1d62f3e143b49a8a3432e6789a3abee8acd005c3c7af1c74"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:553ef617b6836fc7e4df130bb851e32fe357ce36336d897fd6646d6058d980af"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b89ed9eb7d616ef5714e5590e6cf7f23b02d0d539767d33561e3675d6f9e3857"}, + {file = "pydantic_core-2.18.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:75f7e9488238e920ab6204399ded280dc4c307d034f3924cd7f90a38b1829563"}, + {file = "pydantic_core-2.18.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ef26c9e94a8c04a1b2924149a9cb081836913818e55681722d7f29af88fe7b38"}, + {file = "pydantic_core-2.18.2-cp310-none-win32.whl", hash = "sha256:182245ff6b0039e82b6bb585ed55a64d7c81c560715d1bad0cbad6dfa07b4027"}, + {file = "pydantic_core-2.18.2-cp310-none-win_amd64.whl", hash = "sha256:e23ec367a948b6d812301afc1b13f8094ab7b2c280af66ef450efc357d2ae543"}, + {file = "pydantic_core-2.18.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:219da3f096d50a157f33645a1cf31c0ad1fe829a92181dd1311022f986e5fbe3"}, + {file = "pydantic_core-2.18.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cc1cfd88a64e012b74e94cd00bbe0f9c6df57049c97f02bb07d39e9c852e19a4"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05b7133a6e6aeb8df37d6f413f7705a37ab4031597f64ab56384c94d98fa0e90"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:224c421235f6102e8737032483f43c1a8cfb1d2f45740c44166219599358c2cd"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b14d82cdb934e99dda6d9d60dc84a24379820176cc4a0d123f88df319ae9c150"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2728b01246a3bba6de144f9e3115b532ee44bd6cf39795194fb75491824a1413"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:470b94480bb5ee929f5acba6995251ada5e059a5ef3e0dfc63cca287283ebfa6"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:997abc4df705d1295a42f95b4eec4950a37ad8ae46d913caeee117b6b198811c"}, + {file = "pydantic_core-2.18.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:75250dbc5290e3f1a0f4618db35e51a165186f9034eff158f3d490b3fed9f8a0"}, + {file = "pydantic_core-2.18.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4456f2dca97c425231d7315737d45239b2b51a50dc2b6f0c2bb181fce6207664"}, + {file = "pydantic_core-2.18.2-cp311-none-win32.whl", hash = "sha256:269322dcc3d8bdb69f054681edff86276b2ff972447863cf34c8b860f5188e2e"}, + {file = "pydantic_core-2.18.2-cp311-none-win_amd64.whl", hash = "sha256:800d60565aec896f25bc3cfa56d2277d52d5182af08162f7954f938c06dc4ee3"}, + {file = "pydantic_core-2.18.2-cp311-none-win_arm64.whl", hash = "sha256:1404c69d6a676245199767ba4f633cce5f4ad4181f9d0ccb0577e1f66cf4c46d"}, + {file = "pydantic_core-2.18.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:fb2bd7be70c0fe4dfd32c951bc813d9fe6ebcbfdd15a07527796c8204bd36242"}, + {file = "pydantic_core-2.18.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6132dd3bd52838acddca05a72aafb6eab6536aa145e923bb50f45e78b7251043"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d904828195733c183d20a54230c0df0eb46ec746ea1a666730787353e87182"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c9bd70772c720142be1020eac55f8143a34ec9f82d75a8e7a07852023e46617f"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b8ed04b3582771764538f7ee7001b02e1170223cf9b75dff0bc698fadb00cf3"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e6dac87ddb34aaec85f873d737e9d06a3555a1cc1a8e0c44b7f8d5daeb89d86f"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ca4ae5a27ad7a4ee5170aebce1574b375de390bc01284f87b18d43a3984df72"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:886eec03591b7cf058467a70a87733b35f44707bd86cf64a615584fd72488b7c"}, + {file = "pydantic_core-2.18.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ca7b0c1f1c983e064caa85f3792dd2fe3526b3505378874afa84baf662e12241"}, + {file = "pydantic_core-2.18.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b4356d3538c3649337df4074e81b85f0616b79731fe22dd11b99499b2ebbdf3"}, + {file = "pydantic_core-2.18.2-cp312-none-win32.whl", hash = "sha256:8b172601454f2d7701121bbec3425dd71efcb787a027edf49724c9cefc14c038"}, + {file = "pydantic_core-2.18.2-cp312-none-win_amd64.whl", hash = "sha256:b1bd7e47b1558ea872bd16c8502c414f9e90dcf12f1395129d7bb42a09a95438"}, + {file = "pydantic_core-2.18.2-cp312-none-win_arm64.whl", hash = "sha256:98758d627ff397e752bc339272c14c98199c613f922d4a384ddc07526c86a2ec"}, + {file = "pydantic_core-2.18.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:9fdad8e35f278b2c3eb77cbdc5c0a49dada440657bf738d6905ce106dc1de439"}, + {file = "pydantic_core-2.18.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1d90c3265ae107f91a4f279f4d6f6f1d4907ac76c6868b27dc7fb33688cfb347"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:390193c770399861d8df9670fb0d1874f330c79caaca4642332df7c682bf6b91"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:82d5d4d78e4448683cb467897fe24e2b74bb7b973a541ea1dcfec1d3cbce39fb"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4774f3184d2ef3e14e8693194f661dea5a4d6ca4e3dc8e39786d33a94865cefd"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4d938ec0adf5167cb335acb25a4ee69a8107e4984f8fbd2e897021d9e4ca21b"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0e8b1be28239fc64a88a8189d1df7fad8be8c1ae47fcc33e43d4be15f99cc70"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:868649da93e5a3d5eacc2b5b3b9235c98ccdbfd443832f31e075f54419e1b96b"}, + {file = "pydantic_core-2.18.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:78363590ef93d5d226ba21a90a03ea89a20738ee5b7da83d771d283fd8a56761"}, + {file = "pydantic_core-2.18.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:852e966fbd035a6468fc0a3496589b45e2208ec7ca95c26470a54daed82a0788"}, + {file = "pydantic_core-2.18.2-cp38-none-win32.whl", hash = "sha256:6a46e22a707e7ad4484ac9ee9f290f9d501df45954184e23fc29408dfad61350"}, + {file = "pydantic_core-2.18.2-cp38-none-win_amd64.whl", hash = "sha256:d91cb5ea8b11607cc757675051f61b3d93f15eca3cefb3e6c704a5d6e8440f4e"}, + {file = "pydantic_core-2.18.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:ae0a8a797a5e56c053610fa7be147993fe50960fa43609ff2a9552b0e07013e8"}, + {file = "pydantic_core-2.18.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:042473b6280246b1dbf530559246f6842b56119c2926d1e52b631bdc46075f2a"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a388a77e629b9ec814c1b1e6b3b595fe521d2cdc625fcca26fbc2d44c816804"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25add29b8f3b233ae90ccef2d902d0ae0432eb0d45370fe315d1a5cf231004b"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f459a5ce8434614dfd39bbebf1041952ae01da6bed9855008cb33b875cb024c0"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eff2de745698eb46eeb51193a9f41d67d834d50e424aef27df2fcdee1b153845"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8309f67285bdfe65c372ea3722b7a5642680f3dba538566340a9d36e920b5f0"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f93a8a2e3938ff656a7c1bc57193b1319960ac015b6e87d76c76bf14fe0244b4"}, + {file = "pydantic_core-2.18.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:22057013c8c1e272eb8d0eebc796701167d8377441ec894a8fed1af64a0bf399"}, + {file = "pydantic_core-2.18.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cfeecd1ac6cc1fb2692c3d5110781c965aabd4ec5d32799773ca7b1456ac636b"}, + {file = "pydantic_core-2.18.2-cp39-none-win32.whl", hash = "sha256:0d69b4c2f6bb3e130dba60d34c0845ba31b69babdd3f78f7c0c8fae5021a253e"}, + {file = "pydantic_core-2.18.2-cp39-none-win_amd64.whl", hash = "sha256:d9319e499827271b09b4e411905b24a426b8fb69464dfa1696258f53a3334641"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a1874c6dd4113308bd0eb568418e6114b252afe44319ead2b4081e9b9521fe75"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:ccdd111c03bfd3666bd2472b674c6899550e09e9f298954cfc896ab92b5b0e6d"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e18609ceaa6eed63753037fc06ebb16041d17d28199ae5aba0052c51449650a9"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e5c584d357c4e2baf0ff7baf44f4994be121e16a2c88918a5817331fc7599d7"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43f0f463cf89ace478de71a318b1b4f05ebc456a9b9300d027b4b57c1a2064fb"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e1b395e58b10b73b07b7cf740d728dd4ff9365ac46c18751bf8b3d8cca8f625a"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0098300eebb1c837271d3d1a2cd2911e7c11b396eac9661655ee524a7f10587b"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:36789b70d613fbac0a25bb07ab3d9dba4d2e38af609c020cf4d888d165ee0bf3"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3f9a801e7c8f1ef8718da265bba008fa121243dfe37c1cea17840b0944dfd72c"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:3a6515ebc6e69d85502b4951d89131ca4e036078ea35533bb76327f8424531ce"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20aca1e2298c56ececfd8ed159ae4dde2df0781988c97ef77d5c16ff4bd5b400"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:223ee893d77a310a0391dca6df00f70bbc2f36a71a895cecd9a0e762dc37b349"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2334ce8c673ee93a1d6a65bd90327588387ba073c17e61bf19b4fd97d688d63c"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cbca948f2d14b09d20268cda7b0367723d79063f26c4ffc523af9042cad95592"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b3ef08e20ec49e02d5c6717a91bb5af9b20f1805583cb0adfe9ba2c6b505b5ae"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c6fdc8627910eed0c01aed6a390a252fe3ea6d472ee70fdde56273f198938374"}, + {file = "pydantic_core-2.18.2.tar.gz", hash = "sha256:2e29d20810dfc3043ee13ac7d9e25105799817683348823f305ab3f349b9386e"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + +[[package]] +name = "pydantic-extra-types" +version = "2.7.0" +description = "Extra Pydantic types." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic_extra_types-2.7.0-py3-none-any.whl", hash = "sha256:ac01bbdaa4f85e4c4744a9792c5b0cfe61efa5028a0e670c3d8bfbf8b36c8543"}, + {file = "pydantic_extra_types-2.7.0.tar.gz", hash = "sha256:b9d9ddd755fa5960ec5a77cffcbd5d8796a0116e1dfc8f7c3a27fa0041693382"}, +] + +[package.dependencies] +pydantic = ">=2.5.2" + +[package.extras] +all = ["pendulum (>=3.0.0,<4.0.0)", "phonenumbers (>=8,<9)", "pycountry (>=23)", "python-ulid (>=1,<2)", "python-ulid (>=1,<3)"] + +[[package]] +name = "pydantic-settings" +version = "2.2.1" +description = "Settings management using Pydantic" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic_settings-2.2.1-py3-none-any.whl", hash = "sha256:0235391d26db4d2190cb9b31051c4b46882d28a51533f97440867f012d4da091"}, + {file = "pydantic_settings-2.2.1.tar.gz", hash = "sha256:00b9f6a5e95553590434c0fa01ead0b216c3e10bc54ae02e37f359948643c5ed"}, +] + +[package.dependencies] +pydantic = ">=2.3.0" +python-dotenv = ">=0.21.0" + +[package.extras] +toml = ["tomli (>=2.0.1)"] +yaml = ["pyyaml (>=6.0.1)"] + +[[package]] +name = "pygments" +version = "2.18.0" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "python-dotenv" +version = "1.0.1" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, + {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + +[[package]] +name = "python-multipart" +version = "0.0.9" +description = "A streaming multipart parser for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python_multipart-0.0.9-py3-none-any.whl", hash = "sha256:97ca7b8ea7b05f977dc3849c3ba99d51689822fab725c3703af7c866a0c2b215"}, + {file = "python_multipart-0.0.9.tar.gz", hash = "sha256:03f54688c663f1b7977105f021043b0793151e4cb1c1a9d4a11fc13d622c4026"}, +] + +[package.extras] +dev = ["atomicwrites (==1.4.1)", "attrs (==23.2.0)", "coverage (==7.4.1)", "hatch", "invoke (==2.2.0)", "more-itertools (==10.2.0)", "pbr (==6.0.0)", "pluggy (==1.4.0)", "py (==1.11.0)", "pytest (==8.0.0)", "pytest-cov (==4.1.0)", "pytest-timeout (==2.2.0)", "pyyaml (==6.0.1)", "ruff (==0.2.1)"] + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "rich" +version = "13.7.1" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"}, + {file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"}, +] + +[package.dependencies] +markdown-it-py = ">=2.2.0" +pygments = ">=2.13.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<9)"] + +[[package]] +name = "shellingham" +version = "1.5.4" +description = "Tool to Detect Surrounding Shell" +optional = false +python-versions = ">=3.7" +files = [ + {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, + {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, +] + +[[package]] +name = "starlette" +version = "0.37.2" +description = "The little ASGI library that shines." +optional = false +python-versions = ">=3.8" +files = [ + {file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"}, + {file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"}, +] + +[package.dependencies] +anyio = ">=3.4.0,<5" + +[package.extras] +full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"] + +[[package]] +name = "typer" +version = "0.12.3" +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +optional = false +python-versions = ">=3.7" +files = [ + {file = "typer-0.12.3-py3-none-any.whl", hash = "sha256:070d7ca53f785acbccba8e7d28b08dcd88f79f1fbda035ade0aecec71ca5c914"}, + {file = "typer-0.12.3.tar.gz", hash = "sha256:49e73131481d804288ef62598d97a1ceef3058905aa536a1134f90891ba35482"}, +] + +[package.dependencies] +click = ">=8.0.0" +rich = ">=10.11.0" +shellingham = ">=1.3.0" +typing-extensions = ">=3.7.4.3" + +[[package]] +name = "typing-extensions" +version = "4.12.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.12.0-py3-none-any.whl", hash = "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594"}, + {file = "typing_extensions-4.12.0.tar.gz", hash = "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8"}, +] + +[[package]] +name = "ujson" +version = "5.10.0" +description = "Ultra fast JSON encoder and decoder for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "ujson-5.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2601aa9ecdbee1118a1c2065323bda35e2c5a2cf0797ef4522d485f9d3ef65bd"}, + {file = "ujson-5.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:348898dd702fc1c4f1051bc3aacbf894caa0927fe2c53e68679c073375f732cf"}, + {file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22cffecf73391e8abd65ef5f4e4dd523162a3399d5e84faa6aebbf9583df86d6"}, + {file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26b0e2d2366543c1bb4fbd457446f00b0187a2bddf93148ac2da07a53fe51569"}, + {file = "ujson-5.10.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:caf270c6dba1be7a41125cd1e4fc7ba384bf564650beef0df2dd21a00b7f5770"}, + {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a245d59f2ffe750446292b0094244df163c3dc96b3ce152a2c837a44e7cda9d1"}, + {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:94a87f6e151c5f483d7d54ceef83b45d3a9cca7a9cb453dbdbb3f5a6f64033f5"}, + {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:29b443c4c0a113bcbb792c88bea67b675c7ca3ca80c3474784e08bba01c18d51"}, + {file = "ujson-5.10.0-cp310-cp310-win32.whl", hash = "sha256:c18610b9ccd2874950faf474692deee4223a994251bc0a083c114671b64e6518"}, + {file = "ujson-5.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:924f7318c31874d6bb44d9ee1900167ca32aa9b69389b98ecbde34c1698a250f"}, + {file = "ujson-5.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a5b366812c90e69d0f379a53648be10a5db38f9d4ad212b60af00bd4048d0f00"}, + {file = "ujson-5.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:502bf475781e8167f0f9d0e41cd32879d120a524b22358e7f205294224c71126"}, + {file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b91b5d0d9d283e085e821651184a647699430705b15bf274c7896f23fe9c9d8"}, + {file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:129e39af3a6d85b9c26d5577169c21d53821d8cf68e079060602e861c6e5da1b"}, + {file = "ujson-5.10.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f77b74475c462cb8b88680471193064d3e715c7c6074b1c8c412cb526466efe9"}, + {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ec0ca8c415e81aa4123501fee7f761abf4b7f386aad348501a26940beb1860f"}, + {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab13a2a9e0b2865a6c6db9271f4b46af1c7476bfd51af1f64585e919b7c07fd4"}, + {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:57aaf98b92d72fc70886b5a0e1a1ca52c2320377360341715dd3933a18e827b1"}, + {file = "ujson-5.10.0-cp311-cp311-win32.whl", hash = "sha256:2987713a490ceb27edff77fb184ed09acdc565db700ee852823c3dc3cffe455f"}, + {file = "ujson-5.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:f00ea7e00447918ee0eff2422c4add4c5752b1b60e88fcb3c067d4a21049a720"}, + {file = "ujson-5.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98ba15d8cbc481ce55695beee9f063189dce91a4b08bc1d03e7f0152cd4bbdd5"}, + {file = "ujson-5.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9d2edbf1556e4f56e50fab7d8ff993dbad7f54bac68eacdd27a8f55f433578e"}, + {file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6627029ae4f52d0e1a2451768c2c37c0c814ffc04f796eb36244cf16b8e57043"}, + {file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8ccb77b3e40b151e20519c6ae6d89bfe3f4c14e8e210d910287f778368bb3d1"}, + {file = "ujson-5.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3caf9cd64abfeb11a3b661329085c5e167abbe15256b3b68cb5d914ba7396f3"}, + {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6e32abdce572e3a8c3d02c886c704a38a1b015a1fb858004e03d20ca7cecbb21"}, + {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a65b6af4d903103ee7b6f4f5b85f1bfd0c90ba4eeac6421aae436c9988aa64a2"}, + {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:604a046d966457b6cdcacc5aa2ec5314f0e8c42bae52842c1e6fa02ea4bda42e"}, + {file = "ujson-5.10.0-cp312-cp312-win32.whl", hash = "sha256:6dea1c8b4fc921bf78a8ff00bbd2bfe166345f5536c510671bccececb187c80e"}, + {file = "ujson-5.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:38665e7d8290188b1e0d57d584eb8110951a9591363316dd41cf8686ab1d0abc"}, + {file = "ujson-5.10.0-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:618efd84dc1acbd6bff8eaa736bb6c074bfa8b8a98f55b61c38d4ca2c1f7f287"}, + {file = "ujson-5.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38d5d36b4aedfe81dfe251f76c0467399d575d1395a1755de391e58985ab1c2e"}, + {file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67079b1f9fb29ed9a2914acf4ef6c02844b3153913eb735d4bf287ee1db6e557"}, + {file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7d0e0ceeb8fe2468c70ec0c37b439dd554e2aa539a8a56365fd761edb418988"}, + {file = "ujson-5.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59e02cd37bc7c44d587a0ba45347cc815fb7a5fe48de16bf05caa5f7d0d2e816"}, + {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a890b706b64e0065f02577bf6d8ca3b66c11a5e81fb75d757233a38c07a1f20"}, + {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:621e34b4632c740ecb491efc7f1fcb4f74b48ddb55e65221995e74e2d00bbff0"}, + {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b9500e61fce0cfc86168b248104e954fead61f9be213087153d272e817ec7b4f"}, + {file = "ujson-5.10.0-cp313-cp313-win32.whl", hash = "sha256:4c4fc16f11ac1612f05b6f5781b384716719547e142cfd67b65d035bd85af165"}, + {file = "ujson-5.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:4573fd1695932d4f619928fd09d5d03d917274381649ade4328091ceca175539"}, + {file = "ujson-5.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a984a3131da7f07563057db1c3020b1350a3e27a8ec46ccbfbf21e5928a43050"}, + {file = "ujson-5.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:73814cd1b9db6fc3270e9d8fe3b19f9f89e78ee9d71e8bd6c9a626aeaeaf16bd"}, + {file = "ujson-5.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61e1591ed9376e5eddda202ec229eddc56c612b61ac6ad07f96b91460bb6c2fb"}, + {file = "ujson-5.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2c75269f8205b2690db4572a4a36fe47cd1338e4368bc73a7a0e48789e2e35a"}, + {file = "ujson-5.10.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7223f41e5bf1f919cd8d073e35b229295aa8e0f7b5de07ed1c8fddac63a6bc5d"}, + {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d4dc2fd6b3067c0782e7002ac3b38cf48608ee6366ff176bbd02cf969c9c20fe"}, + {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:232cc85f8ee3c454c115455195a205074a56ff42608fd6b942aa4c378ac14dd7"}, + {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cc6139531f13148055d691e442e4bc6601f6dba1e6d521b1585d4788ab0bfad4"}, + {file = "ujson-5.10.0-cp38-cp38-win32.whl", hash = "sha256:e7ce306a42b6b93ca47ac4a3b96683ca554f6d35dd8adc5acfcd55096c8dfcb8"}, + {file = "ujson-5.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:e82d4bb2138ab05e18f089a83b6564fee28048771eb63cdecf4b9b549de8a2cc"}, + {file = "ujson-5.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dfef2814c6b3291c3c5f10065f745a1307d86019dbd7ea50e83504950136ed5b"}, + {file = "ujson-5.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4734ee0745d5928d0ba3a213647f1c4a74a2a28edc6d27b2d6d5bd9fa4319e27"}, + {file = "ujson-5.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d47ebb01bd865fdea43da56254a3930a413f0c5590372a1241514abae8aa7c76"}, + {file = "ujson-5.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dee5e97c2496874acbf1d3e37b521dd1f307349ed955e62d1d2f05382bc36dd5"}, + {file = "ujson-5.10.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7490655a2272a2d0b072ef16b0b58ee462f4973a8f6bbe64917ce5e0a256f9c0"}, + {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba17799fcddaddf5c1f75a4ba3fd6441f6a4f1e9173f8a786b42450851bd74f1"}, + {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2aff2985cef314f21d0fecc56027505804bc78802c0121343874741650a4d3d1"}, + {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ad88ac75c432674d05b61184178635d44901eb749786c8eb08c102330e6e8996"}, + {file = "ujson-5.10.0-cp39-cp39-win32.whl", hash = "sha256:2544912a71da4ff8c4f7ab5606f947d7299971bdd25a45e008e467ca638d13c9"}, + {file = "ujson-5.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:3ff201d62b1b177a46f113bb43ad300b424b7847f9c5d38b1b4ad8f75d4a282a"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5b6fee72fa77dc172a28f21693f64d93166534c263adb3f96c413ccc85ef6e64"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:61d0af13a9af01d9f26d2331ce49bb5ac1fb9c814964018ac8df605b5422dcb3"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecb24f0bdd899d368b715c9e6664166cf694d1e57be73f17759573a6986dd95a"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbd8fd427f57a03cff3ad6574b5e299131585d9727c8c366da4624a9069ed746"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beeaf1c48e32f07d8820c705ff8e645f8afa690cca1544adba4ebfa067efdc88"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:baed37ea46d756aca2955e99525cc02d9181de67f25515c468856c38d52b5f3b"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7663960f08cd5a2bb152f5ee3992e1af7690a64c0e26d31ba7b3ff5b2ee66337"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:d8640fb4072d36b08e95a3a380ba65779d356b2fee8696afeb7794cf0902d0a1"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78778a3aa7aafb11e7ddca4e29f46bc5139131037ad628cc10936764282d6753"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0111b27f2d5c820e7f2dbad7d48e3338c824e7ac4d2a12da3dc6061cc39c8e6"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:c66962ca7565605b355a9ed478292da628b8f18c0f2793021ca4425abf8b01e5"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ba43cc34cce49cf2d4bc76401a754a81202d8aa926d0e2b79f0ee258cb15d3a4"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ac56eb983edce27e7f51d05bc8dd820586c6e6be1c5216a6809b0c668bb312b8"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44bd4b23a0e723bf8b10628288c2c7c335161d6840013d4d5de20e48551773b"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c10f4654e5326ec14a46bcdeb2b685d4ada6911050aa8baaf3501e57024b804"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0de4971a89a762398006e844ae394bd46991f7c385d7a6a3b93ba229e6dac17e"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e1402f0564a97d2a52310ae10a64d25bcef94f8dd643fcf5d310219d915484f7"}, + {file = "ujson-5.10.0.tar.gz", hash = "sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1"}, +] + +[[package]] +name = "uvicorn" +version = "0.29.0" +description = "The lightning-fast ASGI server." +optional = false +python-versions = ">=3.8" +files = [ + {file = "uvicorn-0.29.0-py3-none-any.whl", hash = "sha256:2c2aac7ff4f4365c206fd773a39bf4ebd1047c238f8b8268ad996829323473de"}, + {file = "uvicorn-0.29.0.tar.gz", hash = "sha256:6a69214c0b6a087462412670b3ef21224fa48cae0e452b5883e8e8bdfdd11dd0"}, +] + +[package.dependencies] +click = ">=7.0" +colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""} +h11 = ">=0.8" +httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standard\""} +python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} +pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} +uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "(sys_platform != \"win32\" and sys_platform != \"cygwin\") and platform_python_implementation != \"PyPy\" and extra == \"standard\""} +watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} +websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""} + +[package.extras] +standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] + +[[package]] +name = "uvloop" +version = "0.19.0" +description = "Fast implementation of asyncio event loop on top of libuv" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e"}, + {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428"}, + {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8"}, + {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849"}, + {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957"}, + {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd"}, + {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef"}, + {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2"}, + {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1"}, + {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24"}, + {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533"}, + {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12"}, + {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650"}, + {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec"}, + {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc"}, + {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6"}, + {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593"}, + {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3"}, + {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:78ab247f0b5671cc887c31d33f9b3abfb88d2614b84e4303f1a63b46c046c8bd"}, + {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:472d61143059c84947aa8bb74eabbace30d577a03a1805b77933d6bd13ddebbd"}, + {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45bf4c24c19fb8a50902ae37c5de50da81de4922af65baf760f7c0c42e1088be"}, + {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271718e26b3e17906b28b67314c45d19106112067205119dddbd834c2b7ce797"}, + {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:34175c9fd2a4bc3adc1380e1261f60306344e3407c20a4d684fd5f3be010fa3d"}, + {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e27f100e1ff17f6feeb1f33968bc185bf8ce41ca557deee9d9bbbffeb72030b7"}, + {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13dfdf492af0aa0a0edf66807d2b465607d11c4fa48f4a1fd41cbea5b18e8e8b"}, + {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6e3d4e85ac060e2342ff85e90d0c04157acb210b9ce508e784a944f852a40e67"}, + {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ca4956c9ab567d87d59d49fa3704cf29e37109ad348f2d5223c9bf761a332e7"}, + {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f467a5fd23b4fc43ed86342641f3936a68ded707f4627622fa3f82a120e18256"}, + {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:492e2c32c2af3f971473bc22f086513cedfc66a130756145a931a90c3958cb17"}, + {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2df95fca285a9f5bfe730e51945ffe2fa71ccbfdde3b0da5772b4ee4f2e770d5"}, + {file = "uvloop-0.19.0.tar.gz", hash = "sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd"}, +] + +[package.extras] +docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] +test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=23.0.0,<23.1.0)", "pycodestyle (>=2.9.0,<2.10.0)"] + +[[package]] +name = "watchfiles" +version = "0.21.0" +description = "Simple, modern and high performance file watching and code reload in python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "watchfiles-0.21.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:27b4035013f1ea49c6c0b42d983133b136637a527e48c132d368eb19bf1ac6aa"}, + {file = "watchfiles-0.21.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c81818595eff6e92535ff32825f31c116f867f64ff8cdf6562cd1d6b2e1e8f3e"}, + {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6c107ea3cf2bd07199d66f156e3ea756d1b84dfd43b542b2d870b77868c98c03"}, + {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d9ac347653ebd95839a7c607608703b20bc07e577e870d824fa4801bc1cb124"}, + {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5eb86c6acb498208e7663ca22dbe68ca2cf42ab5bf1c776670a50919a56e64ab"}, + {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f564bf68404144ea6b87a78a3f910cc8de216c6b12a4cf0b27718bf4ec38d303"}, + {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d0f32ebfaa9c6011f8454994f86108c2eb9c79b8b7de00b36d558cadcedaa3d"}, + {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6d45d9b699ecbac6c7bd8e0a2609767491540403610962968d258fd6405c17c"}, + {file = "watchfiles-0.21.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:aff06b2cac3ef4616e26ba17a9c250c1fe9dd8a5d907d0193f84c499b1b6e6a9"}, + {file = "watchfiles-0.21.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d9792dff410f266051025ecfaa927078b94cc7478954b06796a9756ccc7e14a9"}, + {file = "watchfiles-0.21.0-cp310-none-win32.whl", hash = "sha256:214cee7f9e09150d4fb42e24919a1e74d8c9b8a9306ed1474ecaddcd5479c293"}, + {file = "watchfiles-0.21.0-cp310-none-win_amd64.whl", hash = "sha256:1ad7247d79f9f55bb25ab1778fd47f32d70cf36053941f07de0b7c4e96b5d235"}, + {file = "watchfiles-0.21.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:668c265d90de8ae914f860d3eeb164534ba2e836811f91fecc7050416ee70aa7"}, + {file = "watchfiles-0.21.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a23092a992e61c3a6a70f350a56db7197242f3490da9c87b500f389b2d01eef"}, + {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e7941bbcfdded9c26b0bf720cb7e6fd803d95a55d2c14b4bd1f6a2772230c586"}, + {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11cd0c3100e2233e9c53106265da31d574355c288e15259c0d40a4405cbae317"}, + {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d78f30cbe8b2ce770160d3c08cff01b2ae9306fe66ce899b73f0409dc1846c1b"}, + {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6674b00b9756b0af620aa2a3346b01f8e2a3dc729d25617e1b89cf6af4a54eb1"}, + {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd7ac678b92b29ba630d8c842d8ad6c555abda1b9ef044d6cc092dacbfc9719d"}, + {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c873345680c1b87f1e09e0eaf8cf6c891b9851d8b4d3645e7efe2ec20a20cc7"}, + {file = "watchfiles-0.21.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:49f56e6ecc2503e7dbe233fa328b2be1a7797d31548e7a193237dcdf1ad0eee0"}, + {file = "watchfiles-0.21.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:02d91cbac553a3ad141db016e3350b03184deaafeba09b9d6439826ee594b365"}, + {file = "watchfiles-0.21.0-cp311-none-win32.whl", hash = "sha256:ebe684d7d26239e23d102a2bad2a358dedf18e462e8808778703427d1f584400"}, + {file = "watchfiles-0.21.0-cp311-none-win_amd64.whl", hash = "sha256:4566006aa44cb0d21b8ab53baf4b9c667a0ed23efe4aaad8c227bfba0bf15cbe"}, + {file = "watchfiles-0.21.0-cp311-none-win_arm64.whl", hash = "sha256:c550a56bf209a3d987d5a975cdf2063b3389a5d16caf29db4bdddeae49f22078"}, + {file = "watchfiles-0.21.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:51ddac60b96a42c15d24fbdc7a4bfcd02b5a29c047b7f8bf63d3f6f5a860949a"}, + {file = "watchfiles-0.21.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:511f0b034120cd1989932bf1e9081aa9fb00f1f949fbd2d9cab6264916ae89b1"}, + {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cfb92d49dbb95ec7a07511bc9efb0faff8fe24ef3805662b8d6808ba8409a71a"}, + {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f92944efc564867bbf841c823c8b71bb0be75e06b8ce45c084b46411475a915"}, + {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:642d66b75eda909fd1112d35c53816d59789a4b38c141a96d62f50a3ef9b3360"}, + {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d23bcd6c8eaa6324fe109d8cac01b41fe9a54b8c498af9ce464c1aeeb99903d6"}, + {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18d5b4da8cf3e41895b34e8c37d13c9ed294954907929aacd95153508d5d89d7"}, + {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b8d1eae0f65441963d805f766c7e9cd092f91e0c600c820c764a4ff71a0764c"}, + {file = "watchfiles-0.21.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1fd9a5205139f3c6bb60d11f6072e0552f0a20b712c85f43d42342d162be1235"}, + {file = "watchfiles-0.21.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a1e3014a625bcf107fbf38eece0e47fa0190e52e45dc6eee5a8265ddc6dc5ea7"}, + {file = "watchfiles-0.21.0-cp312-none-win32.whl", hash = "sha256:9d09869f2c5a6f2d9df50ce3064b3391d3ecb6dced708ad64467b9e4f2c9bef3"}, + {file = "watchfiles-0.21.0-cp312-none-win_amd64.whl", hash = "sha256:18722b50783b5e30a18a8a5db3006bab146d2b705c92eb9a94f78c72beb94094"}, + {file = "watchfiles-0.21.0-cp312-none-win_arm64.whl", hash = "sha256:a3b9bec9579a15fb3ca2d9878deae789df72f2b0fdaf90ad49ee389cad5edab6"}, + {file = "watchfiles-0.21.0-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:4ea10a29aa5de67de02256a28d1bf53d21322295cb00bd2d57fcd19b850ebd99"}, + {file = "watchfiles-0.21.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:40bca549fdc929b470dd1dbfcb47b3295cb46a6d2c90e50588b0a1b3bd98f429"}, + {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9b37a7ba223b2f26122c148bb8d09a9ff312afca998c48c725ff5a0a632145f7"}, + {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec8c8900dc5c83650a63dd48c4d1d245343f904c4b64b48798c67a3767d7e165"}, + {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8ad3fe0a3567c2f0f629d800409cd528cb6251da12e81a1f765e5c5345fd0137"}, + {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d353c4cfda586db2a176ce42c88f2fc31ec25e50212650c89fdd0f560ee507b"}, + {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:83a696da8922314ff2aec02987eefb03784f473281d740bf9170181829133765"}, + {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a03651352fc20975ee2a707cd2d74a386cd303cc688f407296064ad1e6d1562"}, + {file = "watchfiles-0.21.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3ad692bc7792be8c32918c699638b660c0de078a6cbe464c46e1340dadb94c19"}, + {file = "watchfiles-0.21.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06247538e8253975bdb328e7683f8515ff5ff041f43be6c40bff62d989b7d0b0"}, + {file = "watchfiles-0.21.0-cp38-none-win32.whl", hash = "sha256:9a0aa47f94ea9a0b39dd30850b0adf2e1cd32a8b4f9c7aa443d852aacf9ca214"}, + {file = "watchfiles-0.21.0-cp38-none-win_amd64.whl", hash = "sha256:8d5f400326840934e3507701f9f7269247f7c026d1b6cfd49477d2be0933cfca"}, + {file = "watchfiles-0.21.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:7f762a1a85a12cc3484f77eee7be87b10f8c50b0b787bb02f4e357403cad0c0e"}, + {file = "watchfiles-0.21.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6e9be3ef84e2bb9710f3f777accce25556f4a71e15d2b73223788d528fcc2052"}, + {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4c48a10d17571d1275701e14a601e36959ffada3add8cdbc9e5061a6e3579a5d"}, + {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c889025f59884423428c261f212e04d438de865beda0b1e1babab85ef4c0f01"}, + {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:66fac0c238ab9a2e72d026b5fb91cb902c146202bbd29a9a1a44e8db7b710b6f"}, + {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4a21f71885aa2744719459951819e7bf5a906a6448a6b2bbce8e9cc9f2c8128"}, + {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c9198c989f47898b2c22201756f73249de3748e0fc9de44adaf54a8b259cc0c"}, + {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f57c4461cd24fda22493109c45b3980863c58a25b8bec885ca8bea6b8d4b28"}, + {file = "watchfiles-0.21.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:853853cbf7bf9408b404754b92512ebe3e3a83587503d766d23e6bf83d092ee6"}, + {file = "watchfiles-0.21.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d5b1dc0e708fad9f92c296ab2f948af403bf201db8fb2eb4c8179db143732e49"}, + {file = "watchfiles-0.21.0-cp39-none-win32.whl", hash = "sha256:59137c0c6826bd56c710d1d2bda81553b5e6b7c84d5a676747d80caf0409ad94"}, + {file = "watchfiles-0.21.0-cp39-none-win_amd64.whl", hash = "sha256:6cb8fdc044909e2078c248986f2fc76f911f72b51ea4a4fbbf472e01d14faa58"}, + {file = "watchfiles-0.21.0-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ab03a90b305d2588e8352168e8c5a1520b721d2d367f31e9332c4235b30b8994"}, + {file = "watchfiles-0.21.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:927c589500f9f41e370b0125c12ac9e7d3a2fd166b89e9ee2828b3dda20bfe6f"}, + {file = "watchfiles-0.21.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bd467213195e76f838caf2c28cd65e58302d0254e636e7c0fca81efa4a2e62c"}, + {file = "watchfiles-0.21.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02b73130687bc3f6bb79d8a170959042eb56eb3a42df3671c79b428cd73f17cc"}, + {file = "watchfiles-0.21.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:08dca260e85ffae975448e344834d765983237ad6dc308231aa16e7933db763e"}, + {file = "watchfiles-0.21.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:3ccceb50c611c433145502735e0370877cced72a6c70fd2410238bcbc7fe51d8"}, + {file = "watchfiles-0.21.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57d430f5fb63fea141ab71ca9c064e80de3a20b427ca2febcbfcef70ff0ce895"}, + {file = "watchfiles-0.21.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dd5fad9b9c0dd89904bbdea978ce89a2b692a7ee8a0ce19b940e538c88a809c"}, + {file = "watchfiles-0.21.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:be6dd5d52b73018b21adc1c5d28ac0c68184a64769052dfeb0c5d9998e7f56a2"}, + {file = "watchfiles-0.21.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b3cab0e06143768499384a8a5efb9c4dc53e19382952859e4802f294214f36ec"}, + {file = "watchfiles-0.21.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c6ed10c2497e5fedadf61e465b3ca12a19f96004c15dcffe4bd442ebadc2d85"}, + {file = "watchfiles-0.21.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43babacef21c519bc6631c5fce2a61eccdfc011b4bcb9047255e9620732c8097"}, + {file = "watchfiles-0.21.0.tar.gz", hash = "sha256:c76c635fabf542bb78524905718c39f736a98e5ab25b23ec6d4abede1a85a6a3"}, +] + +[package.dependencies] +anyio = ">=3.0.0" + +[[package]] +name = "websockets" +version = "12.0" +description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"}, + {file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"}, + {file = "websockets-12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603"}, + {file = "websockets-12.0-cp310-cp310-win32.whl", hash = "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f"}, + {file = "websockets-12.0-cp310-cp310-win_amd64.whl", hash = "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf"}, + {file = "websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4"}, + {file = "websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f"}, + {file = "websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53"}, + {file = "websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402"}, + {file = "websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b"}, + {file = "websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df"}, + {file = "websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc"}, + {file = "websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113"}, + {file = "websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d"}, + {file = "websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f"}, + {file = "websockets-12.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438"}, + {file = "websockets-12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2"}, + {file = "websockets-12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7"}, + {file = "websockets-12.0-cp38-cp38-win32.whl", hash = "sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62"}, + {file = "websockets-12.0-cp38-cp38-win_amd64.whl", hash = "sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892"}, + {file = "websockets-12.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d"}, + {file = "websockets-12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28"}, + {file = "websockets-12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9"}, + {file = "websockets-12.0-cp39-cp39-win32.whl", hash = "sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6"}, + {file = "websockets-12.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8"}, + {file = "websockets-12.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b"}, + {file = "websockets-12.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30"}, + {file = "websockets-12.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2"}, + {file = "websockets-12.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468"}, + {file = "websockets-12.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611"}, + {file = "websockets-12.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370"}, + {file = "websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e"}, + {file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.11" +content-hash = "5436cf9c1876079a2603c0cca2b263bbea347ae1181f0373b9912cfda7a36e5e" diff --git a/syft/pkg/cataloger/python/test-fixtures/poetry/nested-extras/pyproject.toml b/syft/pkg/cataloger/python/test-fixtures/poetry/nested-extras/pyproject.toml new file mode 100644 index 000000000..ef95caa7c --- /dev/null +++ b/syft/pkg/cataloger/python/test-fixtures/poetry/nested-extras/pyproject.toml @@ -0,0 +1,14 @@ +[tool.poetry] +name = "testpkg" +version = "0.1.0" +description = "" +authors = ["Alex Goodman "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.11" +fastapi = {extras = ["all"], version = "^0.111.0"} + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/syft/pkg/cataloger/python/test-fixtures/poetry/simple-deps/poetry.lock b/syft/pkg/cataloger/python/test-fixtures/poetry/simple-deps/poetry.lock new file mode 100644 index 000000000..9249bf7df --- /dev/null +++ b/syft/pkg/cataloger/python/test-fixtures/poetry/simple-deps/poetry.lock @@ -0,0 +1,166 @@ +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. + +[[package]] +name = "certifi" +version = "2024.2.2" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] + +[[package]] +name = "idna" +version = "3.7" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, + {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, +] + +[[package]] +name = "requests" +version = "2.32.2" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.8" +files = [ + {file = "requests-2.32.2-py3-none-any.whl", hash = "sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c"}, + {file = "requests-2.32.2.tar.gz", hash = "sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "urllib3" +version = "2.2.1" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, + {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.11" +content-hash = "bbde8c07caea5e9a5695c84bc6ec39ded1436ea0dcbfd59942a4afdff86126ca" diff --git a/syft/pkg/cataloger/python/test-fixtures/poetry/simple-deps/pyproject.toml b/syft/pkg/cataloger/python/test-fixtures/poetry/simple-deps/pyproject.toml new file mode 100644 index 000000000..da1205314 --- /dev/null +++ b/syft/pkg/cataloger/python/test-fixtures/poetry/simple-deps/pyproject.toml @@ -0,0 +1,14 @@ +[tool.poetry] +name = "testpkg" +version = "0.1.0" +description = "" +authors = ["Alex Goodman "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.11" +requests = "^2.32.2" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/syft/pkg/cataloger/redhat/dependency.go b/syft/pkg/cataloger/redhat/dependency.go index e5af127a8..38b9b2be4 100644 --- a/syft/pkg/cataloger/redhat/dependency.go +++ b/syft/pkg/cataloger/redhat/dependency.go @@ -45,8 +45,10 @@ func dbEntryDependencySpecifier(p pkg.Package) dependency.Specification { } return dependency.Specification{ - Provides: provides, - Requires: requires, + ProvidesRequires: dependency.ProvidesRequires{ + Provides: provides, + Requires: requires, + }, } } diff --git a/syft/pkg/cataloger/redhat/dependency_test.go b/syft/pkg/cataloger/redhat/dependency_test.go index de4c2e727..f8343eb18 100644 --- a/syft/pkg/cataloger/redhat/dependency_test.go +++ b/syft/pkg/cataloger/redhat/dependency_test.go @@ -25,8 +25,10 @@ func Test_dbEntryDependencySpecifier(t *testing.T) { }, }, want: dependency.Specification{ - Provides: []string{"package-c", "a-thing"}, - Requires: []string{"b-thing"}, + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"package-c", "a-thing"}, + Requires: []string{"b-thing"}, + }, }, }, { @@ -39,8 +41,10 @@ func Test_dbEntryDependencySpecifier(t *testing.T) { }, }, want: dependency.Specification{ - Provides: []string{"package-a", "libc.so.6(GLIBC_2.11)(64bit)"}, - Requires: []string{"config(bash)"}, + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"package-a", "libc.so.6(GLIBC_2.11)(64bit)"}, + Requires: []string{"config(bash)"}, + }, }, }, { @@ -53,8 +57,10 @@ func Test_dbEntryDependencySpecifier(t *testing.T) { }, }, want: dependency.Specification{ - Provides: []string{"package-a"}, - Requires: nil, + ProvidesRequires: dependency.ProvidesRequires{ + Provides: []string{"package-a"}, + Requires: nil, + }, }, }, } diff --git a/syft/pkg/python.go b/syft/pkg/python.go index 1d1d5bb92..cc08108a2 100644 --- a/syft/pkg/python.go +++ b/syft/pkg/python.go @@ -66,7 +66,22 @@ type PythonPipfileLockEntry struct { // PythonPoetryLockEntry represents a single package entry within a Pipfile.lock file. type PythonPoetryLockEntry struct { - Index string `mapstructure:"index" json:"index"` + Index string `mapstructure:"index" json:"index"` + Dependencies []PythonPoetryLockDependencyEntry `json:"dependencies"` + Extras []PythonPoetryLockExtraEntry `json:"extras,omitempty"` +} + +type PythonPoetryLockDependencyEntry struct { + Name string `json:"name"` + Version string `json:"version"` + Optional bool `json:"optional"` + Markers string `json:"markers,omitempty"` + Extras []string `json:"extras,omitempty"` +} + +type PythonPoetryLockExtraEntry struct { + Name string `json:"name"` + Dependencies []string `json:"dependencies"` } // PythonRequirementsEntry represents a single entry within a [*-]requirements.txt file. From 7508d75b2b24bd028230a4f627364dc5306915e8 Mon Sep 17 00:00:00 2001 From: Christopher Angelo Phillips <32073428+spiffcs@users.noreply.github.com> Date: Wed, 5 Jun 2024 11:31:38 -0700 Subject: [PATCH 016/284] fix: update unit tests to use pinned patch version (#2932) Signed-off-by: Christopher Phillips --- syft/pkg/cataloger/golang/cataloger_test.go | 8 ++++---- .../cataloger/golang/test-fixtures/image-small/Dockerfile | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/syft/pkg/cataloger/golang/cataloger_test.go b/syft/pkg/cataloger/golang/cataloger_test.go index ed8296565..0e1526658 100644 --- a/syft/pkg/cataloger/golang/cataloger_test.go +++ b/syft/pkg/cataloger/golang/cataloger_test.go @@ -31,7 +31,7 @@ func Test_PackageCataloger_Binary(t *testing.T) { "github.com/pierrec/lz4/v4 @ v4.1.2 (/run-me)", "github.com/ulikunitz/xz @ v0.5.9 (/run-me)", "github.com/xi2/xz @ v0.0.0-20171230120015-48954b6210f8 (/run-me)", - "stdlib @ go1.22.3 (/run-me)", + "stdlib @ go1.22.4 (/run-me)", }, expectedRels: []string{ "github.com/andybalholm/brotli @ v1.0.1 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", @@ -44,7 +44,7 @@ func Test_PackageCataloger_Binary(t *testing.T) { "github.com/pierrec/lz4/v4 @ v4.1.2 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", "github.com/ulikunitz/xz @ v0.5.9 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", "github.com/xi2/xz @ v0.0.0-20171230120015-48954b6210f8 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", - "stdlib @ go1.22.3 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", + "stdlib @ go1.22.4 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", }, }, { @@ -64,7 +64,7 @@ func Test_PackageCataloger_Binary(t *testing.T) { "github.com/pierrec/lz4/v4 @ v4.1.2 (/run-me)", "github.com/ulikunitz/xz @ v0.5.9 (/run-me)", "github.com/xi2/xz @ v0.0.0-20171230120015-48954b6210f8 (/run-me)", - "stdlib @ go1.22.3 (/run-me)", + "stdlib @ go1.22.4 (/run-me)", }, expectedRels: []string{ "github.com/andybalholm/brotli @ v1.0.1 (/run-me) [dependency-of] command-line-arguments @ (devel) (/run-me)", @@ -77,7 +77,7 @@ func Test_PackageCataloger_Binary(t *testing.T) { "github.com/pierrec/lz4/v4 @ v4.1.2 (/run-me) [dependency-of] command-line-arguments @ (devel) (/run-me)", "github.com/ulikunitz/xz @ v0.5.9 (/run-me) [dependency-of] command-line-arguments @ (devel) (/run-me)", "github.com/xi2/xz @ v0.0.0-20171230120015-48954b6210f8 (/run-me) [dependency-of] command-line-arguments @ (devel) (/run-me)", - "stdlib @ go1.22.3 (/run-me) [dependency-of] command-line-arguments @ (devel) (/run-me)", + "stdlib @ go1.22.4 (/run-me) [dependency-of] command-line-arguments @ (devel) (/run-me)", }, }, } diff --git a/syft/pkg/cataloger/golang/test-fixtures/image-small/Dockerfile b/syft/pkg/cataloger/golang/test-fixtures/image-small/Dockerfile index cf78c974b..be8d93780 100644 --- a/syft/pkg/cataloger/golang/test-fixtures/image-small/Dockerfile +++ b/syft/pkg/cataloger/golang/test-fixtures/image-small/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=linux/amd64 golang:1.22 AS builder +FROM --platform=linux/amd64 golang:1.22.4 AS builder RUN mkdir /app WORKDIR /app From d2fa5ed41cfd5bba963bbb46c65dd3a6fdeeba9e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jun 2024 11:57:43 -0700 Subject: [PATCH 017/284] chore(deps): bump github.com/CycloneDX/cyclonedx-go from 0.8.0 to 0.9.0 (#2931) Bumps [github.com/CycloneDX/cyclonedx-go](https://github.com/CycloneDX/cyclonedx-go) from 0.8.0 to 0.9.0. - [Release notes](https://github.com/CycloneDX/cyclonedx-go/releases) - [Changelog](https://github.com/CycloneDX/cyclonedx-go/blob/master/.goreleaser.yml) - [Commits](https://github.com/CycloneDX/cyclonedx-go/compare/v0.8.0...v0.9.0) --- updated-dependencies: - dependency-name: github.com/CycloneDX/cyclonedx-go dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6a5fbf45f..5144e2cd4 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/anchore/syft go 1.22.0 require ( - github.com/CycloneDX/cyclonedx-go v0.8.0 + github.com/CycloneDX/cyclonedx-go v0.9.0 github.com/Masterminds/semver v1.5.0 github.com/Masterminds/sprig/v3 v3.2.3 github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d diff --git a/go.sum b/go.sum index dbc546f18..69f75b7bb 100644 --- a/go.sum +++ b/go.sum @@ -58,8 +58,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/CycloneDX/cyclonedx-go v0.8.0 h1:FyWVj6x6hoJrui5uRQdYZcSievw3Z32Z88uYzG/0D6M= -github.com/CycloneDX/cyclonedx-go v0.8.0/go.mod h1:K2bA+324+Og0X84fA8HhN2X066K7Bxz4rpMQ4ZhjtSk= +github.com/CycloneDX/cyclonedx-go v0.9.0 h1:inaif7qD8bivyxp7XLgxUYtOXWtDez7+j72qKTMQTb8= +github.com/CycloneDX/cyclonedx-go v0.9.0/go.mod h1:NE/EWvzELOFlG6+ljX/QeMlVt9VKcTwu8u0ccsACEsw= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= From f11bb95c1e03c6612c8b54a97eb6f4782700f56a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jun 2024 11:57:54 -0700 Subject: [PATCH 018/284] chore(deps): bump golang.org/x/mod from 0.17.0 to 0.18.0 (#2930) Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.17.0 to 0.18.0. - [Commits](https://github.com/golang/mod/compare/v0.17.0...v0.18.0) --- updated-dependencies: - dependency-name: golang.org/x/mod dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5144e2cd4..2a73e6fa3 100644 --- a/go.mod +++ b/go.mod @@ -78,7 +78,7 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1 go.uber.org/goleak v1.3.0 - golang.org/x/mod v0.17.0 + golang.org/x/mod v0.18.0 golang.org/x/net v0.25.0 gopkg.in/yaml.v3 v3.0.1 modernc.org/sqlite v1.30.0 diff --git a/go.sum b/go.sum index 69f75b7bb..31c908abe 100644 --- a/go.sum +++ b/go.sum @@ -917,8 +917,8 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= From 2d5760145c3f9f70591cd895c454b611c2dcfab2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jun 2024 11:58:14 -0700 Subject: [PATCH 019/284] chore(deps): bump github/codeql-action from 3.25.7 to 3.25.8 (#2928) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.7 to 3.25.8. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/f079b8493333aace61c81488f8bd40919487bd9f...2e230e8fe0ad3a14a340ad0815ddb96d599d2aff) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 4d3d88a3a..4a0803f3a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f079b8493333aace61c81488f8bd40919487bd9f #v3.25.7 + uses: github/codeql-action/init@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff #v3.25.8 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@f079b8493333aace61c81488f8bd40919487bd9f #v3.25.7 + uses: github/codeql-action/autobuild@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff #v3.25.8 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f079b8493333aace61c81488f8bd40919487bd9f #v3.25.7 + uses: github/codeql-action/analyze@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff #v3.25.8 From f4c941f08de36f0a9a5e8ceb05cfc9188663ffbe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jun 2024 19:09:09 +0000 Subject: [PATCH 020/284] chore(deps): bump golang.org/x/net from 0.25.0 to 0.26.0 (#2929) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.25.0 to 0.26.0. - [Commits](https://github.com/golang/net/compare/v0.25.0...v0.26.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 2a73e6fa3..3470af47c 100644 --- a/go.mod +++ b/go.mod @@ -79,7 +79,7 @@ require ( github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1 go.uber.org/goleak v1.3.0 golang.org/x/mod v0.18.0 - golang.org/x/net v0.25.0 + golang.org/x/net v0.26.0 gopkg.in/yaml.v3 v3.0.1 modernc.org/sqlite v1.30.0 ) @@ -226,13 +226,13 @@ require ( go.opentelemetry.io/otel/trace v1.19.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect - golang.org/x/crypto v0.23.0 // indirect + golang.org/x/crypto v0.24.0 // indirect golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/term v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect - golang.org/x/tools v0.19.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/term v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect google.golang.org/grpc v1.59.0 // indirect diff --git a/go.sum b/go.sum index 31c908abe..87b4ca246 100644 --- a/go.sum +++ b/go.sum @@ -875,8 +875,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -966,8 +966,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1079,15 +1079,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1100,8 +1100,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1163,8 +1163,8 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= -golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From b608ab77e109b01269fafb0597ee1699ce02c308 Mon Sep 17 00:00:00 2001 From: Laurent Goderre Date: Wed, 5 Jun 2024 17:32:52 -0400 Subject: [PATCH 021/284] feat: classifier for util-linux (#2933) Signed-off-by: Laurent Goderre --- .../cataloger/binary/classifier_cataloger_test.go | 10 ++++++++++ syft/pkg/cataloger/binary/classifiers.go | 9 +++++++++ .../snippets/util-linux/2.37.4/linux-amd64/getopt | Bin 0 -> 348 bytes .../cataloger/binary/test-fixtures/config.yaml | 8 ++++++++ 4 files changed, 27 insertions(+) create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/util-linux/2.37.4/linux-amd64/getopt diff --git a/syft/pkg/cataloger/binary/classifier_cataloger_test.go b/syft/pkg/cataloger/binary/classifier_cataloger_test.go index 7ec368b85..e0f71998d 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger_test.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger_test.go @@ -616,6 +616,16 @@ func Test_Cataloger_PositiveCases(t *testing.T) { Metadata: metadata("busybox-binary", "[", "busybox"), }, }, + { + logicalFixture: `util-linux/2.37.4/linux-amd64`, + expected: pkg.Package{ + Name: "util-linux", + Version: "2.37.4", + PURL: "pkg:generic/util-linux@2.37.4", + Locations: locations("getopt"), + Metadata: metadata("util-linux-binary"), + }, + }, { logicalFixture: "java-jre-openjdk/1.8.0_352-b08/linux-amd64", expected: pkg.Package{ diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index c7ebafa97..229c51339 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -173,6 +173,15 @@ func DefaultClassifiers() []Classifier { PURL: mustPURL("pkg:generic/busybox@version"), CPEs: singleCPE("cpe:2.3:a:busybox:busybox:*:*:*:*:*:*:*:*"), }, + { + Class: "util-linux-binary", + FileGlob: "**/getopt", + EvidenceMatcher: FileContentsVersionMatcher( + `\x00util-linux\s(?P[0-9]+\.[0-9]+\.[0-9]+)\x00`), + Package: "util-linux", + PURL: mustPURL("pkg:generic/util-linux@version"), + CPEs: singleCPE("cpe:2.3:a:kernel:util-linux:*:*:*:*:*:*:*:*"), + }, { Class: "haproxy-binary", FileGlob: "**/haproxy", diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/util-linux/2.37.4/linux-amd64/getopt b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/util-linux/2.37.4/linux-amd64/getopt new file mode 100644 index 0000000000000000000000000000000000000000..e27f0695fa6e6387b79bc033c057982018b0894f GIT binary patch literal 348 zcmYL_%WA_g6hyt&S6oQ5bkN(f3HgcARmkG%MXFJ9X-194Sv$n2qp%})XszEf zTI$0fqLq6X4VPX~qn-6g;*!GO7-dW`CbdST20a?9#o!tDLK_rz-{%eOmJK6ZlCC zC)ph<#H~EwSV>1dD$Zdd9UR$Ph4U__wr$Dt1 Date: Thu, 6 Jun 2024 09:56:47 -0400 Subject: [PATCH 022/284] chore(deps): bump github.com/docker/docker (#2935) Bumps [github.com/docker/docker](https://github.com/docker/docker) from 26.1.3+incompatible to 26.1.4+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v26.1.3...v26.1.4) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3470af47c..e1570c434 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/dave/jennifer v1.7.0 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da github.com/distribution/reference v0.6.0 - github.com/docker/docker v26.1.3+incompatible + github.com/docker/docker v26.1.4+incompatible github.com/dustin/go-humanize v1.0.1 github.com/elliotchance/phpserialize v1.4.0 github.com/facebookincubator/nvdtools v0.1.5 diff --git a/go.sum b/go.sum index 87b4ca246..020c825dd 100644 --- a/go.sum +++ b/go.sum @@ -229,8 +229,8 @@ github.com/docker/cli v24.0.0+incompatible h1:0+1VshNwBQzQAx9lOl+OYCTCEAD8fKs/qe github.com/docker/cli v24.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v26.1.3+incompatible h1:lLCzRbrVZrljpVNobJu1J2FHk8V0s4BawoZippkc+xo= -github.com/docker/docker v26.1.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU= +github.com/docker/docker v26.1.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= From 5cdc0845fb94bd87c05dd0f400244ed8535f7923 Mon Sep 17 00:00:00 2001 From: Brian Ebarb <116963850+brian-ebarb@users.noreply.github.com> Date: Thu, 6 Jun 2024 09:10:53 -0500 Subject: [PATCH 023/284] feat: add license field to ELF binary package metadata (#2890) Signed-off-by: Brian Ebarb feat: add License component to elf binary packages Signed-off-by: Brian Ebarb feat: fix elf_package_cataloger test feat: elf package cataloger unit test updates --- syft/pkg/cataloger/binary/elf_package.go | 4 ++-- syft/pkg/cataloger/binary/elf_package_cataloger.go | 2 +- syft/pkg/cataloger/binary/elf_package_cataloger_test.go | 7 +++++++ syft/pkg/cataloger/binary/elf_package_test.go | 2 +- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/syft/pkg/cataloger/binary/elf_package.go b/syft/pkg/cataloger/binary/elf_package.go index 4c7e5c25f..3e463b025 100644 --- a/syft/pkg/cataloger/binary/elf_package.go +++ b/syft/pkg/cataloger/binary/elf_package.go @@ -6,11 +6,11 @@ import ( "github.com/anchore/syft/syft/pkg" ) -func newELFPackage(metadata elfBinaryPackageNotes, locations file.LocationSet, licenses []pkg.License) pkg.Package { +func newELFPackage(metadata elfBinaryPackageNotes, locations file.LocationSet) pkg.Package { p := pkg.Package{ Name: metadata.Name, Version: metadata.Version, - Licenses: pkg.NewLicenseSet(licenses...), + Licenses: pkg.NewLicenseSet(pkg.NewLicense(metadata.License)), PURL: packageURL(metadata), Type: pkg.BinaryPkg, Locations: locations, diff --git a/syft/pkg/cataloger/binary/elf_package_cataloger.go b/syft/pkg/cataloger/binary/elf_package_cataloger.go index 9dea999e6..2e65a8376 100644 --- a/syft/pkg/cataloger/binary/elf_package_cataloger.go +++ b/syft/pkg/cataloger/binary/elf_package_cataloger.go @@ -79,7 +79,7 @@ func (c *elfPackageCataloger) Catalog(_ context.Context, resolver file.Resolver) } // create a package for each unique name/version pair (based on the first note found) - pkgs = append(pkgs, newELFPackage(notes[0], noteLocations, nil)) + pkgs = append(pkgs, newELFPackage(notes[0], noteLocations)) } // why not return relationships? We have an executable cataloger that will note the dynamic libraries imported by diff --git a/syft/pkg/cataloger/binary/elf_package_cataloger_test.go b/syft/pkg/cataloger/binary/elf_package_cataloger_test.go index 10d979d04..44f689d00 100644 --- a/syft/pkg/cataloger/binary/elf_package_cataloger_test.go +++ b/syft/pkg/cataloger/binary/elf_package_cataloger_test.go @@ -20,6 +20,10 @@ func Test_ELF_Package_Cataloger(t *testing.T) { file.NewVirtualLocation("/usr/local/bin/elftests/elfbinwithsisterlib/lib/libhello_world.so", "/usr/local/bin/elftests/elfbinwithsisterlib/lib/libhello_world.so"), file.NewVirtualLocation("/usr/local/bin/elftests/elfbinwithsisterlib/lib/libhello_world2.so", "/usr/local/bin/elftests/elfbinwithsisterlib/lib/libhello_world2.so"), ), + Licenses: pkg.NewLicenseSet( + pkg.License{Value: "MIT", SPDXExpression: "MIT", Type: "declared"}, + ), + Language: "", Type: pkg.BinaryPkg, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ @@ -40,6 +44,9 @@ func Test_ELF_Package_Cataloger(t *testing.T) { file.NewLocation("/usr/local/bin/elftests/elfbinwithsisterlib/bin/elfwithparallellibbin1").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), file.NewLocation("/usr/local/bin/elftests/elfbinwithsisterlib/bin/elfwithparallellibbin2").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Licenses: pkg.NewLicenseSet( + pkg.License{Value: "MIT", SPDXExpression: "MIT", Type: "declared"}, + ), Language: "", Type: pkg.BinaryPkg, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ diff --git a/syft/pkg/cataloger/binary/elf_package_test.go b/syft/pkg/cataloger/binary/elf_package_test.go index a14948a7f..6a1020ca0 100644 --- a/syft/pkg/cataloger/binary/elf_package_test.go +++ b/syft/pkg/cataloger/binary/elf_package_test.go @@ -82,7 +82,7 @@ func Test_newELFPackage(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - actual := newELFPackage(test.metadata, file.NewLocationSet(), nil) + actual := newELFPackage(test.metadata, file.NewLocationSet()) if diff := cmp.Diff(test.expected, actual, cmpopts.IgnoreFields(pkg.Package{}, "id"), cmpopts.IgnoreUnexported(pkg.Package{}, file.LocationSet{}, pkg.LicenseSet{})); diff != "" { t.Errorf("newELFPackage() mismatch (-want +got):\n%s", diff) } From 6e16396d1842030cd6f0bd20c0fe1ca2c0b0d729 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Thu, 6 Jun 2024 10:29:55 -0400 Subject: [PATCH 024/284] remove dco workflow (#2936) Signed-off-by: Alex Goodman --- .github/workflows/dco.yaml | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 .github/workflows/dco.yaml diff --git a/.github/workflows/dco.yaml b/.github/workflows/dco.yaml deleted file mode 100644 index cf759c79b..000000000 --- a/.github/workflows/dco.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: DCO -on: - pull_request: - push: - branches: - - main -jobs: - DCO: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Setup Python 3.x - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - - name: Check DCO - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - pip3 install -U dco-check - dco-check --verbose --exclude-pattern 'dependabot\[bot\]@users\.noreply\.github\.com' \ No newline at end of file From bc20e66d084b68dafeaedda3e3f142c3386afb41 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Fri, 7 Jun 2024 16:55:32 +0000 Subject: [PATCH 025/284] chore(deps): update tools to latest versions (#2940) * chore(deps): update tools to latest versions Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * chore: update header and deprecated fields Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> --------- Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 4 ++-- .goreleaser.yaml | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.binny.yaml b/.binny.yaml index cdedcf26b..d5cb34429 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -2,7 +2,7 @@ tools: # we want to use a pinned version of binny to manage the toolchain (so binny manages itself!) - name: binny version: - want: v0.7.0 + want: v0.8.0 method: github-release with: repo: anchore/binny @@ -58,7 +58,7 @@ tools: # used to release all artifacts - name: goreleaser version: - want: v1.26.2 + want: v2.0.0 method: github-release with: repo: goreleaser/goreleaser diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 762d87d3e..a8fc7711f 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -1,3 +1,5 @@ +version: 2 + release: prerelease: auto draft: false @@ -80,7 +82,7 @@ nfpms: - deb brews: - - tap: + - repository: owner: anchore name: homebrew-syft token: "{{.Env.GITHUB_BREW_TOKEN}}" From 254a562b4e3d5ad6c3f471342ae0107d570b5eb9 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Fri, 7 Jun 2024 14:38:54 -0400 Subject: [PATCH 026/284] Add support for reading ELF package notes with section header (#2939) * add support for reading ELF package notes with section header Signed-off-by: Alex Goodman * add systemd elf package fields to json schema Signed-off-by: Alex Goodman --------- Signed-off-by: Alex Goodman --- internal/constants.go | 2 +- schema/json/schema-16.0.14.json | 2537 +++++++++++++++++ schema/json/schema-latest.json | 16 +- syft/pkg/binary.go | 33 +- syft/pkg/cataloger/binary/elf_package.go | 55 +- .../cataloger/binary/elf_package_cataloger.go | 41 +- .../binary/elf_package_cataloger_test.go | 147 +- syft/pkg/cataloger/binary/elf_package_test.go | 88 +- .../image-fedora-32bit/Dockerfile | 5 + .../image-fedora-64bit/Dockerfile | 5 + 10 files changed, 2861 insertions(+), 68 deletions(-) create mode 100644 schema/json/schema-16.0.14.json create mode 100644 syft/pkg/cataloger/binary/test-fixtures/image-fedora-32bit/Dockerfile create mode 100644 syft/pkg/cataloger/binary/test-fixtures/image-fedora-64bit/Dockerfile diff --git a/internal/constants.go b/internal/constants.go index 37079fd78..478556fdb 100644 --- a/internal/constants.go +++ b/internal/constants.go @@ -3,5 +3,5 @@ package internal const ( // JSONSchemaVersion is the current schema version output by the JSON encoder // This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment. - JSONSchemaVersion = "16.0.13" + JSONSchemaVersion = "16.0.14" ) diff --git a/schema/json/schema-16.0.14.json b/schema/json/schema-16.0.14.json new file mode 100644 index 000000000..028f3004b --- /dev/null +++ b/schema/json/schema-16.0.14.json @@ -0,0 +1,2537 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "anchore.io/schema/syft/json/16.0.14/document", + "$ref": "#/$defs/Document", + "$defs": { + "AlpmDbEntry": { + "properties": { + "basepackage": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "packager": { + "type": "string" + }, + "url": { + "type": "string" + }, + "validation": { + "type": "string" + }, + "reason": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "backup": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "basepackage", + "package", + "version", + "description", + "architecture", + "size", + "packager", + "url", + "validation", + "reason", + "files", + "backup" + ] + }, + "AlpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "type": { + "type": "string" + }, + "uid": { + "type": "string" + }, + "gid": { + "type": "string" + }, + "time": { + "type": "string", + "format": "date-time" + }, + "size": { + "type": "string" + }, + "link": { + "type": "string" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object" + }, + "ApkDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "originPackage": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "version": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "url": { + "type": "string" + }, + "description": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "installedSize": { + "type": "integer" + }, + "pullDependencies": { + "items": { + "type": "string" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "pullChecksum": { + "type": "string" + }, + "gitCommitOfApkPort": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/ApkFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "originPackage", + "maintainer", + "version", + "architecture", + "url", + "description", + "size", + "installedSize", + "pullDependencies", + "provides", + "pullChecksum", + "gitCommitOfApkPort", + "files" + ] + }, + "ApkFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "ownerUid": { + "type": "string" + }, + "ownerGid": { + "type": "string" + }, + "permissions": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "BinarySignature": { + "properties": { + "matches": { + "items": { + "$ref": "#/$defs/ClassifierMatch" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "matches" + ] + }, + "CConanFileEntry": { + "properties": { + "ref": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanInfoEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "build_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "py_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "options": { + "$ref": "#/$defs/KeyValues" + }, + "path": { + "type": "string" + }, + "context": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockV2Entry": { + "properties": { + "ref": { + "type": "string" + }, + "packageID": { + "type": "string" + }, + "username": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "recipeRevision": { + "type": "string" + }, + "packageRevision": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CPE": { + "properties": { + "cpe": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "cpe" + ] + }, + "ClassifierMatch": { + "properties": { + "classifier": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Location" + } + }, + "type": "object", + "required": [ + "classifier", + "location" + ] + }, + "CocoaPodfileLockEntry": { + "properties": { + "checksum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "checksum" + ] + }, + "Coordinates": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "DartPubspecLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hosted_url": { + "type": "string" + }, + "vcs_url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Descriptor": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "configuration": true + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Digest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "Document": { + "properties": { + "artifacts": { + "items": { + "$ref": "#/$defs/Package" + }, + "type": "array" + }, + "artifactRelationships": { + "items": { + "$ref": "#/$defs/Relationship" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/File" + }, + "type": "array" + }, + "source": { + "$ref": "#/$defs/Source" + }, + "distro": { + "$ref": "#/$defs/LinuxRelease" + }, + "descriptor": { + "$ref": "#/$defs/Descriptor" + }, + "schema": { + "$ref": "#/$defs/Schema" + } + }, + "type": "object", + "required": [ + "artifacts", + "artifactRelationships", + "source", + "distro", + "descriptor", + "schema" + ] + }, + "DotnetDepsEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "path": { + "type": "string" + }, + "sha512": { + "type": "string" + }, + "hashPath": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "path", + "sha512", + "hashPath" + ] + }, + "DotnetPortableExecutableEntry": { + "properties": { + "assemblyVersion": { + "type": "string" + }, + "legalCopyright": { + "type": "string" + }, + "comments": { + "type": "string" + }, + "internalName": { + "type": "string" + }, + "companyName": { + "type": "string" + }, + "productName": { + "type": "string" + }, + "productVersion": { + "type": "string" + } + }, + "type": "object", + "required": [ + "assemblyVersion", + "legalCopyright", + "companyName", + "productName", + "productVersion" + ] + }, + "DpkgDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ] + }, + "DpkgFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "isConfigFile": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "path", + "isConfigFile" + ] + }, + "ELFSecurityFeatures": { + "properties": { + "symbolTableStripped": { + "type": "boolean" + }, + "stackCanary": { + "type": "boolean" + }, + "nx": { + "type": "boolean" + }, + "relRO": { + "type": "string" + }, + "pie": { + "type": "boolean" + }, + "dso": { + "type": "boolean" + }, + "safeStack": { + "type": "boolean" + }, + "cfi": { + "type": "boolean" + }, + "fortify": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "symbolTableStripped", + "nx", + "relRO", + "pie", + "dso" + ] + }, + "ElfBinaryPackageNoteJsonPayload": { + "properties": { + "type": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "osCPE": { + "type": "string" + }, + "os": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "system": { + "type": "string" + }, + "vendor": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "commit": { + "type": "string" + } + }, + "type": "object" + }, + "ElixirMixLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "ErlangRebarLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "Executable": { + "properties": { + "format": { + "type": "string" + }, + "hasExports": { + "type": "boolean" + }, + "hasEntrypoint": { + "type": "boolean" + }, + "importedLibraries": { + "items": { + "type": "string" + }, + "type": "array" + }, + "elfSecurityFeatures": { + "$ref": "#/$defs/ELFSecurityFeatures" + } + }, + "type": "object", + "required": [ + "format", + "hasExports", + "hasEntrypoint", + "importedLibraries" + ] + }, + "File": { + "properties": { + "id": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Coordinates" + }, + "metadata": { + "$ref": "#/$defs/FileMetadataEntry" + }, + "contents": { + "type": "string" + }, + "digests": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/FileLicense" + }, + "type": "array" + }, + "executable": { + "$ref": "#/$defs/Executable" + } + }, + "type": "object", + "required": [ + "id", + "location" + ] + }, + "FileLicense": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "evidence": { + "$ref": "#/$defs/FileLicenseEvidence" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type" + ] + }, + "FileLicenseEvidence": { + "properties": { + "confidence": { + "type": "integer" + }, + "offset": { + "type": "integer" + }, + "extent": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "confidence", + "offset", + "extent" + ] + }, + "FileMetadataEntry": { + "properties": { + "mode": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "linkDestination": { + "type": "string" + }, + "userID": { + "type": "integer" + }, + "groupID": { + "type": "integer" + }, + "mimeType": { + "type": "string" + }, + "size": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "mode", + "type", + "userID", + "groupID", + "mimeType", + "size" + ] + }, + "GoModuleBuildinfoEntry": { + "properties": { + "goBuildSettings": { + "$ref": "#/$defs/KeyValues" + }, + "goCompiledVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "h1Digest": { + "type": "string" + }, + "mainModule": { + "type": "string" + }, + "goCryptoSettings": { + "items": { + "type": "string" + }, + "type": "array" + }, + "goExperiments": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "goCompiledVersion", + "architecture" + ] + }, + "GoModuleEntry": { + "properties": { + "h1Digest": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackEntry": { + "properties": { + "pkgHash": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackLockEntry": { + "properties": { + "pkgHash": { + "type": "string" + }, + "snapshotURL": { + "type": "string" + } + }, + "type": "object" + }, + "IDLikes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "JavaArchive": { + "properties": { + "virtualPath": { + "type": "string" + }, + "manifest": { + "$ref": "#/$defs/JavaManifest" + }, + "pomProperties": { + "$ref": "#/$defs/JavaPomProperties" + }, + "pomProject": { + "$ref": "#/$defs/JavaPomProject" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "virtualPath" + ] + }, + "JavaManifest": { + "properties": { + "main": { + "$ref": "#/$defs/KeyValues" + }, + "sections": { + "items": { + "$ref": "#/$defs/KeyValues" + }, + "type": "array" + } + }, + "type": "object" + }, + "JavaPomParent": { + "properties": { + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object", + "required": [ + "groupId", + "artifactId", + "version" + ] + }, + "JavaPomProject": { + "properties": { + "path": { + "type": "string" + }, + "parent": { + "$ref": "#/$defs/JavaPomParent" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "groupId", + "artifactId", + "version", + "name" + ] + }, + "JavaPomProperties": { + "properties": { + "path": { + "type": "string" + }, + "name": { + "type": "string" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "extraFields": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "name", + "groupId", + "artifactId", + "version" + ] + }, + "JavascriptNpmPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "private": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "homepage", + "description", + "url", + "private" + ] + }, + "JavascriptNpmPackageLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "JavascriptYarnLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "KeyValue": { + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "key", + "value" + ] + }, + "KeyValues": { + "items": { + "$ref": "#/$defs/KeyValue" + }, + "type": "array" + }, + "License": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "urls": { + "items": { + "type": "string" + }, + "type": "array" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type", + "urls", + "locations" + ] + }, + "LinuxKernelArchive": { + "properties": { + "name": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "version": { + "type": "string" + }, + "extendedVersion": { + "type": "string" + }, + "buildTime": { + "type": "string" + }, + "author": { + "type": "string" + }, + "format": { + "type": "string" + }, + "rwRootFS": { + "type": "boolean" + }, + "swapDevice": { + "type": "integer" + }, + "rootDevice": { + "type": "integer" + }, + "videoMode": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "architecture", + "version" + ] + }, + "LinuxKernelModule": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "path": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "license": { + "type": "string" + }, + "kernelVersion": { + "type": "string" + }, + "versionMagic": { + "type": "string" + }, + "parameters": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/LinuxKernelModuleParameter" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "LinuxKernelModuleParameter": { + "properties": { + "type": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "type": "object" + }, + "LinuxRelease": { + "properties": { + "prettyName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" + }, + "idLike": { + "$ref": "#/$defs/IDLikes" + }, + "version": { + "type": "string" + }, + "versionID": { + "type": "string" + }, + "versionCodename": { + "type": "string" + }, + "buildID": { + "type": "string" + }, + "imageID": { + "type": "string" + }, + "imageVersion": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "variantID": { + "type": "string" + }, + "homeURL": { + "type": "string" + }, + "supportURL": { + "type": "string" + }, + "bugReportURL": { + "type": "string" + }, + "privacyPolicyURL": { + "type": "string" + }, + "cpeName": { + "type": "string" + }, + "supportEnd": { + "type": "string" + } + }, + "type": "object" + }, + "Location": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + }, + "accessPath": { + "type": "string" + }, + "annotations": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "accessPath" + ] + }, + "LuarocksPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "dependencies": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "name", + "version", + "license", + "homepage", + "description", + "url", + "dependencies" + ] + }, + "MicrosoftKbPatch": { + "properties": { + "product_id": { + "type": "string" + }, + "kb": { + "type": "string" + } + }, + "type": "object", + "required": [ + "product_id", + "kb" + ] + }, + "NixStoreEntry": { + "properties": { + "outputHash": { + "type": "string" + }, + "output": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "outputHash", + "files" + ] + }, + "Package": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "foundBy": { + "type": "string" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "licenses": { + "$ref": "#/$defs/licenses" + }, + "language": { + "type": "string" + }, + "cpes": { + "$ref": "#/$defs/cpes" + }, + "purl": { + "type": "string" + }, + "metadataType": { + "type": "string" + }, + "metadata": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/AlpmDbEntry" + }, + { + "$ref": "#/$defs/ApkDbEntry" + }, + { + "$ref": "#/$defs/BinarySignature" + }, + { + "$ref": "#/$defs/CConanFileEntry" + }, + { + "$ref": "#/$defs/CConanInfoEntry" + }, + { + "$ref": "#/$defs/CConanLockEntry" + }, + { + "$ref": "#/$defs/CConanLockV2Entry" + }, + { + "$ref": "#/$defs/CocoaPodfileLockEntry" + }, + { + "$ref": "#/$defs/DartPubspecLockEntry" + }, + { + "$ref": "#/$defs/DotnetDepsEntry" + }, + { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + }, + { + "$ref": "#/$defs/DpkgDbEntry" + }, + { + "$ref": "#/$defs/ElfBinaryPackageNoteJsonPayload" + }, + { + "$ref": "#/$defs/ElixirMixLockEntry" + }, + { + "$ref": "#/$defs/ErlangRebarLockEntry" + }, + { + "$ref": "#/$defs/GoModuleBuildinfoEntry" + }, + { + "$ref": "#/$defs/GoModuleEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackLockEntry" + }, + { + "$ref": "#/$defs/JavaArchive" + }, + { + "$ref": "#/$defs/JavascriptNpmPackage" + }, + { + "$ref": "#/$defs/JavascriptNpmPackageLockEntry" + }, + { + "$ref": "#/$defs/JavascriptYarnLockEntry" + }, + { + "$ref": "#/$defs/LinuxKernelArchive" + }, + { + "$ref": "#/$defs/LinuxKernelModule" + }, + { + "$ref": "#/$defs/LuarocksPackage" + }, + { + "$ref": "#/$defs/MicrosoftKbPatch" + }, + { + "$ref": "#/$defs/NixStoreEntry" + }, + { + "$ref": "#/$defs/PhpComposerInstalledEntry" + }, + { + "$ref": "#/$defs/PhpComposerLockEntry" + }, + { + "$ref": "#/$defs/PhpPeclEntry" + }, + { + "$ref": "#/$defs/PortageDbEntry" + }, + { + "$ref": "#/$defs/PythonPackage" + }, + { + "$ref": "#/$defs/PythonPipRequirementsEntry" + }, + { + "$ref": "#/$defs/PythonPipfileLockEntry" + }, + { + "$ref": "#/$defs/PythonPoetryLockEntry" + }, + { + "$ref": "#/$defs/RDescription" + }, + { + "$ref": "#/$defs/RpmArchive" + }, + { + "$ref": "#/$defs/RpmDbEntry" + }, + { + "$ref": "#/$defs/RubyGemspec" + }, + { + "$ref": "#/$defs/RustCargoAuditEntry" + }, + { + "$ref": "#/$defs/RustCargoLockEntry" + }, + { + "$ref": "#/$defs/SwiftPackageManagerLockEntry" + }, + { + "$ref": "#/$defs/WordpressPluginEntry" + } + ] + } + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "foundBy", + "locations", + "licenses", + "language", + "cpes", + "purl" + ] + }, + "PhpComposerAuthors": { + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name" + ] + }, + "PhpComposerExternalReference": { + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "shasum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "type", + "url", + "reference" + ] + }, + "PhpComposerInstalledEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpComposerLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpPeclEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "PortageDbEntry": { + "properties": { + "installedSize": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/PortageFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "installedSize", + "files" + ] + }, + "PortageFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonDirectURLOriginInfo": { + "properties": { + "url": { + "type": "string" + }, + "commitId": { + "type": "string" + }, + "vcs": { + "type": "string" + } + }, + "type": "object", + "required": [ + "url" + ] + }, + "PythonFileDigest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "PythonFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/PythonFileDigest" + }, + "size": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/PythonFileRecord" + }, + "type": "array" + }, + "sitePackagesRootPath": { + "type": "string" + }, + "topLevelPackages": { + "items": { + "type": "string" + }, + "type": "array" + }, + "directUrlOrigin": { + "$ref": "#/$defs/PythonDirectURLOriginInfo" + }, + "requiresPython": { + "type": "string" + }, + "requiresDist": { + "items": { + "type": "string" + }, + "type": "array" + }, + "providesExtra": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "platform", + "sitePackagesRootPath" + ] + }, + "PythonPipRequirementsEntry": { + "properties": { + "name": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + }, + "versionConstraint": { + "type": "string" + }, + "url": { + "type": "string" + }, + "markers": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "versionConstraint" + ] + }, + "PythonPipfileLockEntry": { + "properties": { + "hashes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "index": { + "type": "string" + } + }, + "type": "object", + "required": [ + "hashes", + "index" + ] + }, + "PythonPoetryLockDependencyEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "optional": { + "type": "boolean" + }, + "markers": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "optional" + ] + }, + "PythonPoetryLockEntry": { + "properties": { + "index": { + "type": "string" + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonPoetryLockDependencyEntry" + }, + "type": "array" + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonPoetryLockExtraEntry" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ] + }, + "PythonPoetryLockExtraEntry": { + "properties": { + "name": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ] + }, + "RDescription": { + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "url": { + "items": { + "type": "string" + }, + "type": "array" + }, + "repository": { + "type": "string" + }, + "built": { + "type": "string" + }, + "needsCompilation": { + "type": "boolean" + }, + "imports": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "suggests": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "Relationship": { + "properties": { + "parent": { + "type": "string" + }, + "child": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "parent", + "child", + "type" + ] + }, + "RpmArchive": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmDbEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "mode": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "userName": { + "type": "string" + }, + "groupName": { + "type": "string" + }, + "flags": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "mode", + "size", + "digest", + "userName", + "groupName", + "flags" + ] + }, + "RubyGemspec": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "RustCargoAuditEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source" + ] + }, + "RustCargoLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + }, + "checksum": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "checksum", + "dependencies" + ] + }, + "Schema": { + "properties": { + "version": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "version", + "url" + ] + }, + "Source": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "metadata" + ] + }, + "SwiftPackageManagerLockEntry": { + "properties": { + "revision": { + "type": "string" + } + }, + "type": "object", + "required": [ + "revision" + ] + }, + "WordpressPluginEntry": { + "properties": { + "pluginInstallDirectory": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorUri": { + "type": "string" + } + }, + "type": "object", + "required": [ + "pluginInstallDirectory" + ] + }, + "cpes": { + "items": { + "$ref": "#/$defs/CPE" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/License" + }, + "type": "array" + } + } +} diff --git a/schema/json/schema-latest.json b/schema/json/schema-latest.json index fc873ed1d..028f3004b 100644 --- a/schema/json/schema-latest.json +++ b/schema/json/schema-latest.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "anchore.io/schema/syft/json/16.0.13/document", + "$id": "anchore.io/schema/syft/json/16.0.14/document", "$ref": "#/$defs/Document", "$defs": { "AlpmDbEntry": { @@ -647,12 +647,24 @@ "type": { "type": "string" }, - "vendor": { + "architecture": { + "type": "string" + }, + "osCPE": { + "type": "string" + }, + "os": { + "type": "string" + }, + "osVersion": { "type": "string" }, "system": { "type": "string" }, + "vendor": { + "type": "string" + }, "sourceRepo": { "type": "string" }, diff --git a/syft/pkg/binary.go b/syft/pkg/binary.go index f2a684401..70b72a977 100644 --- a/syft/pkg/binary.go +++ b/syft/pkg/binary.go @@ -15,9 +15,34 @@ type ClassifierMatch struct { // ELFBinaryPackageNoteJSONPayload Represents metadata captured from the .note.package section of the binary type ELFBinaryPackageNoteJSONPayload struct { - Type string `json:"type,omitempty"` - Vendor string `json:"vendor,omitempty"` - System string `json:"system,omitempty"` + // these are well-known fields as defined by systemd ELF package metadata "spec" https://systemd.io/ELF_PACKAGE_METADATA/ + + // Type is the type of the package (e.g. "rpm", "deb", "apk", etc.) + Type string `json:"type,omitempty"` + + // Architecture of the binary package (e.g. "amd64", "arm", etc.) + Architecture string `json:"architecture,omitempty"` + + // OS CPE is a CPE name for the OS, typically corresponding to CPE_NAME in os-release (e.g. cpe:/o:fedoraproject:fedora:33) + OSCPE string `json:"osCPE,omitempty"` + + // OS is the OS name, typically corresponding to ID in os-release (e.g. "fedora") + OS string `json:"os,omitempty"` + + // osVersion is the version of the OS, typically corresponding to VERSION_ID in os-release (e.g. "33") + OSVersion string `json:"osVersion,omitempty"` + + // these are additional fields that are not part of the systemd spec + + // System is a context-specific name for the system that the binary package is intended to run on or a part of + System string `json:"system,omitempty"` + + // Vendor is the individual or organization that produced the source code for the binary + Vendor string `json:"vendor,omitempty"` + + // SourceRepo is the URL to the source repository for which the binary was built from SourceRepo string `json:"sourceRepo,omitempty"` - Commit string `json:"commit,omitempty"` + + // Commit is the commit hash of the source repository for which the binary was built from + Commit string `json:"commit,omitempty"` } diff --git a/syft/pkg/cataloger/binary/elf_package.go b/syft/pkg/cataloger/binary/elf_package.go index 3e463b025..e24853942 100644 --- a/syft/pkg/cataloger/binary/elf_package.go +++ b/syft/pkg/cataloger/binary/elf_package.go @@ -2,6 +2,7 @@ package binary import ( "github.com/anchore/packageurl-go" + "github.com/anchore/syft/syft/cpe" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" ) @@ -23,13 +24,59 @@ func newELFPackage(metadata elfBinaryPackageNotes, locations file.LocationSet) p } func packageURL(metadata elfBinaryPackageNotes) string { - // TODO: what if the System value is not set? + var qualifiers []packageurl.Qualifier + + os := metadata.OS + osVersion := metadata.OSVersion + + atts, err := cpe.NewAttributes(metadata.OSCPE) + if err == nil { + // only "upgrade" the OS information if there is something more specific to use in it's place + if os == "" && osVersion == "" || os == "" && atts.Version != "" || atts.Product != "" && osVersion == "" { + os = atts.Product + osVersion = atts.Version + } + } + + if os != "" { + osQualifier := os + if osVersion != "" { + osQualifier += "-" + osVersion + } + qualifiers = append(qualifiers, packageurl.Qualifier{ + Key: "distro", + Value: osQualifier, + }) + } + + ty := purlDistroType(metadata.Type) + + namespace := os + + if ty == packageurl.TypeGeneric || os == "" { + namespace = metadata.System + } + return packageurl.NewPackageURL( - packageurl.TypeGeneric, - metadata.System, + ty, + namespace, metadata.Name, metadata.Version, - nil, + qualifiers, "", ).ToString() } + +func purlDistroType(ty string) string { + switch ty { + case "rpm": + return packageurl.TypeRPM + case "deb": + return packageurl.TypeDebian + case "apk": + return packageurl.TypeAlpine + case "alpm": + return "alpm" + } + return packageurl.TypeGeneric +} diff --git a/syft/pkg/cataloger/binary/elf_package_cataloger.go b/syft/pkg/cataloger/binary/elf_package_cataloger.go index 2e65a8376..ae2b94d9e 100644 --- a/syft/pkg/cataloger/binary/elf_package_cataloger.go +++ b/syft/pkg/cataloger/binary/elf_package_cataloger.go @@ -1,8 +1,10 @@ package binary import ( + "bytes" "context" "debug/elf" + "encoding/binary" "encoding/json" "fmt" @@ -154,11 +156,42 @@ func getELFNotes(r file.LocationReadCloser) (*elfBinaryPackageNotes, error) { return nil, err } - var metadata elfBinaryPackageNotes - if err := json.Unmarshal(notes, &metadata); err != nil { - log.WithFields("file", r.Location.Path(), "error", err).Trace("unable to unmarshal ELF package notes as JSON") + if len(notes) == 0 { return nil, nil } - return &metadata, err + { + var metadata elfBinaryPackageNotes + if err := json.Unmarshal(notes, &metadata); err == nil { + return &metadata, nil + } + } + + { + var header elf64SectionHeader + headerSize := binary.Size(header) / 4 + if len(notes) > headerSize { + var metadata elfBinaryPackageNotes + newPayload := bytes.TrimRight(notes[headerSize:], "\x00") + if err := json.Unmarshal(newPayload, &metadata); err == nil { + return &metadata, nil + } + log.WithFields("file", r.Location.Path(), "error", err).Trace("unable to unmarshal ELF package notes as JSON") + } + } + + return nil, err +} + +type elf64SectionHeader struct { + ShName uint32 + ShType uint32 + ShFlags uint64 + ShAddr uint64 + ShOffset uint64 + ShSize uint64 + ShLink uint32 + ShInfo uint32 + ShAddralign uint64 + ShEntsize uint64 } diff --git a/syft/pkg/cataloger/binary/elf_package_cataloger_test.go b/syft/pkg/cataloger/binary/elf_package_cataloger_test.go index 44f689d00..f3569e5f4 100644 --- a/syft/pkg/cataloger/binary/elf_package_cataloger_test.go +++ b/syft/pkg/cataloger/binary/elf_package_cataloger_test.go @@ -9,60 +9,115 @@ import ( ) func Test_ELF_Package_Cataloger(t *testing.T) { - expectedPkgs := []pkg.Package{ + + cases := []struct { + name string + fixture string + expected []pkg.Package + }{ { - Name: "libhello_world.so", - Version: "0.01", - PURL: "pkg:generic/syftsys/libhello_world.so@0.01", - FoundBy: "", - Locations: file.NewLocationSet( - file.NewVirtualLocation("/usr/local/bin/elftests/elfbinwithnestedlib/bin/lib/libhello_world.so", "/usr/local/bin/elftests/elfbinwithnestedlib/bin/lib/libhello_world.so"), - file.NewVirtualLocation("/usr/local/bin/elftests/elfbinwithsisterlib/lib/libhello_world.so", "/usr/local/bin/elftests/elfbinwithsisterlib/lib/libhello_world.so"), - file.NewVirtualLocation("/usr/local/bin/elftests/elfbinwithsisterlib/lib/libhello_world2.so", "/usr/local/bin/elftests/elfbinwithsisterlib/lib/libhello_world2.so"), - ), - Licenses: pkg.NewLicenseSet( - pkg.License{Value: "MIT", SPDXExpression: "MIT", Type: "declared"}, - ), + name: "go case", + fixture: "elf-test-fixtures", + expected: []pkg.Package{ + { + Name: "libhello_world.so", + Version: "0.01", + PURL: "pkg:generic/syftsys/libhello_world.so@0.01", + Locations: file.NewLocationSet( + file.NewVirtualLocation("/usr/local/bin/elftests/elfbinwithnestedlib/bin/lib/libhello_world.so", "/usr/local/bin/elftests/elfbinwithnestedlib/bin/lib/libhello_world.so"), + file.NewVirtualLocation("/usr/local/bin/elftests/elfbinwithsisterlib/lib/libhello_world.so", "/usr/local/bin/elftests/elfbinwithsisterlib/lib/libhello_world.so"), + file.NewVirtualLocation("/usr/local/bin/elftests/elfbinwithsisterlib/lib/libhello_world2.so", "/usr/local/bin/elftests/elfbinwithsisterlib/lib/libhello_world2.so"), + ), + Licenses: pkg.NewLicenseSet( + pkg.License{Value: "MIT", SPDXExpression: "MIT", Type: "declared"}, + ), - Language: "", - Type: pkg.BinaryPkg, - Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ - Type: "testfixture", - Vendor: "syft", - System: "syftsys", - SourceRepo: "https://github.com/someone/somewhere.git", - Commit: "5534c38d0ffef9a3f83154f0b7a7fb6ab0ab6dbb", + Type: pkg.BinaryPkg, + Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ + Type: "testfixture", + Vendor: "syft", + System: "syftsys", + SourceRepo: "https://github.com/someone/somewhere.git", + Commit: "5534c38d0ffef9a3f83154f0b7a7fb6ab0ab6dbb", + }, + }, + { + Name: "syfttestfixture", + Version: "0.01", + PURL: "pkg:generic/syftsys/syfttestfixture@0.01", + Locations: file.NewLocationSet( + file.NewLocation("/usr/local/bin/elftests/elfbinwithnestedlib/bin/elfbinwithnestedlib").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + file.NewLocation("/usr/local/bin/elftests/elfbinwithsisterlib/bin/elfwithparallellibbin1").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + file.NewLocation("/usr/local/bin/elftests/elfbinwithsisterlib/bin/elfwithparallellibbin2").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + Licenses: pkg.NewLicenseSet( + pkg.License{Value: "MIT", SPDXExpression: "MIT", Type: "declared"}, + ), + Type: pkg.BinaryPkg, + Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ + Type: "testfixture", + Vendor: "syft", + System: "syftsys", + SourceRepo: "https://github.com/someone/somewhere.git", + Commit: "5534c38d0ffef9a3f83154f0b7a7fb6ab0ab6dbb", + }, + }, }, }, { - Name: "syfttestfixture", - Version: "0.01", - PURL: "pkg:generic/syftsys/syfttestfixture@0.01", - FoundBy: "", - Locations: file.NewLocationSet( - file.NewLocation("/usr/local/bin/elftests/elfbinwithnestedlib/bin/elfbinwithnestedlib").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), - file.NewLocation("/usr/local/bin/elftests/elfbinwithsisterlib/bin/elfwithparallellibbin1").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), - file.NewLocation("/usr/local/bin/elftests/elfbinwithsisterlib/bin/elfwithparallellibbin2").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), - ), - Licenses: pkg.NewLicenseSet( - pkg.License{Value: "MIT", SPDXExpression: "MIT", Type: "declared"}, - ), - Language: "", - Type: pkg.BinaryPkg, - Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ - Type: "testfixture", - Vendor: "syft", - System: "syftsys", - SourceRepo: "https://github.com/someone/somewhere.git", - Commit: "5534c38d0ffef9a3f83154f0b7a7fb6ab0ab6dbb", + name: "fedora 64 bit binaries", + fixture: "image-fedora-64bit", + expected: []pkg.Package{ + { + Name: "coreutils", + Version: "9.5-1.fc41", + PURL: "pkg:rpm/fedora/coreutils@9.5-1.fc41?distro=fedora-40", + Locations: file.NewLocationSet( + file.NewLocation("/sha256sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + file.NewLocation("/sha1sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + Licenses: pkg.NewLicenseSet(), + Type: pkg.BinaryPkg, + Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ + Type: "rpm", + Architecture: "x86_64", + OSCPE: "cpe:/o:fedoraproject:fedora:40", + }, + }, + }, + }, + { + name: "fedora 32 bit binaries", + fixture: "image-fedora-32bit", + expected: []pkg.Package{ + { + Name: "coreutils", + Version: "9.0-5.fc36", + PURL: "pkg:rpm/fedora/coreutils@9.0-5.fc36?distro=fedora-36", + Locations: file.NewLocationSet( + file.NewLocation("/sha256sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + file.NewLocation("/sha1sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + Licenses: pkg.NewLicenseSet(), + Type: pkg.BinaryPkg, + Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ + Type: "rpm", + Architecture: "arm", + OSCPE: "cpe:/o:fedoraproject:fedora:36", + }, + }, }, }, } - pkgtest.NewCatalogTester(). - WithImageResolver(t, "elf-test-fixtures"). - IgnoreLocationLayer(). // this fixture can be rebuilt, thus the layer ID will change - Expects(expectedPkgs, nil). - TestCataloger(t, NewELFPackageCataloger()) + for _, v := range cases { + t.Run(v.name, func(t *testing.T) { + pkgtest.NewCatalogTester(). + WithImageResolver(t, v.fixture). + IgnoreLocationLayer(). // this fixture can be rebuilt, thus the layer ID will change + Expects(v.expected, nil). + TestCataloger(t, NewELFPackageCataloger()) + }) + } } diff --git a/syft/pkg/cataloger/binary/elf_package_test.go b/syft/pkg/cataloger/binary/elf_package_test.go index 6a1020ca0..85fa42221 100644 --- a/syft/pkg/cataloger/binary/elf_package_test.go +++ b/syft/pkg/cataloger/binary/elf_package_test.go @@ -14,36 +14,110 @@ import ( func Test_packageURL(t *testing.T) { tests := []struct { name string - notes elfBinaryPackageNotes - expected string + metadata elfBinaryPackageNotes + want string }{ { name: "elf-binary-package-cataloger", - notes: elfBinaryPackageNotes{ + metadata: elfBinaryPackageNotes{ Name: "github.com/anchore/syft", Version: "v0.1.0", ELFBinaryPackageNoteJSONPayload: pkg.ELFBinaryPackageNoteJSONPayload{ System: "syftsys", }, }, - expected: "pkg:generic/syftsys/github.com/anchore/syft@v0.1.0", + want: "pkg:generic/syftsys/github.com/anchore/syft@v0.1.0", }, { name: "elf binary package short name", - notes: elfBinaryPackageNotes{ + metadata: elfBinaryPackageNotes{ Name: "go.opencensus.io", Version: "v0.23.0", ELFBinaryPackageNoteJSONPayload: pkg.ELFBinaryPackageNoteJSONPayload{ System: "syftsys", }, }, - expected: "pkg:generic/syftsys/go.opencensus.io@v0.23.0", + want: "pkg:generic/syftsys/go.opencensus.io@v0.23.0", + }, + { + name: "no info", + metadata: elfBinaryPackageNotes{ + Name: "test", + Version: "1.0", + ELFBinaryPackageNoteJSONPayload: pkg.ELFBinaryPackageNoteJSONPayload{ + Type: "rpm", + }, + }, + want: "pkg:rpm/test@1.0", + }, + { + name: "with system", + metadata: elfBinaryPackageNotes{ + Name: "test", + Version: "1.0", + ELFBinaryPackageNoteJSONPayload: pkg.ELFBinaryPackageNoteJSONPayload{ + Type: "rpm", + System: "system", + }, + }, + want: "pkg:rpm/system/test@1.0", + }, + { + name: "with os info preferred", + metadata: elfBinaryPackageNotes{ + Name: "test", + Version: "1.0", + ELFBinaryPackageNoteJSONPayload: pkg.ELFBinaryPackageNoteJSONPayload{ + Type: "rpm", + OS: "fedora", + OSVersion: "2.0", + OSCPE: "cpe:/o:someone:redhat:3.0", + }, + }, + want: "pkg:rpm/fedora/test@1.0?distro=fedora-2.0", + }, + { + name: "with os info fallback to CPE parsing (missing version)", + metadata: elfBinaryPackageNotes{ + Name: "test", + Version: "1.0", + ELFBinaryPackageNoteJSONPayload: pkg.ELFBinaryPackageNoteJSONPayload{ + Type: "rpm", + OS: "fedora", + OSCPE: "cpe:/o:someone:redhat:3.0", + }, + }, + want: "pkg:rpm/redhat/test@1.0?distro=redhat-3.0", + }, + { + name: "with os info preferred (missing OS)", + metadata: elfBinaryPackageNotes{ + Name: "test", + Version: "1.0", + ELFBinaryPackageNoteJSONPayload: pkg.ELFBinaryPackageNoteJSONPayload{ + Type: "rpm", + OSVersion: "2.0", + OSCPE: "cpe:/o:someone:redhat:3.0", + }, + }, + want: "pkg:rpm/redhat/test@1.0?distro=redhat-3.0", + }, + { + name: "missing type", + metadata: elfBinaryPackageNotes{ + Name: "test", + Version: "1.0", + ELFBinaryPackageNoteJSONPayload: pkg.ELFBinaryPackageNoteJSONPayload{ + System: "system", + }, + }, + want: "pkg:generic/system/test@1.0", }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - assert.Equal(t, test.expected, packageURL(test.notes)) + assert.Equal(t, test.want, packageURL(test.metadata)) }) } } diff --git a/syft/pkg/cataloger/binary/test-fixtures/image-fedora-32bit/Dockerfile b/syft/pkg/cataloger/binary/test-fixtures/image-fedora-32bit/Dockerfile new file mode 100644 index 000000000..e89c76124 --- /dev/null +++ b/syft/pkg/cataloger/binary/test-fixtures/image-fedora-32bit/Dockerfile @@ -0,0 +1,5 @@ +FROM --platform=linux/arm arm32v7/fedora:36 as build + +FROM scratch +COPY --from=build /bin/sha256sum /sha256sum +COPY --from=build /bin/sha1sum /sha1sum diff --git a/syft/pkg/cataloger/binary/test-fixtures/image-fedora-64bit/Dockerfile b/syft/pkg/cataloger/binary/test-fixtures/image-fedora-64bit/Dockerfile new file mode 100644 index 000000000..14dc99c44 --- /dev/null +++ b/syft/pkg/cataloger/binary/test-fixtures/image-fedora-64bit/Dockerfile @@ -0,0 +1,5 @@ +FROM --platform=linux/amd64 fedora:41 as build + +FROM scratch +COPY --from=build /bin/sha256sum /sha256sum +COPY --from=build /bin/sha1sum /sha1sum From a658cc7402fb42e35a748ec26c1f01939733480d Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 09:20:22 -0400 Subject: [PATCH 027/284] chore(deps): update tools to latest versions (#2943) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index d5cb34429..1ac4de0cb 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -26,7 +26,7 @@ tools: # used for linting - name: golangci-lint version: - want: v1.59.0 + want: v1.59.1 method: github-release with: repo: golangci/golangci-lint From db0c33481ed5bac4c1f70361eb9f9323392040f4 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Mon, 10 Jun 2024 09:59:33 -0400 Subject: [PATCH 028/284] pin golang image (#2944) Signed-off-by: Alex Goodman --- .../golang/test-fixtures/image-not-a-module/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/Dockerfile b/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/Dockerfile index 38b26c721..4376b96cd 100644 --- a/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/Dockerfile +++ b/syft/pkg/cataloger/golang/test-fixtures/image-not-a-module/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=linux/amd64 golang:1.22 AS builder +FROM --platform=linux/amd64 golang:1.22.4 AS builder RUN mkdir /app WORKDIR /app From c43f4fb416c34c1c4b3997373689d8d4c0fb9b36 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Mon, 10 Jun 2024 11:29:53 -0400 Subject: [PATCH 029/284] add signature verification to install.sh (#2941) Signed-off-by: Alex Goodman --- .github/workflows/release.yaml | 8 + .github/workflows/validations.yaml | 3 + README.md | 9 +- install.sh | 261 ++++++++++++++---- ..._for_asset_test.sh => 0_checksums_test.sh} | 46 +++ .../install/1_download_snapshot_asset_test.sh | 2 +- test/install/2_download_release_asset_test.sh | 4 + .../4_prep_signature_verification_test.sh | 89 ++++++ test/install/Makefile | 37 ++- .../environments/Dockerfile-alpine-3.6 | 7 +- .../environments/Dockerfile-busybox-1.36 | 21 ++ .../environments/Dockerfile-ubuntu-20.04 | 7 +- .../test-fixtures/assets/invalid/.gitignore | 1 + .../assets/invalid/checksums.txt | 22 ++ .../invalid/syft_1.5.0_linux_arm64.tar.gz | 1 + .../test-fixtures/assets/valid/.gitignore | 1 + .../test-fixtures/assets/valid/checksums.txt | 22 ++ .../valid/syft_1.5.0_linux_arm64.tar.gz | 1 + 18 files changed, 471 insertions(+), 71 deletions(-) rename test/install/{0_search_for_asset_test.sh => 0_checksums_test.sh} (54%) create mode 100755 test/install/4_prep_signature_verification_test.sh create mode 100644 test/install/environments/Dockerfile-busybox-1.36 create mode 100644 test/install/test-fixtures/assets/invalid/.gitignore create mode 100644 test/install/test-fixtures/assets/invalid/checksums.txt create mode 100644 test/install/test-fixtures/assets/invalid/syft_1.5.0_linux_arm64.tar.gz create mode 100644 test/install/test-fixtures/assets/valid/.gitignore create mode 100644 test/install/test-fixtures/assets/valid/checksums.txt create mode 100644 test/install/test-fixtures/assets/valid/syft_1.5.0_linux_arm64.tar.gz diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 09ce1d5a5..1b6f94d4e 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -17,6 +17,14 @@ jobs: steps: - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6 + - name: Check if running on main + if: github.ref != 'refs/heads/main' + # we are using the following flag when running `cosign blob-verify` for checksum signature verification: + # --certificate-identity-regexp "https://github.com/anchore/.github/workflows/release.yaml@refs/heads/main" + # if we are not on the main branch, the signature will not be verifiable since the suffix requires the main branch + # at the time of when the OIDC token was issued on the Github Actions runner. + run: echo "This can only be run on the main branch otherwise releases produced will not be verifiable with cosign" && exit 1 + - name: Check if tag already exists # note: this will fail if the tag already exists run: | diff --git a/.github/workflows/validations.yaml b/.github/workflows/validations.yaml index 417d89bad..2a29a4858 100644 --- a/.github/workflows/validations.yaml +++ b/.github/workflows/validations.yaml @@ -187,6 +187,9 @@ jobs: needs: [Build-Snapshot-Artifacts] runs-on: macos-latest steps: + - name: Install Cosign + uses: sigstore/cosign-installer@v3.5.0 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6 - name: Bootstrap environment diff --git a/README.md b/README.md index 565f44be2..b36ab288d 100644 --- a/README.md +++ b/README.md @@ -40,11 +40,10 @@ Syft binaries are provided for Linux, macOS and Windows. > curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin > ``` -... or, you can specify a release version and destination directory for the installation: - -> ```bash -> curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b -> ``` +Install script options: +- `-b`: Specify a custom installation directory (defaults to `./bin`) +- `-d`: More verbose logging levels (`-d` for debug, `-dd` for trace) +- `-v`: Verify the signature of the downloaded artifact before installation (requires [`cosign`](https://github.com/sigstore/cosign) to be installed) ### Homebrew ```bash diff --git a/install.sh b/install.sh index f5680271e..1c2f49f0f 100755 --- a/install.sh +++ b/install.sh @@ -2,33 +2,25 @@ # note: we require errors to propagate (don't set -e) set -u -PROJECT_NAME="syft" +PROJECT_NAME=syft OWNER=anchore REPO="${PROJECT_NAME}" GITHUB_DOWNLOAD_PREFIX=https://github.com/${OWNER}/${REPO}/releases/download INSTALL_SH_BASE_URL=https://raw.githubusercontent.com/${OWNER}/${PROJECT_NAME} PROGRAM_ARGS=$@ -# do not change the name of this parameter (this must always be backwards compatible) -DOWNLOAD_TAG_INSTALL_SCRIPT=${DOWNLOAD_TAG_INSTALL_SCRIPT:-true} +# signature verification options -# -# usage [script-name] -# -usage() ( - this=$1 - cat </dev/null | tr '\t' ' ' | cut -d ' ' -f 1) + target_basename=${target##*/} + want=$(grep "${target_basename}" "${checksums}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1) if [ -z "$want" ]; then - log_err "hash_sha256_verify unable to find checksum for '${TARGET}' in '${checksums}'" + log_err "hash_sha256_verify unable to find checksum for '${target}' in '${checksums}'" return 1 fi - got=$(hash_sha256 "$TARGET") + got=$(hash_sha256 "$target") if [ "$want" != "$got" ]; then - log_err "hash_sha256_verify checksum for '$TARGET' did not verify ${want} vs $got" + log_err "hash_sha256_verify checksum for '$target' did not verify ${want} vs $got" return 1 fi ) @@ -358,30 +350,71 @@ github_release_tag() ( echo "$tag" ) -# download_github_release_checksums [release-url-prefix] [name] [version] [output-dir] +# github_release_asset_url [release-url-prefix] [name] [version] [output-dir] [filename] # -# outputs path to the downloaded checksums file +# outputs the url to the release asset # -download_github_release_checksums() ( +github_release_asset_url() ( + download_url="$1" + name="$2" + version="$3" + filename="$4" + + complete_filename="${name}_${version}_${filename}" + complete_url="${download_url}/${complete_filename}" + + echo "${complete_url}" +) + +# download_github_release_checksums_files [release-url-prefix] [name] [version] [output-dir] [filename] +# +# outputs path to the downloaded checksums related file +# +download_github_release_checksums_files() ( download_url="$1" name="$2" version="$3" output_dir="$4" + filename="$5" - log_trace "download_github_release_checksums(url=${download_url}, name=${name}, version=${version}, output_dir=${output_dir})" + log_trace "download_github_release_checksums_files(url=${download_url}, name=${name}, version=${version}, output_dir=${output_dir}, filename=${filename})" - checksum_filename=${name}_${version}_checksums.txt - checksum_url=${download_url}/${checksum_filename} - output_path="${output_dir}/${checksum_filename}" + complete_filename="${name}_${version}_${filename}" + complete_url=$(github_release_asset_url "${download_url}" "${name}" "${version}" "${filename}") + output_path="${output_dir}/${complete_filename}" - http_download "${output_path}" "${checksum_url}" "" + http_download "${output_path}" "${complete_url}" "" asset_file_exists "${output_path}" - log_trace "download_github_release_checksums() returned '${output_path}'" + log_trace "download_github_release_checksums_files() returned '${output_path}' for file '${complete_filename}'" echo "${output_path}" ) +# download_github_release_checksums [release-url-prefix] [name] [version] [output-dir] +# +# outputs path to the downloaded checksums file +# +download_github_release_checksums() ( + download_github_release_checksums_files "$@" "checksums.txt" +) + +# github_release_checksums_sig_url [release-url-prefix] [name] [version] +# +# outputs the url to the release checksums signature file +# +github_release_checksums_sig_url() ( + github_release_asset_url "$@" "checksums.txt.sig" +) + +# github_release_checksums_cert_url [release-url-prefix] [name] [version] +# +# outputs the url to the release checksums certificate file +# +github_release_checksums_cert_url() ( + github_release_asset_url "$@" "checksums.txt.pem" +) + # search_for_asset [checksums-file-path] [name] [os] [arch] [format] # # outputs name of the asset to download @@ -535,7 +568,10 @@ download_and_install_asset() ( format="$8" binary="$9" - asset_filepath=$(download_asset "${download_url}" "${download_path}" "${name}" "${os}" "${arch}" "${version}" "${format}") + if ! asset_filepath=$(download_asset "${download_url}" "${download_path}" "${name}" "${os}" "${arch}" "${version}" "${format}"); then + log_err "could not download asset for os='${os}' arch='${arch}' format='${format}'" + return 1 + fi # don't continue if we couldn't download an asset if [ -z "${asset_filepath}" ]; then @@ -546,6 +582,36 @@ download_and_install_asset() ( install_asset "${asset_filepath}" "${install_path}" "${binary}" ) +# verify_sign [checksums-file-path] [certificate-reference] [signature-reference] [version] +# +# attempts verify the signature of the checksums file from the release workflow in Github Actions run against the main branch. +# +verify_sign() { + checksums_file=$1 + cert_reference=$2 + sig_reference=$3 + + log_trace "verifying artifact $1" + + log_file=$(mktemp) + + ${COSIGN_BINARY} \ + verify-blob "$checksums_file" \ + --certificate "$cert_reference" \ + --signature "$sig_reference" \ + --certificate-identity "https://github.com/${OWNER}/${REPO}/.github/workflows/release.yaml@refs/heads/main" \ + --certificate-oidc-issuer "https://token.actions.githubusercontent.com" > "${log_file}" 2>&1 + + if [ $? -ne 0 ]; then + log_err "$(cat "${log_file}")" + rm -f "${log_file}" + return 1 + fi + + rm -f "${log_file}" +} + + # download_asset [release-url-prefix] [download-path] [name] [os] [arch] [version] [format] [binary] # # outputs the path to the downloaded asset asset_filepath @@ -572,6 +638,20 @@ download_asset() ( return 1 fi + if [ "$VERIFY_SIGN" = true ]; then + checksum_sig_file_url=$(github_release_checksums_sig_url "${download_url}" "${name}" "${version}") + log_trace "checksums signature url: ${checksum_sig_file_url}" + + checksums_cert_file_url=$(github_release_checksums_cert_url "${download_url}" "${name}" "${version}") + log_trace "checksums certificate url: ${checksums_cert_file_url}" + + if ! verify_sign "${checksums_filepath}" "${checksums_cert_file_url}" "${checksum_sig_file_url}"; then + log_err "signature verification failed" + return 1 + fi + log_info "signature verification succeeded" + fi + asset_url="${download_url}/${asset_filename}" asset_filepath="${destination}/${asset_filename}" http_download "${asset_filepath}" "${asset_url}" "" @@ -609,6 +689,79 @@ install_asset() ( install "${archive_dir}/${binary}" "${destination}/" ) +# compare two semver strings. Returns 0 if version1 >= version2, 1 otherwise. +# Note: pre-release (-) and metadata (+) are not supported. +compare_semver() { + # remove leading 'v' if present + version1=${1#v} + version2=${2#v} + + IFS=. read -r major1 minor1 patch1 <= '$VERIFY_SIGN_SUPPORTED_VERSION')" + log_err "aborting installation" + return 1 + else + log_trace "${PROJECT_NAME} release '$version' supports signature verification (>= '$VERIFY_SIGN_SUPPORTED_VERSION')" + fi + + # will invoking an earlier version of this script work (considering the -v flag)? + if ! compare_semver "$version" "$VERIFY_SIGN_FLAG_VERSION"; then + # the -v argument did not always exist, so we cannot be guaranteed that invoking an earlier version of this script + # will work (error with "illegal option -v"). However, the user requested signature verification, so we will + # attempt to install the application with this version of the script (keeping signature verification). + DOWNLOAD_TAG_INSTALL_SCRIPT=false + log_debug "provided version install script does not support -v flag (>= '$VERIFY_SIGN_FLAG_VERSION'), using current script for installation" + else + log_trace "provided version install script supports -v flag (>= '$VERIFY_SIGN_FLAG_VERSION')" + fi + + # check to see if the cosign binary is installed + if is_command "${COSIGN_BINARY}"; then + log_trace "${COSIGN_BINARY} binary is installed" + else + log_err "signature verification is requested but ${COSIGN_BINARY} binary is not installed (see https://docs.sigstore.dev/system_config/installation/ to install it)" + return 1 + fi +} + main() ( # parse arguments @@ -616,7 +769,7 @@ main() ( install_dir=${install_dir:-./bin} # note: never change the program flags or arguments (this must always be backwards compatible) - while getopts "b:dh?x" arg; do + while getopts "b:dvh?x" arg; do case "$arg" in b) install_dir="$OPTARG" ;; d) @@ -628,25 +781,37 @@ main() ( log_set_priority $log_trace_priority fi ;; - h | \?) usage "$0" ;; + v) VERIFY_SIGN=true;; + h | \?) + cat <= version2) + compare_semver "0.32.0" "0.32.0" + assertEquals "0" "$?" "+ versions should equal" + + compare_semver "0.32.1" "0.32.0" + assertEquals "0" "$?" "+ patch version should be greater" + + compare_semver "0.33.0" "0.32.0" + assertEquals "0" "$?" "+ minor version should be greater" + + compare_semver "0.333.0" "0.32.0" + assertEquals "0" "$?" "+ minor version should be greater (different length)" + + compare_semver "00.33.00" "0.032.0" + assertEquals "0" "$?" "+ minor version should be greater (different length reversed)" + + compare_semver "1.0.0" "0.9.9" + assertEquals "0" "$?" "+ major version should be greater" + + compare_semver "v1.0.0" "1.0.0" + assertEquals "0" "$?" "+ can remove leading 'v' from version" + + # negative cases (version1 < version2) + compare_semver "0.32.0" "0.32.1" + assertEquals "1" "$?" "- patch version should be less" + + compare_semver "0.32.7" "0.33.0" + assertEquals "1" "$?" "- minor version should be less" + + compare_semver "00.00032.070" "0.33.0" + assertEquals "1" "$?" "- minor version should be less (different length)" + + compare_semver "0.32.7" "00.0033.000" + assertEquals "1" "$?" "- minor version should be less (different length reversed)" + + compare_semver "1.9.9" "2.0.1" + assertEquals "1" "$?" "- major version should be less" + + compare_semver "1.0.0" "v2.0.0" + assertEquals "1" "$?" "- can remove leading 'v' from version" +} + +run_test_case test_compare_semver + +# ensure that various signature verification pre-requisites are correctly checked for +test_prep_signature_verification() { + # prep_sign_verification [version] + + # we are expecting error messages, which is confusing to look at in passing tests... disable logging for now + log_set_priority -1 + + # backup original values... + OG_COSIGN_BINARY=${COSIGN_BINARY} + + # check the verification path... + VERIFY_SIGN=true + + # release does not support signature verification + prep_signature_verification "0.103.0" + assertEquals "1" "$?" "release does not support signature verification" + + # check that the COSIGN binary exists + COSIGN_BINARY=fake-cosign-that-doesnt-exist + prep_signature_verification "0.105.0" + assertEquals "1" "$?" "cosign binary verification failed" + # restore original values... + COSIGN_BINARY=${OG_COSIGN_BINARY} + + # ignore any failing conditions since we are not verifying the signature + VERIFY_SIGN=false + prep_signature_verification "0.103.0" + assertEquals "0" "$?" "release support verification should not have been triggered" + + COSIGN_BINARY=fake-cosign-that-doesnt-exist + prep_signature_verification "0.105.0" + assertEquals "0" "$?" "cosign binary verification should not have been triggered" + # restore original values... + COSIGN_BINARY=${OG_COSIGN_BINARY} + + # restore logging... + log_set_priority 0 +} + +run_test_case test_prep_signature_verification diff --git a/test/install/Makefile b/test/install/Makefile index fd8588418..2a632cd28 100644 --- a/test/install/Makefile +++ b/test/install/Makefile @@ -1,18 +1,22 @@ NAME=syft +# for local testing (not testing within containers) use the binny-managed version of cosign. +# this also means that the user does not need to install cosign on their system to run tests. +COSIGN_BINARY=../../.tool/cosign + IMAGE_NAME=$(NAME)-install.sh-env UBUNTU_IMAGE=$(IMAGE_NAME):ubuntu-20.04 ALPINE_IMAGE=$(IMAGE_NAME):alpine-3.6 -BUSYBOX_IMAGE=busybox:1.36.1-musl +BUSYBOX_IMAGE=$(IMAGE_NAME):busybox-1.36 ENVS=./environments DOCKER_RUN=docker run --rm -t -w /project/test/install -v $(shell pwd)/../../:/project -UNIT=make unit-local +UNIT=make unit-run # acceptance testing is running the current install.sh against the latest release. Note: this could be a problem down # the line if there are breaking changes made that don't align with the latest release (but will be OK with the next -# release) -ACCEPTANCE_CMD=sh -c '../../install.sh -b /usr/local/bin && syft version' +# release). This tests both installing with signature verification and without. +ACCEPTANCE_CMD=sh -c '../../install.sh -v -b /usr/local/bin && syft version && rm /usr/local/bin/syft && ../../install.sh -b /usr/local/bin && syft version' # we also want to test against a previous release to ensure that install.sh defers execution to a former install.sh PREVIOUS_RELEASE=v0.33.0 ACCEPTANCE_PREVIOUS_RELEASE_CMD=sh -c "../../install.sh -b /usr/local/bin $(PREVIOUS_RELEASE) && syft version" @@ -28,17 +32,22 @@ endef test: unit acceptance .PHONY: ci-test-mac -ci-test-mac: unit-local acceptance-local +ci-test-mac: unit-run acceptance-local # note: do not add acceptance-local to this list .PHONY: acceptance -acceptance: acceptance-ubuntu-20.04 acceptance-alpine-3.6 acceptance-busybox +acceptance: acceptance-ubuntu-20.04 acceptance-alpine-3.6 acceptance-busybox-1.36 .PHONY: unit unit: unit-ubuntu-20.04 .PHONY: unit-local unit-local: + $(call title,unit tests) + @for f in $(shell ls *_test.sh); do echo "Running unit test suite '$${f}'"; bash -c "COSIGN_BINARY=$(COSIGN_BINARY) ./$${f}" || exit 1; done + +.PHONY: unit-run +unit-run: $(call title,unit tests) @for f in $(shell ls *_test.sh); do echo "Running unit test suite '$${f}'"; bash $${f} || exit 1; done @@ -55,7 +64,7 @@ acceptance-previous-release-local: syft version | grep $(shell echo $(PREVIOUS_RELEASE)| tr -d "v") .PHONY: save -save: ubuntu-20.04 alpine-3.6 pull-busybox +save: ubuntu-20.04 alpine-3.6 busybox-1.36 @mkdir cache || true docker image save -o cache/ubuntu-env.tar $(UBUNTU_IMAGE) docker image save -o cache/alpine-env.tar $(ALPINE_IMAGE) @@ -107,17 +116,17 @@ alpine-3.6: # note: busybox by default will not have cacerts, so you will get TLS warnings (we want to test under these conditions) -.PHONY: acceptance-busybox -acceptance-busybox: pull-busybox - $(call title,busybox - acceptance) +.PHONY: acceptance-busybox-1.36 +acceptance-busybox-1.36: busybox-1.36 + $(call title,busybox-1.36 - acceptance) $(DOCKER_RUN) $(BUSYBOX_IMAGE) \ $(ACCEPTANCE_CMD) @echo "\n*** test note: you should see syft spit out a 'x509: certificate signed by unknown authority' error --this is expected ***" -.PHONY: pull-busybox -pull-busybox: - $(call title,busybox - build environment) - docker pull $(BUSYBOX_IMAGE) +.PHONY: busybox-1.36 +busybox-1.36: + $(call title,busybox-1.36 - build environment) + docker build -t $(BUSYBOX_IMAGE) -f $(ENVS)/Dockerfile-busybox-1.36 . ## For CI ######################################################## diff --git a/test/install/environments/Dockerfile-alpine-3.6 b/test/install/environments/Dockerfile-alpine-3.6 index 90923d566..51dc3d0ea 100644 --- a/test/install/environments/Dockerfile-alpine-3.6 +++ b/test/install/environments/Dockerfile-alpine-3.6 @@ -1,2 +1,5 @@ -FROM alpine:3.6@sha256:66790a2b79e1ea3e1dabac43990c54aca5d1ddf268d9a5a0285e4167c8b24475 -RUN apk update && apk add python3 wget unzip make ca-certificates jq +FROM alpine:3.6 +RUN apk update && apk add python3 wget curl unzip make ca-certificates +RUN curl -O -L "https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64" && \ + mv cosign-linux-amd64 /usr/local/bin/cosign && \ + chmod +x /usr/local/bin/cosign diff --git a/test/install/environments/Dockerfile-busybox-1.36 b/test/install/environments/Dockerfile-busybox-1.36 new file mode 100644 index 000000000..e2cf2d722 --- /dev/null +++ b/test/install/environments/Dockerfile-busybox-1.36 @@ -0,0 +1,21 @@ +FROM alpine as certs +RUN apk update && apk add ca-certificates + +# note: using qemu with a multi-arch image results in redirects not working with wget +# so let docker pull the image that matches the hosts architecture first and then pull the correct asset +FROM busybox:1.36.1-musl + +RUN ARCH=$(uname -m) && \ + if [ "$ARCH" = "x86_64" ]; then \ + COSIGN_ARCH="amd64"; \ + elif [ "$ARCH" = "aarch64" ]; then \ + COSIGN_ARCH="arm64"; \ + else \ + echo "Unsupported architecture: $ARCH" && exit 1; \ + fi && \ + echo "Downloading cosign for $COSIGN_ARCH" && \ + wget https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-${COSIGN_ARCH} && \ + mv cosign-linux-${COSIGN_ARCH} /bin/cosign && \ + chmod +x /bin/cosign + +COPY --from=certs /etc/ssl/certs /etc/ssl/certs diff --git a/test/install/environments/Dockerfile-ubuntu-20.04 b/test/install/environments/Dockerfile-ubuntu-20.04 index 9de8d2a82..d91d10fca 100644 --- a/test/install/environments/Dockerfile-ubuntu-20.04 +++ b/test/install/environments/Dockerfile-ubuntu-20.04 @@ -1,2 +1,5 @@ -FROM ubuntu:20.04@sha256:33a5cc25d22c45900796a1aca487ad7a7cb09f09ea00b779e3b2026b4fc2faba -RUN apt update -y && apt install make python3 curl unzip jq -y +FROM --platform=linux/amd64 ubuntu:20.04@sha256:33a5cc25d22c45900796a1aca487ad7a7cb09f09ea00b779e3b2026b4fc2faba +RUN apt update -y && apt install make python3 curl unzip -y +RUN LATEST_VERSION=$(curl https://api.github.com/repos/sigstore/cosign/releases/latest | grep tag_name | cut -d : -f2 | tr -d "v\", ") && \ + curl -O -L "https://github.com/sigstore/cosign/releases/latest/download/cosign_${LATEST_VERSION}_amd64.deb" && \ + dpkg -i cosign_${LATEST_VERSION}_amd64.deb diff --git a/test/install/test-fixtures/assets/invalid/.gitignore b/test/install/test-fixtures/assets/invalid/.gitignore new file mode 100644 index 000000000..653353c26 --- /dev/null +++ b/test/install/test-fixtures/assets/invalid/.gitignore @@ -0,0 +1 @@ +!syft_1.5.0_linux_arm64.tar.gz \ No newline at end of file diff --git a/test/install/test-fixtures/assets/invalid/checksums.txt b/test/install/test-fixtures/assets/invalid/checksums.txt new file mode 100644 index 000000000..b38380486 --- /dev/null +++ b/test/install/test-fixtures/assets/invalid/checksums.txt @@ -0,0 +1,22 @@ +f459ecbed6621933b4dee4a613a6bdca915631742083f77ab88752f3ae0c6a9d syft_1.5.0_darwin_amd64.sbom +605322e3e7043a4f2f3d6e37f75a71389d38f6f290bff2e54bb2aaebbbf4829b syft_1.5.0_darwin_amd64.tar.gz +2feb92f6a4d117a3eb0cc5d887ac4b8da9a959ca404986dbe76e81ac83569d76 syft_1.5.0_darwin_arm64.sbom +fe02d072e7ec9a8eb4ac866ba973396a8beae79829ee870acaadd4d862e5e65a syft_1.5.0_darwin_arm64.tar.gz +40562766f99db7221dac4c82c44ccae4d9983a6795a96127f4da955d6797c090 syft_1.5.0_linux_amd64.deb +9adc0c0a3bbbdb8ce66914ffde5e176373cf5ec70a2a88cc886dc6ec54db0cd2 syft_1.5.0_linux_amd64.rpm +9de7f1c549020a25df12f07dd58330e6f6dd0c5363cf0de1157eb4f01fc41020 syft_1.5.0_linux_amd64.sbom +3d10023d46dfaf0fe75288df207b478b43597f7d2fff553f58430817166bd478 syft_1.5.0_linux_amd64.tar.gz +b661dd1be48b75b735717f9bedc4beea587968af8bf2d8c2752a302ae0a34f89 syft_1.5.0_linux_arm64.deb +5c311f44cc73fcae58884f8ea3328fc120bdaf3d21f4fe40270a22c6bb981f6d syft_1.5.0_linux_arm64.rpm +a74549794fa5dac79ab9f6401ee7000db3bd9589435b302583c3ee4ca13fb8e3 syft_1.5.0_linux_arm64.sbom +ee2b1289a1e4b0de9409c3a78867949ca42788a5f50072b8a6e6e04e6a269f9c syft_1.5.0_linux_arm64.tar.gz +599e66f0a00ba8b5cc7817f774c66c5f23de32e6b935ca9c03a185e4d2554d80 syft_1.5.0_linux_ppc64le.deb +dc4b8c4a02ffd8dd394ab94695ed44ed2bfceb06bc239835c51e84dd9b84a68c syft_1.5.0_linux_ppc64le.rpm +392044f2951ca6522d0bc71de43763202a548d40bf836098caf286041a7c8fa4 syft_1.5.0_linux_ppc64le.sbom +551d98b67f7476bc2e38453a588177b0b038933850a351a94c4bf360813f01d0 syft_1.5.0_linux_ppc64le.tar.gz +98cd582d9484f428cccd7351031543038f26d4e3f1481c5916e08e65983f1e21 syft_1.5.0_linux_s390x.deb +3a5197d43a469feaa87c723448a47a2312cf26456eef4580b59eac447baef9d4 syft_1.5.0_linux_s390x.rpm +5805bfb3e30452c8860665ea88bfdf356e9536a35c1b8ba28ac5b4717f2e6388 syft_1.5.0_linux_s390x.sbom +ff15f556660cc4c4279ce41e2475bffe2a0f72eb4423c21edf7380b2484fbf68 syft_1.5.0_linux_s390x.tar.gz +6b22df07e992d8f4881901535c095d268f79924e10be34fab03dec2b4f9f9ca0 syft_1.5.0_windows_amd64.sbom +5079c6a88e130f8677d0701cb2689f9eae2088022ecf5fa2b9f341b96d9983d2 syft_1.5.0_windows_amd64.zip diff --git a/test/install/test-fixtures/assets/invalid/syft_1.5.0_linux_arm64.tar.gz b/test/install/test-fixtures/assets/invalid/syft_1.5.0_linux_arm64.tar.gz new file mode 100644 index 000000000..c90127d2f --- /dev/null +++ b/test/install/test-fixtures/assets/invalid/syft_1.5.0_linux_arm64.tar.gz @@ -0,0 +1 @@ +fake archive \ No newline at end of file diff --git a/test/install/test-fixtures/assets/valid/.gitignore b/test/install/test-fixtures/assets/valid/.gitignore new file mode 100644 index 000000000..653353c26 --- /dev/null +++ b/test/install/test-fixtures/assets/valid/.gitignore @@ -0,0 +1 @@ +!syft_1.5.0_linux_arm64.tar.gz \ No newline at end of file diff --git a/test/install/test-fixtures/assets/valid/checksums.txt b/test/install/test-fixtures/assets/valid/checksums.txt new file mode 100644 index 000000000..b1dfe76b9 --- /dev/null +++ b/test/install/test-fixtures/assets/valid/checksums.txt @@ -0,0 +1,22 @@ +f459ecbed6621933b4dee4a613a6bdca915631742083f77ab88752f3ae0c6a9d syft_1.5.0_darwin_amd64.sbom +605322e3e7043a4f2f3d6e37f75a71389d38f6f290bff2e54bb2aaebbbf4829b syft_1.5.0_darwin_amd64.tar.gz +2feb92f6a4d117a3eb0cc5d887ac4b8da9a959ca404986dbe76e81ac83569d76 syft_1.5.0_darwin_arm64.sbom +fe02d072e7ec9a8eb4ac866ba973396a8beae79829ee870acaadd4d862e5e65a syft_1.5.0_darwin_arm64.tar.gz +40562766f99db7221dac4c82c44ccae4d9983a6795a96127f4da955d6797c090 syft_1.5.0_linux_amd64.deb +9adc0c0a3bbbdb8ce66914ffde5e176373cf5ec70a2a88cc886dc6ec54db0cd2 syft_1.5.0_linux_amd64.rpm +9de7f1c549020a25df12f07dd58330e6f6dd0c5363cf0de1157eb4f01fc41020 syft_1.5.0_linux_amd64.sbom +3d10023d46dfaf0fe75288df207b478b43597f7d2fff553f58430817166bd478 syft_1.5.0_linux_amd64.tar.gz +b661dd1be48b75b735717f9bedc4beea587968af8bf2d8c2752a302ae0a34f89 syft_1.5.0_linux_arm64.deb +5c311f44cc73fcae58884f8ea3328fc120bdaf3d21f4fe40270a22c6bb981f6d syft_1.5.0_linux_arm64.rpm +a74549794fa5dac79ab9f6401ee7000db3bd9589435b302583c3ee4ca13fb8e3 syft_1.5.0_linux_arm64.sbom +8d57abb57a0dae3ff23c8f0df1f51951b7772822e0d560e860d6f68c24ef6d3d syft_1.5.0_linux_arm64.tar.gz +599e66f0a00ba8b5cc7817f774c66c5f23de32e6b935ca9c03a185e4d2554d80 syft_1.5.0_linux_ppc64le.deb +dc4b8c4a02ffd8dd394ab94695ed44ed2bfceb06bc239835c51e84dd9b84a68c syft_1.5.0_linux_ppc64le.rpm +392044f2951ca6522d0bc71de43763202a548d40bf836098caf286041a7c8fa4 syft_1.5.0_linux_ppc64le.sbom +551d98b67f7476bc2e38453a588177b0b038933850a351a94c4bf360813f01d0 syft_1.5.0_linux_ppc64le.tar.gz +98cd582d9484f428cccd7351031543038f26d4e3f1481c5916e08e65983f1e21 syft_1.5.0_linux_s390x.deb +3a5197d43a469feaa87c723448a47a2312cf26456eef4580b59eac447baef9d4 syft_1.5.0_linux_s390x.rpm +5805bfb3e30452c8860665ea88bfdf356e9536a35c1b8ba28ac5b4717f2e6388 syft_1.5.0_linux_s390x.sbom +ff15f556660cc4c4279ce41e2475bffe2a0f72eb4423c21edf7380b2484fbf68 syft_1.5.0_linux_s390x.tar.gz +6b22df07e992d8f4881901535c095d268f79924e10be34fab03dec2b4f9f9ca0 syft_1.5.0_windows_amd64.sbom +5079c6a88e130f8677d0701cb2689f9eae2088022ecf5fa2b9f341b96d9983d2 syft_1.5.0_windows_amd64.zip diff --git a/test/install/test-fixtures/assets/valid/syft_1.5.0_linux_arm64.tar.gz b/test/install/test-fixtures/assets/valid/syft_1.5.0_linux_arm64.tar.gz new file mode 100644 index 000000000..c90127d2f --- /dev/null +++ b/test/install/test-fixtures/assets/valid/syft_1.5.0_linux_arm64.tar.gz @@ -0,0 +1 @@ +fake archive \ No newline at end of file From f966bcfd03fd80c961c8b480ac084cfc72014a68 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Mon, 10 Jun 2024 13:35:01 -0400 Subject: [PATCH 030/284] trim whitespace from wordpress values (#2945) Signed-off-by: Alex Goodman --- syft/pkg/cataloger/wordpress/parse_plugin.go | 22 +++++++++------ .../cataloger/wordpress/parse_plugin_test.go | 27 +++++++++++++++++++ 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/syft/pkg/cataloger/wordpress/parse_plugin.go b/syft/pkg/cataloger/wordpress/parse_plugin.go index 2facba49a..a3d266b00 100644 --- a/syft/pkg/cataloger/wordpress/parse_plugin.go +++ b/syft/pkg/cataloger/wordpress/parse_plugin.go @@ -5,6 +5,7 @@ import ( "fmt" "path/filepath" "regexp" + "strings" "github.com/anchore/syft/internal" "github.com/anchore/syft/syft/artifact" @@ -39,7 +40,6 @@ type pluginData struct { func parseWordpressPluginFiles(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { var pkgs []pkg.Package - var fields = make(map[string]interface{}) buffer := make([]byte, contentBufferSize) _, err := reader.Read(buffer) @@ -47,13 +47,7 @@ func parseWordpressPluginFiles(_ context.Context, _ file.Resolver, _ *generic.En return nil, nil, fmt.Errorf("failed to read %s file: %w", reader.Location.Path(), err) } - fileContent := string(buffer) - for field, pattern := range patterns { - matchMap := internal.MatchNamedCaptureGroups(pattern, fileContent) - if value := matchMap[field]; value != "" { - fields[field] = value - } - } + fields := extractFields(string(buffer)) name, nameOk := fields["name"] version, versionOk := fields["version"] @@ -96,3 +90,15 @@ func parseWordpressPluginFiles(_ context.Context, _ file.Resolver, _ *generic.En return pkgs, nil, nil } + +func extractFields(in string) map[string]any { + var fields = make(map[string]interface{}) + + for field, pattern := range patterns { + matchMap := internal.MatchNamedCaptureGroups(pattern, in) + if value := matchMap[field]; value != "" { + fields[field] = strings.TrimSpace(value) + } + } + return fields +} diff --git a/syft/pkg/cataloger/wordpress/parse_plugin_test.go b/syft/pkg/cataloger/wordpress/parse_plugin_test.go index 1f71cbd83..a9e10f289 100644 --- a/syft/pkg/cataloger/wordpress/parse_plugin_test.go +++ b/syft/pkg/cataloger/wordpress/parse_plugin_test.go @@ -3,6 +3,8 @@ package wordpress import ( "testing" + "github.com/stretchr/testify/assert" + "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" @@ -30,3 +32,28 @@ func TestParseWordpressPluginFiles(t *testing.T) { pkgtest.TestFileParser(t, fixture, parseWordpressPluginFiles, []pkg.Package{expectedPkg}, nil) } + +func Test_extractFields(t *testing.T) { + tests := []struct { + name string + in string + want map[string]any + }{ + { + name: "carriage returns are stripped", + in: "Plugin Name: WP Migration\r\nVersion: 5.3\r\nLicense: GPLv3\r\nAuthor: MonsterInsights\r\nAuthor URI: https://servmask.com/\r\n", + want: map[string]any{ + "name": "WP Migration", + "version": "5.3", + "license": "GPLv3", + "author": "MonsterInsights", + "author_uri": "https://servmask.com/", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.want, extractFields(tt.in)) + }) + } +} From 0956753409585ee7d25f09bdb8ad650c68164044 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Mon, 10 Jun 2024 14:12:20 -0400 Subject: [PATCH 031/284] Consider `Author` field for wordpress plugins when generating CPEs (#2946) * enhance wordpress vendor candidates for CPEs Signed-off-by: Alex Goodman * encode wordpress plugin target software Signed-off-by: Alex Goodman --------- Signed-off-by: Alex Goodman --- .../internal/cpegenerate/generate.go | 32 ++++++++++++------- .../internal/cpegenerate/generate_test.go | 25 +++++++++++++++ .../internal/cpegenerate/wordpress.go | 10 ++++-- .../internal/cpegenerate/wordpress_test.go | 22 +++++++++++-- 4 files changed, 73 insertions(+), 16 deletions(-) diff --git a/syft/pkg/cataloger/internal/cpegenerate/generate.go b/syft/pkg/cataloger/internal/cpegenerate/generate.go index 3d58ea9f5..4860116a0 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/generate.go +++ b/syft/pkg/cataloger/internal/cpegenerate/generate.go @@ -129,23 +129,26 @@ func FromDictionaryFind(p pkg.Package) ([]cpe.CPE, bool) { func FromPackageAttributes(p pkg.Package) []cpe.CPE { vendors := candidateVendors(p) products := candidateProducts(p) + targetSWs := candidateTargetSw(p) if len(products) == 0 { return nil } keys := strset.New() cpes := make([]cpe.Attributes, 0) - for _, product := range products { - for _, vendor := range vendors { - // prevent duplicate entries... - key := fmt.Sprintf("%s|%s|%s", product, vendor, p.Version) - if keys.Has(key) { - continue - } - keys.Add(key) - // add a new entry... - if c := newCPE(product, vendor, p.Version, cpe.Any); c != nil { - cpes = append(cpes, *c) + for _, ts := range targetSWs { + for _, product := range products { + for _, vendor := range vendors { + // prevent duplicate entries... + key := fmt.Sprintf("%s|%s|%s|%s", product, vendor, p.Version, ts) + if keys.Has(key) { + continue + } + keys.Add(key) + // add a new entry... + if c := newCPE(product, vendor, p.Version, ts); c != nil { + cpes = append(cpes, *c) + } } } } @@ -162,6 +165,13 @@ func FromPackageAttributes(p pkg.Package) []cpe.CPE { return result } +func candidateTargetSw(p pkg.Package) []string { + if p.Type == pkg.WordpressPluginPkg { + return []string{"wordpress"} + } + return []string{cpe.Any} +} + //nolint:funlen func candidateVendors(p pkg.Package) []string { // in ecosystems where the packaging metadata does not have a clear field to indicate a vendor (or a field that diff --git a/syft/pkg/cataloger/internal/cpegenerate/generate_test.go b/syft/pkg/cataloger/internal/cpegenerate/generate_test.go index 633fe3207..e0b9af6cb 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/generate_test.go +++ b/syft/pkg/cataloger/internal/cpegenerate/generate_test.go @@ -719,6 +719,31 @@ func TestGeneratePackageCPEs(t *testing.T) { "cpe:2.3:a:ruby_rake:ruby_rake:2.7.6-r0:*:*:*:*:*:*:*", }, }, + { + name: "wordpress plugin", + p: pkg.Package{ + Name: "WP Coder", + Version: "2.5.1", + Type: pkg.WordpressPluginPkg, + Metadata: pkg.WordpressPluginEntry{ + PluginInstallDirectory: "wp-coder", + Author: "Wow-Company", + AuthorURI: "https://wow-estore.com", + }, + }, + expected: []string{ + "cpe:2.3:a:wow-company:wp-coder:2.5.1:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wow-company:wp_coder:2.5.1:*:*:*:*:wordpress:*:*", // this is the correct CPE relative to CVE-2021-25053 + "cpe:2.3:a:wow-estore:wp-coder:2.5.1:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wow-estore:wp_coder:2.5.1:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wow:wp-coder:2.5.1:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wow:wp_coder:2.5.1:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wow_company:wp-coder:2.5.1:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wow_company:wp_coder:2.5.1:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wow_estore:wp-coder:2.5.1:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wow_estore:wp_coder:2.5.1:*:*:*:*:wordpress:*:*", + }, + }, } for _, test := range tests { diff --git a/syft/pkg/cataloger/internal/cpegenerate/wordpress.go b/syft/pkg/cataloger/internal/cpegenerate/wordpress.go index 3a28b2702..ae71b9fe2 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/wordpress.go +++ b/syft/pkg/cataloger/internal/cpegenerate/wordpress.go @@ -21,12 +21,18 @@ func candidateVendorsForWordpressPlugin(p pkg.Package) fieldCandidateSet { vendors := newFieldCandidateSet() + if metadata.Author != "" { + vendors.addValue(strings.ToLower(metadata.Author)) + } + if metadata.AuthorURI != "" { matchMap := internal.MatchNamedCaptureGroups(vendorFromURLRegexp, metadata.AuthorURI) if vendor, ok := matchMap["vendor"]; ok && vendor != "" { - vendors.addValue(vendor) + vendors.addValue(strings.ToLower(vendor)) } - } else { + } + + if len(vendors) == 0 { // add plugin_name + _project as a vendor if no Author URI found vendors.addValue(fmt.Sprintf("%s_project", normalizeWordpressPluginName(p.Name))) } diff --git a/syft/pkg/cataloger/internal/cpegenerate/wordpress_test.go b/syft/pkg/cataloger/internal/cpegenerate/wordpress_test.go index 939588e92..f292db915 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/wordpress_test.go +++ b/syft/pkg/cataloger/internal/cpegenerate/wordpress_test.go @@ -24,7 +24,7 @@ func Test_candidateVendorsForWordpressPlugin(t *testing.T) { AuthorURI: "https://automattic.com/wordpress-plugins/", }, }, - expected: []string{"automattic"}, + expected: []string{"automattic - anti-spam team", "automattic"}, }, { name: "All-in-One WP Migration", @@ -47,7 +47,7 @@ func Test_candidateVendorsForWordpressPlugin(t *testing.T) { AuthorURI: "https://bookingultrapro.com/", }, }, - expected: []string{"bookingultrapro"}, + expected: []string{"booking ultra pro", "bookingultrapro"}, }, { name: "Coming Soon Chop Chop", @@ -58,7 +58,7 @@ func Test_candidateVendorsForWordpressPlugin(t *testing.T) { AuthorURI: "https://www.chop-chop.org", }, }, - expected: []string{"chop-chop"}, + expected: []string{"chop-chop.org", "chop-chop"}, }, { name: "Access Code Feeder", @@ -71,6 +71,22 @@ func Test_candidateVendorsForWordpressPlugin(t *testing.T) { // When a plugin as no `Author URI` use plugin_name + _project as a vendor expected: []string{"access_code_feeder_project"}, }, + { + name: "WP Coder", + pkg: pkg.Package{ + Name: "WP Coder", + Metadata: pkg.WordpressPluginEntry{ + PluginInstallDirectory: "wp-coder", + Author: "Wow-Company", + AuthorURI: "https://wow-estore.com/", + }, + }, + // found in the wild https://plugins.trac.wordpress.org/browser/wp-coder/tags/2.5.1/wp-coder.php + expected: []string{ + "wow-company", // this is the correct answer relative to CPEs registered on CVE-2021-25053 + "wow-estore", + }, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { From 5590d5c1ceb4b978c2767e447ba7c3700446c3a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Jun 2024 08:08:45 -0700 Subject: [PATCH 032/284] chore(deps): bump modernc.org/sqlite from 1.30.0 to 1.30.1 (#2950) Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.30.0 to 1.30.1. - [Commits](https://gitlab.com/cznic/sqlite/compare/v1.30.0...v1.30.1) --- updated-dependencies: - dependency-name: modernc.org/sqlite dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index e1570c434..fa22d09fe 100644 --- a/go.mod +++ b/go.mod @@ -81,7 +81,7 @@ require ( golang.org/x/mod v0.18.0 golang.org/x/net v0.26.0 gopkg.in/yaml.v3 v3.0.1 - modernc.org/sqlite v1.30.0 + modernc.org/sqlite v1.30.1 ) require google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect @@ -240,7 +240,7 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect - modernc.org/libc v1.50.9 // indirect + modernc.org/libc v1.52.1 // indirect modernc.org/mathutil v1.6.0 // indirect modernc.org/memory v1.8.0 // indirect modernc.org/strutil v1.2.0 // indirect diff --git a/go.sum b/go.sum index 020c825dd..0b300f016 100644 --- a/go.sum +++ b/go.sum @@ -1359,16 +1359,16 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= modernc.org/cc/v4 v4.21.2 h1:dycHFB/jDc3IyacKipCNSDrjIC0Lm1hyoWOZTRR20Lk= modernc.org/cc/v4 v4.21.2/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= -modernc.org/ccgo/v4 v4.17.8 h1:yyWBf2ipA0Y9GGz/MmCmi3EFpKgeS7ICrAFes+suEbs= -modernc.org/ccgo/v4 v4.17.8/go.mod h1:buJnJ6Fn0tyAdP/dqePbrrvLyr6qslFfTbFrCuaYvtA= +modernc.org/ccgo/v4 v4.17.10 h1:6wrtRozgrhCxieCeJh85QsxkX/2FFrT9hdaWPlbn4Zo= +modernc.org/ccgo/v4 v4.17.10/go.mod h1:0NBHgsqTTpm9cA5z2ccErvGZmtntSM9qD2kFAs6pjXM= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= -modernc.org/libc v1.50.9 h1:hIWf1uz55lorXQhfoEoezdUHjxzuO6ceshET/yWjSjk= -modernc.org/libc v1.50.9/go.mod h1:15P6ublJ9FJR8YQCGy8DeQ2Uwur7iW9Hserr/T3OFZE= +modernc.org/libc v1.52.1 h1:uau0VoiT5hnR+SpoWekCKbLqm7v6dhRL3hI+NQhgN3M= +modernc.org/libc v1.52.1/go.mod h1:HR4nVzFDSDizP620zcMCgjb1/8xk2lg5p/8yjfGv1IQ= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= @@ -1377,8 +1377,8 @@ modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= -modernc.org/sqlite v1.30.0 h1:8YhPUs/HTnlEgErn/jSYQTwHN/ex8CjHHjg+K9iG7LM= -modernc.org/sqlite v1.30.0/go.mod h1:cgkTARJ9ugeXSNaLBPK3CqbOe7Ec7ZhWPoMFGldEYEw= +modernc.org/sqlite v1.30.1 h1:YFhPVfu2iIgUf9kuA1CR7iiHdcEEsI2i+yjRYHscyxk= +modernc.org/sqlite v1.30.1/go.mod h1:DUmsiWQDaAvU4abhc/N+djlom/L2o8f7gZ95RCvyoLU= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= From fb684895907cc73b8a61f09b71bd41f7b27d3796 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Tue, 11 Jun 2024 08:09:07 -0700 Subject: [PATCH 033/284] chore(deps): update tools to latest versions (#2949) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index 1ac4de0cb..15d5fc834 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -58,7 +58,7 @@ tools: # used to release all artifacts - name: goreleaser version: - want: v2.0.0 + want: v2.0.1 method: github-release with: repo: goreleaser/goreleaser From dd723bb3c5fcde00795353857094676a9bacd4c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Jun 2024 13:17:06 -0400 Subject: [PATCH 034/284] chore(deps): bump github.com/vbatts/go-mtree from 0.5.3 to 0.5.4 (#2952) Bumps [github.com/vbatts/go-mtree](https://github.com/vbatts/go-mtree) from 0.5.3 to 0.5.4. - [Release notes](https://github.com/vbatts/go-mtree/releases) - [Changelog](https://github.com/vbatts/go-mtree/blob/main/releases.md) - [Commits](https://github.com/vbatts/go-mtree/compare/v0.5.3...v0.5.4) --- updated-dependencies: - dependency-name: github.com/vbatts/go-mtree dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index fa22d09fe..4aacbc628 100644 --- a/go.mod +++ b/go.mod @@ -71,7 +71,7 @@ require ( github.com/spf13/afero v1.11.0 github.com/spf13/cobra v1.8.0 github.com/stretchr/testify v1.9.0 - github.com/vbatts/go-mtree v0.5.3 + github.com/vbatts/go-mtree v0.5.4 github.com/vifraa/gopom v1.0.0 github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0 diff --git a/go.sum b/go.sum index 0b300f016..1605ba10b 100644 --- a/go.sum +++ b/go.sum @@ -791,8 +791,8 @@ github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/vbatts/go-mtree v0.5.3 h1:S/jYlfG8rZ+a0bhZd+RANXejy7M4Js8fq9U+XoWTd5w= -github.com/vbatts/go-mtree v0.5.3/go.mod h1:eXsdoPMdL2jcJx6HweWi9lYQxBsTp4lNhqqAjgkZUg8= +github.com/vbatts/go-mtree v0.5.4 h1:OMAb8jaCyiFA7zXj0Zc/oARcxBDBoeu2LizjB8BVJl0= +github.com/vbatts/go-mtree v0.5.4/go.mod h1:5GqJbVhm9BBiCc4K5uc/c42FPgXulHaQs4sFUEfIWMo= github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RVck= github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY= github.com/vifraa/gopom v1.0.0 h1:L9XlKbyvid8PAIK8nr0lihMApJQg/12OBvMA28BcWh0= From ca0cc52d47b103642c4b8516cf7a09a7a2671656 Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Wed, 12 Jun 2024 19:12:35 -0400 Subject: [PATCH 035/284] fix: separate golang license caches from mod dir (#2852) Signed-off-by: Keith Zantow --- cmd/syft/internal/commands/attest.go | 2 + cmd/syft/internal/commands/scan.go | 2 + cmd/syft/internal/options/cache.go | 122 ++++++++ cmd/syft/internal/options/cache_test.go | 184 +++++++++++ go.mod | 6 +- internal/cache/README.md | 51 +++ internal/cache/bypass.go | 24 ++ internal/cache/bypass_test.go | 18 ++ internal/cache/cache.go | 48 +++ internal/cache/cache_test.go | 21 ++ internal/cache/error_resolver.go | 40 +++ internal/cache/error_resolver_test.go | 47 +++ internal/cache/filesystem.go | 120 +++++++ internal/cache/filesystem_test.go | 94 ++++++ internal/cache/hash_type.go | 71 +++++ internal/cache/hash_type_test.go | 123 ++++++++ internal/cache/memory.go | 16 + internal/cache/memory_test.go | 37 +++ internal/cache/resolver.go | 83 +++++ internal/cache/resolver_test.go | 92 ++++++ syft/pkg/cataloger/golang/cataloger.go | 6 +- syft/pkg/cataloger/golang/config.go | 28 +- syft/pkg/cataloger/golang/config_test.go | 3 +- syft/pkg/cataloger/golang/licenses.go | 293 ++++++++++++------ syft/pkg/cataloger/golang/licenses_test.go | 32 +- syft/pkg/cataloger/golang/package.go | 2 +- syft/pkg/cataloger/golang/parse_go_binary.go | 4 +- syft/pkg/cataloger/golang/parse_go_mod.go | 12 +- .../pkg/cataloger/golang/parse_go_mod_test.go | 4 +- syft/source/directorysource/cache_excludes.go | 33 ++ .../directorysource/directory_source.go | 3 + 31 files changed, 1484 insertions(+), 137 deletions(-) create mode 100644 cmd/syft/internal/options/cache.go create mode 100644 cmd/syft/internal/options/cache_test.go create mode 100644 internal/cache/README.md create mode 100644 internal/cache/bypass.go create mode 100644 internal/cache/bypass_test.go create mode 100644 internal/cache/cache.go create mode 100644 internal/cache/cache_test.go create mode 100644 internal/cache/error_resolver.go create mode 100644 internal/cache/error_resolver_test.go create mode 100644 internal/cache/filesystem.go create mode 100644 internal/cache/filesystem_test.go create mode 100644 internal/cache/hash_type.go create mode 100644 internal/cache/hash_type_test.go create mode 100644 internal/cache/memory.go create mode 100644 internal/cache/memory_test.go create mode 100644 internal/cache/resolver.go create mode 100644 internal/cache/resolver_test.go create mode 100644 syft/source/directorysource/cache_excludes.go diff --git a/cmd/syft/internal/commands/attest.go b/cmd/syft/internal/commands/attest.go index 8e01cbc68..374945eff 100644 --- a/cmd/syft/internal/commands/attest.go +++ b/cmd/syft/internal/commands/attest.go @@ -43,6 +43,7 @@ type attestOptions struct { options.UpdateCheck `yaml:",inline" mapstructure:",squash"` options.Catalog `yaml:",inline" mapstructure:",squash"` Attest options.Attest `yaml:"attest" mapstructure:"attest"` + Cache options.Cache `json:"-" yaml:"cache" mapstructure:"cache"` } func Attest(app clio.Application) *cobra.Command { @@ -77,6 +78,7 @@ func defaultAttestOptions() attestOptions { Output: defaultAttestOutputOptions(), UpdateCheck: options.DefaultUpdateCheck(), Catalog: options.DefaultCatalog(), + Cache: options.DefaultCache(), } } diff --git a/cmd/syft/internal/commands/scan.go b/cmd/syft/internal/commands/scan.go index 31f3277ef..ff5b4254f 100644 --- a/cmd/syft/internal/commands/scan.go +++ b/cmd/syft/internal/commands/scan.go @@ -68,6 +68,7 @@ type scanOptions struct { options.Output `yaml:",inline" mapstructure:",squash"` options.UpdateCheck `yaml:",inline" mapstructure:",squash"` options.Catalog `yaml:",inline" mapstructure:",squash"` + Cache options.Cache `json:"-" yaml:"cache" mapstructure:"cache"` } func defaultScanOptions() *scanOptions { @@ -75,6 +76,7 @@ func defaultScanOptions() *scanOptions { Output: options.DefaultOutput(), UpdateCheck: options.DefaultUpdateCheck(), Catalog: options.DefaultCatalog(), + Cache: options.DefaultCache(), } } diff --git a/cmd/syft/internal/options/cache.go b/cmd/syft/internal/options/cache.go new file mode 100644 index 000000000..d8e4130a2 --- /dev/null +++ b/cmd/syft/internal/options/cache.go @@ -0,0 +1,122 @@ +package options + +import ( + "fmt" + "os" + "path/filepath" + "regexp" + "strconv" + "strings" + "time" + + "github.com/adrg/xdg" + "github.com/mitchellh/go-homedir" + + "github.com/anchore/clio" + "github.com/anchore/syft/internal/cache" + "github.com/anchore/syft/internal/log" +) + +// Cache provides configuration for the Syft caching behavior +type Cache struct { + Dir string `yaml:"dir" mapstructure:"dir"` + TTL string `yaml:"ttl" mapstructure:"ttl"` +} + +func (c *Cache) DescribeFields(descriptions clio.FieldDescriptionSet) { + descriptions.Add(&c.Dir, "root directory to cache any downloaded content") + descriptions.Add(&c.TTL, "time to live for cached data") +} + +func (c *Cache) PostLoad() error { + if c.Dir != "" { + ttl, err := parseDuration(c.TTL) + if err != nil { + log.Warnf("unable to parse duration '%v', using default (%s) due to: %v", c.TTL, durationToString(defaultTTL()), err) + ttl = defaultTTL() + } + dir, err := homedir.Expand(c.Dir) + if err != nil { + log.Warnf("unable to expand cache directory %s: %v", c.Dir, err) + cache.SetManager(cache.NewInMemory(ttl)) + } else { + m, err := cache.NewFromDir(dir, ttl) + if err != nil { + log.Warnf("unable to get filesystem cache at %s: %v", c.Dir, err) + cache.SetManager(cache.NewInMemory(ttl)) + } else { + cache.SetManager(m) + } + } + } + return nil +} + +var _ interface { + clio.PostLoader + clio.FieldDescriber +} = (*Cache)(nil) + +func DefaultCache() Cache { + return Cache{ + Dir: defaultDir(), + TTL: durationToString(defaultTTL()), + } +} + +func defaultTTL() time.Duration { + return 7 * 24 * time.Hour +} + +func defaultDir() string { + var err error + cacheRoot := xdg.CacheHome + if cacheRoot == "" { + cacheRoot, err = homedir.Dir() + if err != nil { + cacheRoot = os.TempDir() + log.Debugf("unable to get stable cache directory due to: %v, defaulting cache to temp dir: %s", err, cacheRoot) + } else { + cacheRoot = filepath.Join(cacheRoot, ".cache") + } + } + + return filepath.Join(cacheRoot, "syft") +} + +func durationToString(duration time.Duration) string { + days := int64(duration / (24 * time.Hour)) + remain := duration % (24 * time.Hour) + out := "" + if days > 0 { + out = fmt.Sprintf("%vd", days) + } + if remain != 0 { + out += remain.String() + } + if out == "" { + return "0" + } + return out +} + +var whitespace = regexp.MustCompile(`\s+`) + +func parseDuration(duration string) (time.Duration, error) { + duration = strings.ToLower(whitespace.ReplaceAllString(duration, "")) + parts := strings.SplitN(duration, "d", 2) + var days time.Duration + var remain time.Duration + var err error + if len(parts) > 1 { + numDays, daysErr := strconv.Atoi(parts[0]) + if daysErr != nil { + return 0, daysErr + } + days = time.Duration(numDays) * 24 * time.Hour + remain, err = time.ParseDuration(parts[1]) + } else { + remain, err = time.ParseDuration(duration) + } + return days + remain, err +} diff --git a/cmd/syft/internal/options/cache_test.go b/cmd/syft/internal/options/cache_test.go new file mode 100644 index 000000000..e9bf92087 --- /dev/null +++ b/cmd/syft/internal/options/cache_test.go @@ -0,0 +1,184 @@ +package options + +import ( + "os" + "path/filepath" + "strings" + "testing" + "time" + + "github.com/adrg/xdg" + "github.com/mitchellh/go-homedir" + "github.com/stretchr/testify/require" +) + +func Test_defaultDir(t *testing.T) { + tmpDir := filepath.Join(t.TempDir(), "cache-temp") + xdgCacheDir := filepath.Join(tmpDir, "fake-xdg-cache") + homeDir := filepath.Join(tmpDir, "fake-home") + + tests := []struct { + name string + env map[string]string + expected string + }{ + { + name: "no-xdg", + env: map[string]string{ + "HOME": homeDir, + }, + expected: homeDir, + }, + { + name: "xdg-cache", + env: map[string]string{ + "XDG_CACHE_HOME": xdgCacheDir, + }, + expected: xdgCacheDir, + }, + } + + // capture all the initial environment variables to reset them before we reset library caches + env := map[string]string{ + "HOME": "", + "XDG_DATA_HOME": "", + "XDG_DATA_DIRS": "", + "XDG_CONFIG_HOME": "", + "XDG_CONFIG_DIRS": "", + "XDG_STATE_HOME": "", + "XDG_CACHE_HOME": "", + "XDG_RUNTIME_DIR": "", + } + for k := range env { + env[k] = os.Getenv(k) + } + + unsetEnv := func(t *testing.T) { + for k := range env { + t.Setenv(k, "") + } + } + + resetEnv := func() { + for k, v := range env { + if v == "" { + _ = os.Unsetenv(k) + } else { + _ = os.Setenv(k, v) + } + } + homedir.Reset() + xdg.Reload() + } + + t.Cleanup(resetEnv) + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + defer resetEnv() + + unsetEnv(t) + for k, v := range test.env { + t.Setenv(k, v) + } + homedir.Reset() + xdg.Reload() + + got := defaultDir() + + require.True(t, strings.HasPrefix(got, test.expected)) + }) + } +} + +func Test_parseDuration(t *testing.T) { + tests := []struct { + duration string + expect time.Duration + err require.ErrorAssertionFunc + }{ + { + duration: "1d", + expect: 24 * time.Hour, + }, + { + duration: "7d", + expect: 7 * 24 * time.Hour, + }, + { + duration: "365D", + expect: 365 * 24 * time.Hour, + }, + { + duration: "7d1h1m1s", + expect: 7*24*time.Hour + time.Hour + time.Minute + time.Second, + }, + { + duration: "7d 1h 1m 1s", + expect: 7*24*time.Hour + time.Hour + time.Minute + time.Second, + }, + { + duration: "2h", + expect: 2 * time.Hour, + }, + { + duration: "2h5m", + expect: 2*time.Hour + 5*time.Minute, + }, + { + duration: "2h 5m", + expect: 2*time.Hour + 5*time.Minute, + }, + { + duration: "d24h", + err: require.Error, + }, + } + + for _, test := range tests { + t.Run(test.duration, func(t *testing.T) { + got, err := parseDuration(test.duration) + if test.err != nil { + test.err(t, err) + return + } + require.Equal(t, test.expect, got) + }) + } +} + +func Test_durationToString(t *testing.T) { + tests := []struct { + duration time.Duration + expect string + err require.ErrorAssertionFunc + }{ + { + expect: "1d", + duration: 24 * time.Hour, + }, + { + expect: "7d", + duration: 7 * 24 * time.Hour, + }, + { + expect: "7d1h1m1s", + duration: 7*24*time.Hour + time.Hour + time.Minute + time.Second, + }, + { + expect: "2h0m0s", + duration: 2 * time.Hour, + }, + { + expect: "2h5m0s", + duration: 2*time.Hour + 5*time.Minute, + }, + } + + for _, test := range tests { + t.Run(test.expect, func(t *testing.T) { + got := durationToString(test.duration) + require.Equal(t, test.expect, got) + }) + } +} diff --git a/go.mod b/go.mod index 4aacbc628..3c345cef0 100644 --- a/go.mod +++ b/go.mod @@ -86,7 +86,10 @@ require ( require google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect -require github.com/magiconair/properties v1.8.7 +require ( + github.com/adrg/xdg v0.4.0 + github.com/magiconair/properties v1.8.7 +) require ( dario.cat/mergo v1.0.0 // indirect @@ -98,7 +101,6 @@ require ( github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect github.com/ProtonMail/go-crypto v1.0.0 // indirect - github.com/adrg/xdg v0.4.0 // indirect github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect github.com/andybalholm/brotli v1.0.4 // indirect github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492 // indirect diff --git a/internal/cache/README.md b/internal/cache/README.md new file mode 100644 index 000000000..174e03b9e --- /dev/null +++ b/internal/cache/README.md @@ -0,0 +1,51 @@ +# Caching + +All caches are created from a global `manager`. By defaut this is a `bypassedCache`, which performs no caching. +One benefit of this is that tests don't need to worry about caching causing issues unless they explicitly need +to test the cache and can opt-in using the `cache.TestCache(t)` helper. + +Syft sets a `filesystemCache` when the [cache options](../../cmd/syft/internal/options/cache.go) are loaded. + +When using the `filesystemCache` all items are stored on disk under a root directory, generally in the form of: +``` +///path/to/data +``` + +# Using the cache + +The easiest and preferred method to use the cache is a `cache.Resolver`, which automatically creates a `` +based on the _structure_ of the provided type. +If the structure changes in any way it will end up with a new version key and all will re populate this new key, +ignoring cached values from older, different versions. +The resolver will store items using the `json` package to serialize/deserialize values, so to save space +it is encouraged to use `omitempty`. For example: + +```go +type myCacheItem struct { + Name string `json:"name",omitempty` +} +``` + +It is possible to use core types such as `pkg.Package` as long as they support the standard `json` serialization, +but this is discouraged in order to decouple changes to them from affecting the information stored in the cache. + +To get a cache for this type: +```go +resolver := cache.GetResolver[myCacheItem]("myCacheName", "v1") +``` + +Using the `resolver` is a single call, which manages checking for items in the cache, expiry times, +and if not found invoking the callback to populate the cache and return a value: +```go +data := resolver.Resolve("some/cache/key", func() (myCacheItem, error) { + // do things to return a myCacheItem or error +}) +``` + +If it is common that checking for an item will result in errors, and you do not want to re-run the resolve function +when errors are encountered, instead of using `GetResolver`, you can use `GetResolverCachingErrors`, which is useful +for things such as resolving artifacts over a network, where a number of them will not be resolved, and you do not want +to continue to have the expense of running the network resolution. This should be used when it is acceptable a network +outage and cached errors is an acceptable risk. + +An example can be seen in the [golang cataloger](../../syft/pkg/cataloger/golang/licenses.go) fetching remote licenses. diff --git a/internal/cache/bypass.go b/internal/cache/bypass.go new file mode 100644 index 000000000..4d32f1a61 --- /dev/null +++ b/internal/cache/bypass.go @@ -0,0 +1,24 @@ +package cache + +import "io" + +type bypassedCache struct{} + +func (b *bypassedCache) Read(_ string) (ReaderAtCloser, error) { + return nil, errNotFound +} + +func (b *bypassedCache) Write(_ string, contents io.Reader) error { + if closer, ok := contents.(io.Closer); ok { + _ = closer.Close() + } + return nil +} + +func (b *bypassedCache) GetCache(_, _ string) Cache { + return b +} + +func (b *bypassedCache) RootDirs() []string { + return nil +} diff --git a/internal/cache/bypass_test.go b/internal/cache/bypass_test.go new file mode 100644 index 000000000..073c0ef36 --- /dev/null +++ b/internal/cache/bypass_test.go @@ -0,0 +1,18 @@ +package cache + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func Test_bypassedCache(t *testing.T) { + m := bypassedCache{} + cache := m.GetCache("name", "version") + err := cache.Write("test", strings.NewReader("value")) + require.NoError(t, err) + rdr, err := cache.Read("test") + require.Nil(t, rdr) + require.ErrorIs(t, err, errNotFound) +} diff --git a/internal/cache/cache.go b/internal/cache/cache.go new file mode 100644 index 000000000..02208504e --- /dev/null +++ b/internal/cache/cache.go @@ -0,0 +1,48 @@ +package cache + +import ( + "io" +) + +// Manager is responsible for managing cache data and instantiating all caches +type Manager interface { + // GetCache returns a cache scoped to the given named, versioned data + GetCache(name, version string) Cache + + // RootDirs returns any root directories this cache manager uses + RootDirs() []string +} + +// ReaderAtCloser is an amalgamation of: io.Reader, io.ReaderAt, and io.Closer +type ReaderAtCloser interface { + io.Reader + io.ReaderAt + io.Closer +} + +// Cache is what the application interacts with to get and set cached data +type Cache interface { + // Read returns a reader for the cache value, if found and not expired + // or errors when unable to find / expired + Read(key string) (ReaderAtCloser, error) + + // Write writes the contents of the reader to the cache + // and closes it, if the reader implements io.Closer + Write(key string, contents io.Reader) error +} + +// GetManager returns the global cache manager, which is used to instantiate all caches +func GetManager() Manager { + return manager +} + +// SetManager sets the global cache manager, which is used to instantiate all caches +func SetManager(m Manager) { + if m == nil { + manager = &bypassedCache{} + } else { + manager = m + } +} + +var manager Manager = &bypassedCache{} diff --git a/internal/cache/cache_test.go b/internal/cache/cache_test.go new file mode 100644 index 000000000..548a4b03b --- /dev/null +++ b/internal/cache/cache_test.go @@ -0,0 +1,21 @@ +package cache + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func Test_SetManager(t *testing.T) { + original := GetManager() + defer SetManager(original) + + SetManager(NewInMemory(0)) + + require.NotNil(t, GetManager()) + require.IsType(t, &filesystemCache{}, GetManager()) + + SetManager(nil) + require.NotNil(t, GetManager()) + require.IsType(t, &bypassedCache{}, GetManager()) +} diff --git a/internal/cache/error_resolver.go b/internal/cache/error_resolver.go new file mode 100644 index 000000000..614d707f1 --- /dev/null +++ b/internal/cache/error_resolver.go @@ -0,0 +1,40 @@ +package cache + +import "fmt" + +// GetResolverCachingErrors returns a Resolver that caches errors and will return them +// instead of continuing to call the provided resolve functions +func GetResolverCachingErrors[T any](name, version string) Resolver[T] { + return &errorResolver[T]{ + resolver: GetResolver[errResponse[T]](name, version), + } +} + +type errResponse[T any] struct { + Error string `json:"err,omitempty"` + Value T `json:"val,omitempty"` +} + +type errorResolver[T any] struct { + resolver Resolver[errResponse[T]] +} + +func (r *errorResolver[T]) Resolve(key string, resolver resolverFunc[T]) (T, error) { + v, err := r.resolver.Resolve(key, func() (errResponse[T], error) { + v, err := resolver() + out := errResponse[T]{ + Value: v, + } + if err != nil { + out.Error = err.Error() + } + return out, nil + }) + if err != nil { + return v.Value, err + } + if v.Error != "" { + return v.Value, fmt.Errorf(v.Error) + } + return v.Value, nil +} diff --git a/internal/cache/error_resolver_test.go b/internal/cache/error_resolver_test.go new file mode 100644 index 000000000..b7216a536 --- /dev/null +++ b/internal/cache/error_resolver_test.go @@ -0,0 +1,47 @@ +package cache + +import ( + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func Test_errorResolver(t *testing.T) { + original := GetManager() + defer SetManager(original) + SetManager(NewInMemory(time.Hour)) + + resolver := GetResolverCachingErrors[string]("theCache", "theVersion") + + resolveCount := 0 + resolveFunc := func() (string, error) { + resolveCount++ + return "theValue", nil + } + + val, err := resolver.Resolve("theKey", resolveFunc) + require.NoError(t, err) + require.Equal(t, 1, resolveCount) + require.Equal(t, "theValue", val) + + val, err = resolver.Resolve("theKey", resolveFunc) + require.NoError(t, err) + require.Equal(t, 1, resolveCount) + require.Equal(t, "theValue", val) + + errorCount := 0 + errorFunc := func() (string, error) { + errorCount++ + return "", fmt.Errorf("an error") + } + + _, err = resolver.Resolve("errorValue", errorFunc) + require.ErrorContains(t, err, "an error") + require.Equal(t, 1, errorCount) + + _, err = resolver.Resolve("errorValue", errorFunc) + require.ErrorContains(t, err, "an error") + require.Equal(t, 1, errorCount) +} diff --git a/internal/cache/filesystem.go b/internal/cache/filesystem.go new file mode 100644 index 000000000..8b628cc50 --- /dev/null +++ b/internal/cache/filesystem.go @@ -0,0 +1,120 @@ +package cache + +import ( + "errors" + "fmt" + "io" + "net/url" + "os" + "path/filepath" + "regexp" + "strings" + "time" + + "github.com/spf13/afero" + + "github.com/anchore/syft/internal/log" +) + +// NewFromDir creates a new cache manager which returns caches stored on disk, rooted at the given directory +func NewFromDir(dir string, ttl time.Duration) (Manager, error) { + dir = filepath.Clean(dir) + fsys, err := subFs(afero.NewOsFs(), dir) + if err != nil { + return nil, err + } + return &filesystemCache{ + dir: dir, + fs: fsys, + ttl: ttl, + }, nil +} + +const filePermissions = 0700 +const dirPermissions = os.ModeDir | filePermissions + +type filesystemCache struct { + dir string + fs afero.Fs + ttl time.Duration +} + +func (d *filesystemCache) GetCache(name, version string) Cache { + fsys, err := subFs(d.fs, name, version) + if err != nil { + log.Warnf("error getting cache for: %s/%s: %v", name, version, err) + return &bypassedCache{} + } + return &filesystemCache{ + dir: filepath.Join(d.dir, name, version), + fs: fsys, + ttl: d.ttl, + } +} + +func (d *filesystemCache) RootDirs() []string { + if d.dir == "" { + return nil + } + return []string{d.dir} +} + +func (d *filesystemCache) Read(key string) (ReaderAtCloser, error) { + path := makeDiskKey(key) + f, err := d.fs.Open(path) + if err != nil { + log.Tracef("no cache entry for %s %s: %v", d.dir, key, err) + return nil, errNotFound + } else if stat, err := f.Stat(); err != nil || stat == nil || time.Since(stat.ModTime()) > d.ttl { + log.Tracef("cache entry is too old for %s %s", d.dir, key) + return nil, errExpired + } + log.Tracef("using cache for %s %s", d.dir, key) + return f, nil +} + +func (d *filesystemCache) Write(key string, contents io.Reader) error { + path := makeDiskKey(key) + return afero.WriteReader(d.fs, path, contents) +} + +// subFs returns a writable directory with the given name under the root cache directory returned from findRoot, +// the directory will be created if it does not exist +func subFs(fsys afero.Fs, subDirs ...string) (afero.Fs, error) { + dir := filepath.Join(subDirs...) + dir = filepath.Clean(dir) + stat, err := fsys.Stat(dir) + if errors.Is(err, afero.ErrFileNotFound) { + err = fsys.MkdirAll(dir, dirPermissions) + if err != nil { + return nil, fmt.Errorf("unable to create directory at '%s/%s': %v", dir, strings.Join(subDirs, "/"), err) + } + stat, err = fsys.Stat(dir) + if err != nil { + return nil, err + } + } + if err != nil || stat == nil || !stat.IsDir() { + return nil, fmt.Errorf("unable to verify directory '%s': %v", dir, err) + } + fsys = afero.NewBasePathFs(fsys, dir) + return fsys, err +} + +var keyReplacer = regexp.MustCompile("[^-._/a-zA-Z0-9]") + +// makeDiskKey makes a safe sub-path but not escape forward slashes, this allows for logical partitioning on disk +func makeDiskKey(key string) string { + // encode single dot directory + if key == "." { + return "%2E" + } + // replace any disallowed chars with encoded form + key = keyReplacer.ReplaceAllStringFunc(key, url.QueryEscape) + // allow . in names but not .. + key = strings.ReplaceAll(key, "..", "%2E%2E") + return key +} + +var errNotFound = fmt.Errorf("not found") +var errExpired = fmt.Errorf("expired") diff --git a/internal/cache/filesystem_test.go b/internal/cache/filesystem_test.go new file mode 100644 index 000000000..721cb9f6a --- /dev/null +++ b/internal/cache/filesystem_test.go @@ -0,0 +1,94 @@ +package cache + +import ( + "io" + "net/url" + "os" + "path/filepath" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/anchore/syft/internal" +) + +func Test_filesystemCache(t *testing.T) { + dir := t.TempDir() + man, err := NewFromDir(dir, 1*time.Minute) + require.NoError(t, err) + + cacheName := "test" + cacheVersion := "v1" + cache := man.GetCache(cacheName, cacheVersion) + + cacheKey := "test-key" + contentsValue := "some contents to cache" + + err = cache.Write(cacheKey, strings.NewReader(contentsValue)) + require.NoError(t, err) + + rdr, err := cache.Read(cacheKey) + require.NoError(t, err) + defer internal.CloseAndLogError(rdr, cacheKey) + + contents, err := io.ReadAll(rdr) + require.NoError(t, err) + require.Equal(t, contentsValue, string(contents)) + + // check the contents were actually written to disk as expected + contents, err = os.ReadFile(filepath.Join(dir, cacheName, cacheVersion, cacheKey)) + require.NoError(t, err) + require.Equal(t, contentsValue, string(contents)) + + _, err = cache.Read("otherKey") + require.ErrorIs(t, err, errNotFound) +} + +func Test_makeDiskKey(t *testing.T) { + tests := []struct { + in string + expected string + }{ + { + in: "", + expected: "", + }, + { + in: ".", + expected: "%2E", + }, + { + in: "..", + expected: "%2E%2E", + }, + { + in: "github.com", + expected: "github.com", + }, + { + in: "../github.com", + expected: "%2E%2E/github.com", + }, + { + in: "github.com/../..", + expected: "github.com/%2E%2E/%2E%2E", + }, + { + in: "github.com/%2E../..", + expected: "github.com/%252E%2E%2E/%2E%2E", + }, + } + for _, test := range tests { + t.Run(test.in, func(t *testing.T) { + got := makeDiskKey(test.in) + // validate appropriate escaping + require.Equal(t, test.expected, got) + // also validate that unescaped string matches original + unescaped, err := url.QueryUnescape(got) + require.NoError(t, err) + require.Equal(t, test.in, unescaped) + }) + } +} diff --git a/internal/cache/hash_type.go b/internal/cache/hash_type.go new file mode 100644 index 000000000..c7b3c4a42 --- /dev/null +++ b/internal/cache/hash_type.go @@ -0,0 +1,71 @@ +package cache + +import ( + "fmt" + "reflect" + + "github.com/mitchellh/hashstructure/v2" +) + +// hashType returns a stable hash based on the structure of the type +func hashType[T any]() string { + // get the base type and hash an empty instance + var t T + empty := emptyValue(reflect.TypeOf(t)).Interface() + hash, err := hashstructure.Hash(empty, hashstructure.FormatV2, &hashstructure.HashOptions{ + ZeroNil: false, + IgnoreZeroValue: false, + SlicesAsSets: false, + UseStringer: false, + }) + if err != nil { + panic(fmt.Errorf("unable to use type as cache key: %w", err)) + } + return fmt.Sprintf("%x", hash) +} + +func emptyValue(t reflect.Type) reflect.Value { + switch t.Kind() { + case reflect.Pointer: + e := t.Elem() + v := emptyValue(e) + if v.CanAddr() { + return v.Addr() + } + ptrv := reflect.New(e) + ptrv.Elem().Set(v) + return ptrv + case reflect.Slice: + v := emptyValue(t.Elem()) + s := reflect.MakeSlice(t, 1, 1) + s.Index(0).Set(v) + return s + case reflect.Struct: + v := reflect.New(t).Elem() + // get all empty field values, too + for i := 0; i < v.NumField(); i++ { + f := t.Field(i) + if isIgnored(f) { + continue + } + fv := v.Field(i) + if fv.CanSet() { + fv.Set(emptyValue(f.Type)) + } + } + return v + default: + return reflect.New(t).Elem() + } +} + +func isIgnored(f reflect.StructField) bool { + if !f.IsExported() { + return true + } + tag := f.Tag.Get("hash") + if tag == "-" || tag == "ignore" { + return true + } + return false +} diff --git a/internal/cache/hash_type_test.go b/internal/cache/hash_type_test.go new file mode 100644 index 000000000..3fe24cbd3 --- /dev/null +++ b/internal/cache/hash_type_test.go @@ -0,0 +1,123 @@ +package cache + +import ( + "fmt" + "testing" + + "github.com/mitchellh/hashstructure/v2" + "github.com/stretchr/testify/require" +) + +func Test_hashType(t *testing.T) { + type t1 struct { + Name string + } + type t2 struct { + Name string + } + type generic[T any] struct { + Val T + } + tests := []struct { + name string + hash func() string + expected string + }{ + { + name: "struct 1", + hash: func() string { return hashType[t1]() }, + expected: "d106c3ffbf98a0b1", + }, + { + name: "slice of struct 1", + hash: func() string { return hashType[[]t1]() }, + expected: "8122ace4ee1af0b4", + }, + { + name: "slice of struct 2", + hash: func() string { return hashType[[]t2]() }, + expected: "8cc04b5808be5bf9", + }, + { + name: "ptr 1", + hash: func() string { return hashType[*t1]() }, + expected: "d106c3ffbf98a0b1", // same hash as t1, which is ok since the structs are the same + }, + { + name: "slice of ptr 1", + hash: func() string { return hashType[[]*t1]() }, + expected: "8122ace4ee1af0b4", // same hash as []t1, again underlying serialization is the same + }, + { + name: "slice of ptr 2", + hash: func() string { return hashType[[]*t2]() }, + expected: "8cc04b5808be5bf9", // same hash as []t2, underlying serialization is the same + }, + { + name: "slice of ptr of slice of ptr", + hash: func() string { return hashType[[]*[]*t1]() }, + expected: "500d9f5b3a5977ce", + }, + { + name: "generic 1", + hash: func() string { return hashType[generic[t1]]() }, + expected: "b5fbb30e24400e81", + }, + { + name: "generic 2", + hash: func() string { return hashType[generic[t2]]() }, + expected: "becdb767c6b22bfa", + }, + { + name: "generic with ptr 1", + hash: func() string { return hashType[generic[*t1]]() }, + expected: "30c8855bf290fd83", + }, + { + name: "generic with ptr 2", + hash: func() string { return hashType[generic[*t2]]() }, + expected: "b66366b6ce9e6361", + }, + { + name: "generic with slice 1", + hash: func() string { return hashType[generic[[]t1]]() }, + expected: "d2ed158942fa6c29", + }, + { + name: "generic with slice 2", + hash: func() string { return hashType[generic[[]t2]]() }, + expected: "7a7bec575871c179", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + require.Equal(t, test.expected, test.hash()) + }) + } +} + +func Test_hashIgnores(t *testing.T) { + hash := func(v any) string { + v, err := hashstructure.Hash(v, hashstructure.FormatV2, &hashstructure.HashOptions{}) + require.NoError(t, err) + return fmt.Sprintf("%x", v) + } + type t1 struct { + Name string + notExported string + } + require.Equal(t, hash(t1{notExported: "a value"}), hashType[t1]()) + + type t2 struct { + Name string + Exported string `hash:"ignore"` + } + require.Equal(t, hash(t2{Exported: "another value"}), hashType[t2]()) + + type t3 struct { + Name string + Exported string `hash:"-"` + } + require.Equal(t, hash(t3{Exported: "still valued"}), hashType[t3]()) +} diff --git a/internal/cache/memory.go b/internal/cache/memory.go new file mode 100644 index 000000000..247e67e0d --- /dev/null +++ b/internal/cache/memory.go @@ -0,0 +1,16 @@ +package cache + +import ( + "time" + + "github.com/spf13/afero" +) + +// NewInMemory returns an in-memory only cache manager +func NewInMemory(ttl time.Duration) Manager { + return &filesystemCache{ + dir: "", + fs: afero.NewMemMapFs(), + ttl: ttl, + } +} diff --git a/internal/cache/memory_test.go b/internal/cache/memory_test.go new file mode 100644 index 000000000..e8bcbef7f --- /dev/null +++ b/internal/cache/memory_test.go @@ -0,0 +1,37 @@ +package cache + +import ( + "io" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/anchore/syft/internal" +) + +func Test_NewInMemory(t *testing.T) { + man := NewInMemory(time.Hour) + + cacheName := "test" + cacheVersion := "v1" + cache := man.GetCache(cacheName, cacheVersion) + + cacheKey := "test-key" + contentsValue := "some contents to cache" + + err := cache.Write(cacheKey, strings.NewReader(contentsValue)) + require.NoError(t, err) + + rdr, err := cache.Read(cacheKey) + require.NoError(t, err) + defer internal.CloseAndLogError(rdr, cacheKey) + + contents, err := io.ReadAll(rdr) + require.NoError(t, err) + require.Equal(t, contentsValue, string(contents)) + + _, err = cache.Read("otherKey") + require.ErrorIs(t, err, errNotFound) +} diff --git a/internal/cache/resolver.go b/internal/cache/resolver.go new file mode 100644 index 000000000..68af21a2b --- /dev/null +++ b/internal/cache/resolver.go @@ -0,0 +1,83 @@ +package cache + +import ( + "bytes" + "encoding/json" + "fmt" + "path" + + "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/log" +) + +// Resolver interface provides a single Resolve method, which will return from cache +// or call the provided resolve function to get the value if not available in cache +type Resolver[T any] interface { + // Resolve attempts to resolve the given key from cache and convert it to the type of the cache, + // or calls the resolver function if unable to resolve a cached value + Resolve(key string, resolver resolverFunc[T]) (T, error) +} + +// GetResolver returns a cache resolver for persistent cached data across Syft runs, stored in a unique +// location based on the provided name and versioned by the type +func GetResolver[T any](name, version string) Resolver[T] { + typeHash := hashType[T]() + versionKey := path.Join(version, typeHash) + return &cacheResolver[T]{ + name: fmt.Sprintf("%s/%s", name, versionKey), + cache: manager.GetCache(name, versionKey), + } +} + +const resolverKeySuffix = ".json" + +type resolverFunc[T any] func() (T, error) + +type cacheResolver[T any] struct { + name string + cache Cache +} + +var _ interface { + Resolver[int] +} = (*cacheResolver[int])(nil) + +func (r *cacheResolver[T]) Resolve(key string, resolver resolverFunc[T]) (T, error) { + key += resolverKeySuffix + + rdr, err := r.cache.Read(key) + if rdr == nil || err != nil { + return r.resolveAndCache(key, resolver) + } + defer internal.CloseAndLogError(rdr, key) + + dec := json.NewDecoder(rdr) + if dec == nil { + log.Tracef("error getting cache json decoder for %s %v: %v", r.name, key, err) + return r.resolveAndCache(key, resolver) + } + var t T + err = dec.Decode(&t) + if err != nil { + log.Tracef("error decoding cached entry for %s %v: %v", r.name, key, err) + return r.resolveAndCache(key, resolver) + } + // no error, able to resolve from cache + return t, nil +} + +func (r *cacheResolver[T]) resolveAndCache(key string, resolver func() (T, error)) (T, error) { + t, err := resolver() + if err != nil { + return t, err + } + var data bytes.Buffer + enc := json.NewEncoder(&data) + enc.SetEscapeHTML(false) + err = enc.Encode(t) + if err != nil { + return t, err + } + err = r.cache.Write(key, &data) + return t, err +} diff --git a/internal/cache/resolver_test.go b/internal/cache/resolver_test.go new file mode 100644 index 000000000..4a74d0526 --- /dev/null +++ b/internal/cache/resolver_test.go @@ -0,0 +1,92 @@ +package cache + +import ( + "encoding/json" + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func Test_Resolver(t *testing.T) { + original := GetManager() + defer SetManager(original) + SetManager(NewInMemory(time.Hour)) + + type sub struct { + Name string + Value bool + } + + type thing struct { + Value string + Values []int + Subs []*sub + } + + versionHash := hashType[thing]() + cache := GetManager().GetCache("test", "v7/"+versionHash) + + resolver := GetResolver[thing]("test", "v7") + require.NotNil(t, resolver) + + require.IsType(t, &cacheResolver[thing]{}, resolver) + cr := resolver.(*cacheResolver[thing]) + + require.IsType(t, cache, cr.cache) + + resolveErrCount := 0 + resolveThingErr := func() (thing, error) { + resolveErrCount++ + return thing{}, fmt.Errorf("an error") + } + + _, err := resolver.Resolve("err", resolveThingErr) + require.ErrorContains(t, err, "an error") + require.Equal(t, 1, resolveErrCount) + + _, err = resolver.Resolve("err", resolveThingErr) + require.ErrorContains(t, err, "an error") + require.Equal(t, 2, resolveErrCount) + + aThing := thing{ + Value: "a value", + Values: []int{7, 8, 9}, + Subs: []*sub{ + { + Name: "sub1", + Value: true, + }, + { + Name: "sub2", + Value: false, + }, + }, + } + + resolveThingCount := 0 + resolveThing := func() (thing, error) { + resolveThingCount++ + return aThing, nil + } + + val, err := resolver.Resolve("thing", resolveThing) + require.NoError(t, err) + require.Equal(t, 1, resolveThingCount) + require.Equal(t, aThing, val) + + val, err = resolver.Resolve("thing", resolveThing) + require.NoError(t, err) + require.Equal(t, 1, resolveThingCount) + require.Equal(t, aThing, val) + + rdr, err := cache.Read("thing" + resolverKeySuffix) + require.NoError(t, err) + decoder := json.NewDecoder(rdr) + + var val2 thing + err = decoder.Decode(&val2) + require.NoError(t, err) + require.Equal(t, aThing, val2) +} diff --git a/syft/pkg/cataloger/golang/cataloger.go b/syft/pkg/cataloger/golang/cataloger.go index 6798b15a2..c7d483faa 100644 --- a/syft/pkg/cataloger/golang/cataloger.go +++ b/syft/pkg/cataloger/golang/cataloger.go @@ -20,12 +20,8 @@ const ( // NewGoModuleFileCataloger returns a new cataloger object that searches within go.mod files. func NewGoModuleFileCataloger(opts CatalogerConfig) pkg.Cataloger { - c := goModCataloger{ - licenses: newGoLicenses(modFileCatalogerName, opts), - } - return generic.NewCataloger(modFileCatalogerName). - WithParserByGlobs(c.parseGoModFile, "**/go.mod") + WithParserByGlobs(newGoModCataloger(opts).parseGoModFile, "**/go.mod") } // NewGoModuleBinaryCataloger returns a new cataloger object that searches within binaries built by the go compiler. diff --git a/syft/pkg/cataloger/golang/config.go b/syft/pkg/cataloger/golang/config.go index e55ed5d0b..aa7bc7708 100644 --- a/syft/pkg/cataloger/golang/config.go +++ b/syft/pkg/cataloger/golang/config.go @@ -41,6 +41,7 @@ type MainModuleVersionConfig struct { func DefaultCatalogerConfig() CatalogerConfig { g := CatalogerConfig{ MainModuleVersion: DefaultMainModuleVersionConfig(), + LocalModCacheDir: defaultGoModDir(), } // first process the proxy settings @@ -67,22 +68,23 @@ func DefaultCatalogerConfig() CatalogerConfig { } } - if g.LocalModCacheDir == "" { - goPath := os.Getenv("GOPATH") + return g +} - if goPath == "" { - homeDir, err := homedir.Dir() - if err != nil { - log.Debug("unable to determine user home dir: %v", err) - } else { - goPath = filepath.Join(homeDir, "go") - } - } - if goPath != "" { - g.LocalModCacheDir = filepath.Join(goPath, "pkg", "mod") +// defaultGoModDir returns $GOPATH/pkg/mod or $HOME/go/pkg/mod based on environment variables available +func defaultGoModDir() string { + goPath := os.Getenv("GOPATH") + + if goPath == "" { + homeDir, err := homedir.Dir() + if err != nil { + log.Warnf("unable to determine GOPATH or user home dir: %w", err) + return "" } + goPath = filepath.Join(homeDir, "go") } - return g + + return filepath.Join(goPath, "pkg", "mod") } func DefaultMainModuleVersionConfig() MainModuleVersionConfig { diff --git a/syft/pkg/cataloger/golang/config_test.go b/syft/pkg/cataloger/golang/config_test.go index 5719b312f..2720dc1b3 100644 --- a/syft/pkg/cataloger/golang/config_test.go +++ b/syft/pkg/cataloger/golang/config_test.go @@ -1,6 +1,7 @@ package golang import ( + "path/filepath" "testing" "github.com/mitchellh/go-homedir" @@ -47,7 +48,7 @@ func Test_Config(t *testing.T) { opts: opts{}, expected: CatalogerConfig{ SearchLocalModCacheLicenses: false, - LocalModCacheDir: "/go/pkg/mod", + LocalModCacheDir: filepath.Join("/go", "pkg", "mod"), SearchRemoteLicenses: false, Proxies: []string{"https://my.proxy"}, NoProxy: []string{"my.private", "no.proxy"}, diff --git a/syft/pkg/cataloger/golang/licenses.go b/syft/pkg/cataloger/golang/licenses.go index 5d9ba7734..911d386cc 100644 --- a/syft/pkg/cataloger/golang/licenses.go +++ b/syft/pkg/cataloger/golang/licenses.go @@ -21,25 +21,41 @@ import ( "github.com/scylladb/go-set/strset" "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/cache" "github.com/anchore/syft/internal/licenses" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/file" - "github.com/anchore/syft/syft/internal/fileresolver" + "github.com/anchore/syft/syft/license" "github.com/anchore/syft/syft/pkg" ) -type goLicenses struct { +type goLicense struct { + Value string `json:"val,omitempty"` + SPDXExpression string `json:"spdx,omitempty"` + Type license.Type `json:"type,omitempty"` + URLs []string `json:"urls,omitempty"` + Locations []string `json:"locations,omitempty"` +} + +type goLicenseResolver struct { catalogerName string opts CatalogerConfig - localModCacheResolver file.WritableResolver + localModCacheDir fs.FS + licenseCache cache.Resolver[[]goLicense] lowerLicenseFileNames *strset.Set } -func newGoLicenses(catalogerName string, opts CatalogerConfig) goLicenses { - return goLicenses{ +func newGoLicenseResolver(catalogerName string, opts CatalogerConfig) goLicenseResolver { + var localModCacheDir fs.FS + if opts.SearchLocalModCacheLicenses { + localModCacheDir = os.DirFS(opts.LocalModCacheDir) + } + + return goLicenseResolver{ catalogerName: catalogerName, opts: opts, - localModCacheResolver: modCacheResolver(opts.LocalModCacheDir), + localModCacheDir: localModCacheDir, + licenseCache: cache.GetResolverCachingErrors[[]goLicense]("golang", "v1"), lowerLicenseFileNames: strset.New(lowercaseLicenseFiles()...), } } @@ -63,98 +79,95 @@ func remotesForModule(proxies []string, noProxy []string, module string) []strin return proxies } -func modCacheResolver(modCacheDir string) file.WritableResolver { - var r file.WritableResolver - - if modCacheDir == "" { - log.Trace("unable to determine mod cache directory, skipping mod cache resolver") - r = fileresolver.Empty{} - } else { - stat, err := os.Stat(modCacheDir) - - if os.IsNotExist(err) || stat == nil || !stat.IsDir() { - log.Tracef("unable to open mod cache directory: %s, skipping mod cache resolver", modCacheDir) - r = fileresolver.Empty{} - } else { - r = fileresolver.NewFromUnindexedDirectory(modCacheDir) - } - } - - return r -} - -func (c *goLicenses) getLicenses(resolver file.Resolver, moduleName, moduleVersion string) (licenses []pkg.License, err error) { - licenses, err = c.findLicenses(resolver, +func (c *goLicenseResolver) getLicenses(resolver file.Resolver, moduleName, moduleVersion string) ([]pkg.License, error) { + // search the scan target first, ignoring local and remote sources + goLicenses, err := c.findLicensesInSource(resolver, fmt.Sprintf(`**/go/pkg/mod/%s@%s/*`, processCaps(moduleName), moduleVersion), ) - if err != nil || len(licenses) > 0 { - return requireCollection(licenses), err + if err != nil || len(goLicenses) > 0 { + return toPkgLicenses(goLicenses), err } - // look in the local host mod cache... - licenses, err = c.getLicensesFromLocal(moduleName, moduleVersion) - if err != nil || len(licenses) > 0 { - return requireCollection(licenses), err + // look in the local host mod directory... + if c.opts.SearchLocalModCacheLicenses { + goLicenses, err = c.getLicensesFromLocal(moduleName, moduleVersion) + if err != nil || len(goLicenses) > 0 { + return toPkgLicenses(goLicenses), err + } } - // we did not find it yet and remote searching was enabled - licenses, err = c.getLicensesFromRemote(moduleName, moduleVersion) - return requireCollection(licenses), err -} - -func (c *goLicenses) getLicensesFromLocal(moduleName, moduleVersion string) ([]pkg.License, error) { - if !c.opts.SearchLocalModCacheLicenses { - return nil, nil + // download from remote sources + if c.opts.SearchRemoteLicenses { + goLicenses, err = c.getLicensesFromRemote(moduleName, moduleVersion) } - // if we're running against a directory on the filesystem, it may not include the - // user's homedir / GOPATH, so we defer to using the localModCacheResolver - return c.findLicenses(c.localModCacheResolver, moduleSearchGlob(moduleName, moduleVersion)) + return toPkgLicenses(goLicenses), err } -func (c *goLicenses) getLicensesFromRemote(moduleName, moduleVersion string) ([]pkg.License, error) { - if !c.opts.SearchRemoteLicenses { +func (c *goLicenseResolver) getLicensesFromLocal(moduleName, moduleVersion string) ([]goLicense, error) { + if c.localModCacheDir == nil { return nil, nil } - proxies := remotesForModule(c.opts.Proxies, c.opts.NoProxy, moduleName) + subdir := moduleDir(moduleName, moduleVersion) - fsys, err := getModule(proxies, moduleName, moduleVersion) + // get the local subdirectory containing the specific go module + dir, err := fs.Sub(c.localModCacheDir, subdir) if err != nil { return nil, err } - dir := moduleDir(moduleName, moduleVersion) + // if we're running against a directory on the filesystem, it may not include the + // user's homedir / GOPATH, so we defer to using the localModCacheResolver + // we use $GOPATH/pkg/mod to avoid leaking information about the user's system + return c.findLicensesInFS("file://$GOPATH/pkg/mod/"+subdir+"/", dir) +} + +func (c *goLicenseResolver) getLicensesFromRemote(moduleName, moduleVersion string) ([]goLicense, error) { + return c.licenseCache.Resolve(fmt.Sprintf("%s/%s", moduleName, moduleVersion), func() ([]goLicense, error) { + proxies := remotesForModule(c.opts.Proxies, c.opts.NoProxy, moduleName) - // populate the mod cache with the results - err = fs.WalkDir(fsys, ".", func(filePath string, d fs.DirEntry, err error) error { + urlPrefix, fsys, err := getModule(proxies, moduleName, moduleVersion) if err != nil { - log.Debug(err) + return nil, err + } + + return c.findLicensesInFS(urlPrefix, fsys) + }) +} + +func (c *goLicenseResolver) findLicensesInFS(urlPrefix string, fsys fs.FS) ([]goLicense, error) { + var out []goLicense + err := fs.WalkDir(fsys, ".", func(filePath string, d fs.DirEntry, _ error) error { + if !c.lowerLicenseFileNames.Has(strings.ToLower(d.Name())) { return nil } - if d.IsDir() { + rdr, err := fsys.Open(filePath) + if err != nil { + log.Debugf("error opening license file %s: %v", filePath, err) return nil } - f, err := fsys.Open(filePath) + defer internal.CloseAndLogError(rdr, filePath) + parsed, err := licenses.Parse(rdr, file.NewLocation(filePath)) if err != nil { - return err + log.Debugf("error parsing license file %s: %v", filePath, err) + return nil + } + // since these licenses are found in an external fs.FS, not in the scanned source, + // get rid of the locations but keep information about the where the license was found + // by prepending the urlPrefix to the internal path for an accurate representation + for _, l := range toGoLicenses(parsed) { + l.URLs = []string{urlPrefix + filePath} + l.Locations = nil + out = append(out, l) } - return c.localModCacheResolver.Write(file.NewLocation(path.Join(dir, filePath)), f) + return nil }) - - if err != nil { - log.Tracef("remote proxy walk failed for: %s", moduleName) - } - - return c.findLicenses(c.localModCacheResolver, moduleSearchGlob(moduleName, moduleVersion)) + return out, err } -func (c *goLicenses) findLicenses(resolver file.Resolver, globMatch string) (out []pkg.License, err error) { - out = make([]pkg.License, 0) - if resolver == nil { - return - } - +func (c *goLicenseResolver) findLicensesInSource(resolver file.Resolver, globMatch string) ([]goLicense, error) { + var out []goLicense locations, err := resolver.FilesByGlob(globMatch) if err != nil { return nil, err @@ -168,11 +181,19 @@ func (c *goLicenses) findLicenses(resolver file.Resolver, globMatch string) (out out = append(out, parsed...) } - return + // if we have a directory but simply don't have any found license files, indicate this so we + // don't re-download modules continually + if len(locations) > 0 && len(out) == 0 { + return nil, noLicensesFound{ + glob: globMatch, + } + } + + return out, nil } -func (c *goLicenses) parseLicenseFromLocation(l file.Location, resolver file.Resolver) ([]pkg.License, error) { - var out []pkg.License +func (c *goLicenseResolver) parseLicenseFromLocation(l file.Location, resolver file.Resolver) ([]goLicense, error) { + var out []goLicense fileName := path.Base(l.RealPath) if c.lowerLicenseFileNames.Has(strings.ToLower(fileName)) { contents, err := resolver.FileContentsByLocation(l) @@ -185,7 +206,7 @@ func (c *goLicenses) parseLicenseFromLocation(l file.Location, resolver file.Res return nil, err } - out = append(out, parsed...) + out = append(out, toGoLicenses(parsed)...) } return out, nil } @@ -194,13 +215,9 @@ func moduleDir(moduleName, moduleVersion string) string { return fmt.Sprintf("%s@%s", processCaps(moduleName), moduleVersion) } -func moduleSearchGlob(moduleName, moduleVersion string) string { - return fmt.Sprintf("%s/*", moduleDir(moduleName, moduleVersion)) -} - -func requireCollection(licenses []pkg.License) []pkg.License { +func requireCollection[T any](licenses []T) []T { if licenses == nil { - return make([]pkg.License, 0) + return make([]T, 0) } return licenses } @@ -213,18 +230,19 @@ func processCaps(s string) string { }) } -func getModule(proxies []string, moduleName, moduleVersion string) (fsys fs.FS, err error) { +func getModule(proxies []string, moduleName, moduleVersion string) (urlPrefix string, fsys fs.FS, err error) { for _, proxy := range proxies { u, _ := url.Parse(proxy) if proxy == "direct" { - fsys, err = getModuleRepository(moduleName, moduleVersion) + urlPrefix, fsys, err = getModuleRepository(moduleName, moduleVersion) continue } switch u.Scheme { case "https", "http": - fsys, err = getModuleProxy(proxy, moduleName, moduleVersion) + urlPrefix, fsys, err = getModuleProxy(proxy, moduleName, moduleVersion) case "file": p := filepath.Join(u.Path, moduleName, "@v", moduleVersion) + urlPrefix = path.Join("file://", p) + "/" fsys = os.DirFS(p) } if fsys != nil { @@ -234,13 +252,13 @@ func getModule(proxies []string, moduleName, moduleVersion string) (fsys fs.FS, return } -func getModuleProxy(proxy string, moduleName string, moduleVersion string) (out fs.FS, _ error) { +func getModuleProxy(proxy string, moduleName string, moduleVersion string) (moduleURL string, out fs.FS, _ error) { u := fmt.Sprintf("%s/%s/@v/%s.zip", proxy, moduleName, moduleVersion) // get the module zip resp, err := http.Get(u) //nolint:gosec if err != nil { - return nil, err + return "", nil, err } defer func() { _ = resp.Body.Close() }() @@ -250,25 +268,25 @@ func getModuleProxy(proxy string, moduleName string, moduleVersion string) (out // try lowercasing it; some packages have mixed casing that really messes up the proxy resp, err = http.Get(u) //nolint:gosec if err != nil { - return nil, err + return "", nil, err } defer func() { _ = resp.Body.Close() }() if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("failed to get module zip: %s", resp.Status) + return "", nil, fmt.Errorf("failed to get module zip: %s", resp.Status) } } // read the zip b, err := io.ReadAll(resp.Body) if err != nil { - return nil, err + return "", nil, err } out, err = zip.NewReader(bytes.NewReader(b), resp.ContentLength) versionPath := findVersionPath(out, ".") out = getSubFS(out, versionPath) - return out, err + return u + "#" + versionPath + "/", out, err } func findVersionPath(f fs.FS, dir string) string { @@ -288,26 +306,111 @@ func findVersionPath(f fs.FS, dir string) string { return "" } -func getModuleRepository(moduleName string, moduleVersion string) (fs.FS, error) { +func getModuleRepository(moduleName string, moduleVersion string) (string, fs.FS, error) { repoName := moduleName parts := strings.Split(moduleName, "/") if len(parts) > 2 { repoName = fmt.Sprintf("%s/%s/%s", parts[0], parts[1], parts[2]) } + // see if there's a hash and use that if so, otherwise use a tag + splitVersion := strings.Split(moduleVersion, "-") + var cloneRefName plumbing.ReferenceName + refPath := "" + if len(splitVersion) < 3 { + tagName := splitVersion[0] + cloneRefName = plumbing.NewTagReferenceName(tagName) + refPath = "/tags/" + tagName + } + f := memfs.New() buf := &bytes.Buffer{} - _, err := git.Clone(memory.NewStorage(), f, &git.CloneOptions{ - URL: fmt.Sprintf("https://%s", repoName), - ReferenceName: plumbing.NewTagReferenceName(moduleVersion), // FIXME version might be a SHA + repoURL := fmt.Sprintf("https://%s", repoName) + r, err := git.Clone(memory.NewStorage(), f, &git.CloneOptions{ + URL: repoURL, + ReferenceName: cloneRefName, SingleBranch: true, Depth: 1, Progress: buf, }) - if err != nil { - return nil, fmt.Errorf("%w -- %s", err, buf.String()) + return "", nil, fmt.Errorf("%w -- %s", err, buf.String()) + } + + if len(splitVersion) > 2 { + sha := splitVersion[len(splitVersion)-1] + hash, err := r.ResolveRevision(plumbing.Revision(sha)) + if err != nil || hash == nil { + log.Tracef("unable to resolve hash %s: %v", sha, err) + } else { + w, err := r.Worktree() + if err != nil { + log.Tracef("unable to get worktree, using default: %v", err) + } + err = w.Checkout(&git.CheckoutOptions{ + Hash: *hash, + }) + if err != nil { + log.Tracef("unable to checkout commit, using default: %v", err) + } else { + refPath = "/refs/" + hash.String() + } + } } - return billyFSAdapter{fs: f}, nil + return repoURL + refPath + "/", billyFSAdapter{fs: f}, err +} + +type noLicensesFound struct { + glob string +} + +func (l noLicensesFound) Error() string { + return fmt.Sprintf("unable to find license information matching: %s", l.glob) +} + +var _ error = (*noLicensesFound)(nil) + +func toPkgLicenses(goLicenses []goLicense) []pkg.License { + var out []pkg.License + for _, l := range goLicenses { + out = append(out, pkg.License{ + Value: l.Value, + SPDXExpression: l.SPDXExpression, + Type: l.Type, + URLs: l.URLs, + Locations: toPkgLocations(l.Locations), + }) + } + return requireCollection(out) +} + +func toPkgLocations(goLocations []string) file.LocationSet { + out := file.NewLocationSet() + for _, l := range goLocations { + out.Add(file.NewLocation(l)) + } + return out +} + +func toGoLicenses(pkgLicenses []pkg.License) []goLicense { + var out []goLicense + for _, l := range pkgLicenses { + out = append(out, goLicense{ + Value: l.Value, + SPDXExpression: l.SPDXExpression, + Type: l.Type, + URLs: l.URLs, + Locations: toGoLocations(l.Locations), + }) + } + return out +} + +func toGoLocations(locations file.LocationSet) []string { + var out []string + for _, l := range locations.ToSlice() { + out = append(out, l.RealPath) + } + return out } diff --git a/syft/pkg/cataloger/golang/licenses_test.go b/syft/pkg/cataloger/golang/licenses_test.go index a4d1a4a9b..d34d59e5a 100644 --- a/syft/pkg/cataloger/golang/licenses_test.go +++ b/syft/pkg/cataloger/golang/licenses_test.go @@ -8,6 +8,7 @@ import ( "net/http/httptest" "os" "path" + "path/filepath" "strings" "testing" @@ -36,7 +37,8 @@ func Test_LocalLicenseSearch(t *testing.T) { Value: "Apache-2.0", SPDXExpression: "Apache-2.0", Type: license.Concluded, - Locations: file.NewLocationSet(loc1), + URLs: []string{"file://$GOPATH/pkg/mod/" + loc1.RealPath}, + Locations: file.NewLocationSet(), }, }, { @@ -46,7 +48,8 @@ func Test_LocalLicenseSearch(t *testing.T) { Value: "MIT", SPDXExpression: "MIT", Type: license.Concluded, - Locations: file.NewLocationSet(loc2), + URLs: []string{"file://$GOPATH/pkg/mod/" + loc2.RealPath}, + Locations: file.NewLocationSet(), }, }, { @@ -56,7 +59,8 @@ func Test_LocalLicenseSearch(t *testing.T) { Value: "Apache-2.0", SPDXExpression: "Apache-2.0", Type: license.Concluded, - Locations: file.NewLocationSet(loc3), + URLs: []string{"file://$GOPATH/pkg/mod/" + loc3.RealPath}, + Locations: file.NewLocationSet(), }, }, } @@ -66,11 +70,11 @@ func Test_LocalLicenseSearch(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - l := newGoLicenses( + l := newGoLicenseResolver( "", CatalogerConfig{ SearchLocalModCacheLicenses: true, - LocalModCacheDir: path.Join(wd, "test-fixtures", "licenses", "pkg", "mod"), + LocalModCacheDir: filepath.Join(wd, "test-fixtures", "licenses", "pkg", "mod"), }, ) licenses, err := l.getLicenses(fileresolver.Empty{}, test.name, test.version) @@ -97,7 +101,7 @@ func Test_RemoteProxyLicenseSearch(t *testing.T) { wd, err := os.Getwd() require.NoError(t, err) - testDir := path.Join(wd, "test-fixtures", "licenses", "pkg", "mod", processCaps(modPath)+"@"+modVersion) + testDir := filepath.Join(wd, "test-fixtures", "licenses", "pkg", "mod", processCaps(modPath)+"@"+modVersion) archive := zip.NewWriter(buf) @@ -106,9 +110,9 @@ func Test_RemoteProxyLicenseSearch(t *testing.T) { for _, f := range entries { // the zip files downloaded contain a path to the repo that somewhat matches where it ends up on disk, // so prefix entries with something similar - writer, err := archive.Create(path.Join("github.com/something/some@version", f.Name())) + writer, err := archive.Create(path.Join(moduleDir(modPath, modVersion), f.Name())) require.NoError(t, err) - contents, err := os.ReadFile(path.Join(testDir, f.Name())) + contents, err := os.ReadFile(filepath.Join(testDir, f.Name())) require.NoError(t, err) _, err = writer.Write(contents) require.NoError(t, err) @@ -136,7 +140,8 @@ func Test_RemoteProxyLicenseSearch(t *testing.T) { Value: "Apache-2.0", SPDXExpression: "Apache-2.0", Type: license.Concluded, - Locations: file.NewLocationSet(loc1), + URLs: []string{server.URL + "/github.com/someorg/somename/@v/v0.3.2.zip#" + loc1.RealPath}, + Locations: file.NewLocationSet(), }, }, { @@ -146,21 +151,20 @@ func Test_RemoteProxyLicenseSearch(t *testing.T) { Value: "MIT", SPDXExpression: "MIT", Type: license.Concluded, - Locations: file.NewLocationSet(loc2), + URLs: []string{server.URL + "/github.com/CapORG/CapProject/@v/v4.111.5.zip#" + loc2.RealPath}, + Locations: file.NewLocationSet(), }, }, } - modDir := path.Join(t.TempDir()) - for _, test := range tests { t.Run(test.name, func(t *testing.T) { - l := newGoLicenses( + + l := newGoLicenseResolver( "", CatalogerConfig{ SearchRemoteLicenses: true, Proxies: []string{server.URL}, - LocalModCacheDir: modDir, }, ) diff --git a/syft/pkg/cataloger/golang/package.go b/syft/pkg/cataloger/golang/package.go index 00c4f7909..8946b5f06 100644 --- a/syft/pkg/cataloger/golang/package.go +++ b/syft/pkg/cataloger/golang/package.go @@ -15,7 +15,7 @@ func (c *goBinaryCataloger) newGoBinaryPackage(resolver file.Resolver, dep *debu dep = dep.Replace } - licenses, err := c.licenses.getLicenses(resolver, dep.Path, dep.Version) + licenses, err := c.licenseResolver.getLicenses(resolver, dep.Path, dep.Version) if err != nil { log.Tracef("error getting licenses for golang package: %s %v", dep.Path, err) } diff --git a/syft/pkg/cataloger/golang/parse_go_binary.go b/syft/pkg/cataloger/golang/parse_go_binary.go index f3ea97180..c6906d156 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary.go +++ b/syft/pkg/cataloger/golang/parse_go_binary.go @@ -46,13 +46,13 @@ var ( const devel = "(devel)" type goBinaryCataloger struct { - licenses goLicenses + licenseResolver goLicenseResolver mainModuleVersion MainModuleVersionConfig } func newGoBinaryCataloger(opts CatalogerConfig) *goBinaryCataloger { return &goBinaryCataloger{ - licenses: newGoLicenses(binaryCatalogerName, opts), + licenseResolver: newGoLicenseResolver(binaryCatalogerName, opts), mainModuleVersion: opts.MainModuleVersion, } } diff --git a/syft/pkg/cataloger/golang/parse_go_mod.go b/syft/pkg/cataloger/golang/parse_go_mod.go index 1c06e8739..8faf4acb5 100644 --- a/syft/pkg/cataloger/golang/parse_go_mod.go +++ b/syft/pkg/cataloger/golang/parse_go_mod.go @@ -19,7 +19,13 @@ import ( ) type goModCataloger struct { - licenses goLicenses + licenseResolver goLicenseResolver +} + +func newGoModCataloger(opts CatalogerConfig) *goModCataloger { + return &goModCataloger{ + licenseResolver: newGoLicenseResolver(modFileCatalogerName, opts), + } } // parseGoModFile takes a go.mod and lists all packages discovered. @@ -44,7 +50,7 @@ func (c *goModCataloger) parseGoModFile(_ context.Context, resolver file.Resolve } for _, m := range f.Require { - licenses, err := c.licenses.getLicenses(resolver, m.Mod.Path, m.Mod.Version) + licenses, err := c.licenseResolver.getLicenses(resolver, m.Mod.Path, m.Mod.Version) if err != nil { log.Tracef("error getting licenses for package: %s %v", m.Mod.Path, err) } @@ -65,7 +71,7 @@ func (c *goModCataloger) parseGoModFile(_ context.Context, resolver file.Resolve // remove any old packages and replace with new ones... for _, m := range f.Replace { - licenses, err := c.licenses.getLicenses(resolver, m.New.Path, m.New.Version) + licenses, err := c.licenseResolver.getLicenses(resolver, m.New.Path, m.New.Version) if err != nil { log.Tracef("error getting licenses for package: %s %v", m.New.Path, err) } diff --git a/syft/pkg/cataloger/golang/parse_go_mod_test.go b/syft/pkg/cataloger/golang/parse_go_mod_test.go index 59a7164f1..19ae7f33b 100644 --- a/syft/pkg/cataloger/golang/parse_go_mod_test.go +++ b/syft/pkg/cataloger/golang/parse_go_mod_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/internal/fileresolver" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" ) @@ -91,10 +92,11 @@ func TestParseGoMod(t *testing.T) { for _, test := range tests { t.Run(test.fixture, func(t *testing.T) { - c := goModCataloger{} + c := newGoModCataloger(DefaultCatalogerConfig()) pkgtest.NewCatalogTester(). FromFile(t, test.fixture). Expects(test.expected, nil). + WithResolver(fileresolver.Empty{}). TestParser(t, c.parseGoModFile) }) } diff --git a/syft/source/directorysource/cache_excludes.go b/syft/source/directorysource/cache_excludes.go new file mode 100644 index 000000000..59c7c490e --- /dev/null +++ b/syft/source/directorysource/cache_excludes.go @@ -0,0 +1,33 @@ +package directorysource + +import ( + "os" + "strings" + + "github.com/anchore/syft/internal/cache" + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/syft/internal/fileresolver" +) + +// we do not want to cache things and then subsequently scan them, if, for example a user runs `syft /` twice +func excludeCachePathVisitors() []fileresolver.PathIndexVisitor { + var out []fileresolver.PathIndexVisitor + for _, dir := range cache.GetManager().RootDirs() { + out = append(out, excludeCacheDirPathVisitor{ + dir: dir, + }.excludeCacheDir) + } + return out +} + +type excludeCacheDirPathVisitor struct { + dir string +} + +func (d excludeCacheDirPathVisitor) excludeCacheDir(_, path string, _ os.FileInfo, _ error) error { + if strings.HasPrefix(path, d.dir) { + log.Tracef("skipping cache path: %s", path) + return fileresolver.ErrSkipPath + } + return nil +} diff --git a/syft/source/directorysource/directory_source.go b/syft/source/directorysource/directory_source.go index 2a4ab3705..0ab06980f 100644 --- a/syft/source/directorysource/directory_source.go +++ b/syft/source/directorysource/directory_source.go @@ -142,6 +142,9 @@ func (s *directorySource) FileResolver(_ source.Scope) (file.Resolver, error) { return nil, err } + // this should be the only file resolver that might have overlap with where files are cached + exclusionFunctions = append(exclusionFunctions, excludeCachePathVisitors()...) + res, err := fileresolver.NewFromDirectory(s.config.Path, s.config.Base, exclusionFunctions...) if err != nil { return nil, fmt.Errorf("unable to create directory resolver: %w", err) From 9beaec2e97c33b6e486e52b13ef0e2bbb7eebd6e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jun 2024 12:27:53 -0400 Subject: [PATCH 036/284] chore(deps): bump github/codeql-action from 3.25.8 to 3.25.9 (#2956) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.8 to 3.25.9. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/2e230e8fe0ad3a14a340ad0815ddb96d599d2aff...530d4feaa9c62aaab2d250371e2061eb7a172363) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 4a0803f3a..79e75cfb9 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff #v3.25.8 + uses: github/codeql-action/init@530d4feaa9c62aaab2d250371e2061eb7a172363 #v3.25.9 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff #v3.25.8 + uses: github/codeql-action/autobuild@530d4feaa9c62aaab2d250371e2061eb7a172363 #v3.25.9 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff #v3.25.8 + uses: github/codeql-action/analyze@530d4feaa9c62aaab2d250371e2061eb7a172363 #v3.25.9 From 273e31e8061c94742638b25ed74762dd5e74e783 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jun 2024 12:28:04 -0400 Subject: [PATCH 037/284] chore(deps): bump actions/checkout from 4.1.6 to 4.1.7 (#2955) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.6 to 4.1.7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/a5ac7e51b41094c92402da3b24376905380afc29...692973e3d937129bcbf40652eb9f2f61becf3332) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/benchmark-testing.yaml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/detect-schema-changes.yaml | 2 +- .github/workflows/release-version-file.yaml | 2 +- .github/workflows/release.yaml | 4 ++-- .github/workflows/update-bootstrap-tools.yml | 2 +- .github/workflows/update-cpe-dictionary-index.yml | 2 +- .github/workflows/update-stereoscope-release.yml | 2 +- .github/workflows/validations.yaml | 14 +++++++------- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/benchmark-testing.yaml b/.github/workflows/benchmark-testing.yaml index 41b142ae6..c23197c83 100644 --- a/.github/workflows/benchmark-testing.yaml +++ b/.github/workflows/benchmark-testing.yaml @@ -17,7 +17,7 @@ jobs: # the job by event. steps: - name: Checkout code - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Bootstrap environment uses: ./.github/actions/bootstrap diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 79e75cfb9..e555bdb22 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -36,7 +36,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - name: Install Go uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 #v5.0.1 diff --git a/.github/workflows/detect-schema-changes.yaml b/.github/workflows/detect-schema-changes.yaml index 300591fed..1241d687b 100644 --- a/.github/workflows/detect-schema-changes.yaml +++ b/.github/workflows/detect-schema-changes.yaml @@ -30,7 +30,7 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - run: python .github/scripts/labeler.py env: diff --git a/.github/workflows/release-version-file.yaml b/.github/workflows/release-version-file.yaml index 74e53bdec..cd41a0c8e 100644 --- a/.github/workflows/release-version-file.yaml +++ b/.github/workflows/release-version-file.yaml @@ -20,7 +20,7 @@ jobs: release: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - name: Update version file run: make ci-release-version-file diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 1b6f94d4e..1e2d26f4b 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -15,7 +15,7 @@ jobs: environment: release runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - name: Check if running on main if: github.ref != 'refs/heads/main' @@ -105,7 +105,7 @@ jobs: # required for goreleaser signs section with cosign id-token: write steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 with: fetch-depth: 0 diff --git a/.github/workflows/update-bootstrap-tools.yml b/.github/workflows/update-bootstrap-tools.yml index 992cb9d7c..a32b5f9ac 100644 --- a/.github/workflows/update-bootstrap-tools.yml +++ b/.github/workflows/update-bootstrap-tools.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'anchore/syft' # only run for main repo steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - name: Bootstrap environment uses: ./.github/actions/bootstrap diff --git a/.github/workflows/update-cpe-dictionary-index.yml b/.github/workflows/update-cpe-dictionary-index.yml index 0943df388..5e324ef68 100644 --- a/.github/workflows/update-cpe-dictionary-index.yml +++ b/.github/workflows/update-cpe-dictionary-index.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'anchore/syft' # only run for main repo steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - name: Bootstrap environment uses: ./.github/actions/bootstrap diff --git a/.github/workflows/update-stereoscope-release.yml b/.github/workflows/update-stereoscope-release.yml index fa901330c..feaec61cd 100644 --- a/.github/workflows/update-stereoscope-release.yml +++ b/.github/workflows/update-stereoscope-release.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'anchore/syft' # only run for main repo steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 #v5.0.1 with: diff --git a/.github/workflows/validations.yaml b/.github/workflows/validations.yaml index 2a29a4858..f54771d9b 100644 --- a/.github/workflows/validations.yaml +++ b/.github/workflows/validations.yaml @@ -17,7 +17,7 @@ jobs: name: "Static analysis" runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -31,7 +31,7 @@ jobs: name: "Unit tests" runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -87,7 +87,7 @@ jobs: name: "Integration tests" runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -109,7 +109,7 @@ jobs: name: "Build snapshot artifacts" runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -139,7 +139,7 @@ jobs: needs: [Build-Snapshot-Artifacts] runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -190,7 +190,7 @@ jobs: - name: Install Cosign uses: sigstore/cosign-installer@v3.5.0 - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -234,7 +234,7 @@ jobs: needs: [Build-Snapshot-Artifacts] runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - name: Bootstrap environment uses: ./.github/actions/bootstrap From 749ccc59c1595d0ff8d276d8462c7e1d63f790aa Mon Sep 17 00:00:00 2001 From: Weston Steimel Date: Fri, 14 Jun 2024 14:35:14 +0100 Subject: [PATCH 038/284] fix(golang): improve version extraction from ldflags for pingcap TiDB (#2962) * fix(golang): improve version extraction from ldflags for pingcap TiDB Signed-off-by: Weston Steimel * loosen ld flag parsing requirements Signed-off-by: Alex Goodman --------- Signed-off-by: Weston Steimel Signed-off-by: Alex Goodman Co-authored-by: Alex Goodman --- syft/pkg/cataloger/golang/parse_go_binary.go | 4 ++-- syft/pkg/cataloger/golang/parse_go_binary_test.go | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/syft/pkg/cataloger/golang/parse_go_binary.go b/syft/pkg/cataloger/golang/parse_go_binary.go index c6906d156..88600355c 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary.go +++ b/syft/pkg/cataloger/golang/parse_go_binary.go @@ -38,8 +38,8 @@ var ( // inject the correct version into the main module of the build process knownBuildFlagPatterns = []*regexp.Regexp{ - regexp.MustCompile(`(?m)\.([gG]it)?([bB]uild)?[vV]er(sion)?=(\S+/)*(?Pv?\d+.\d+.\d+[-\w]*)`), - regexp.MustCompile(`(?m)\.([tT]ag)=(\S+/)*(?Pv?\d+.\d+.\d+[-\w]*)`), + regexp.MustCompile(`(?m)\.[a-zA-Z0-9]*([rR]elease)?([gG]it)?([bB]uild)?[vV]er(sion)?=(\S+/)*(?Pv?\d+.\d+.\d+[-\w]*)`), + regexp.MustCompile(`(?m)\.[a-zA-Z0-9]*([tT]ag)=(\S+/)*(?Pv?\d+.\d+.\d+[-\w]*)`), } ) diff --git a/syft/pkg/cataloger/golang/parse_go_binary_test.go b/syft/pkg/cataloger/golang/parse_go_binary_test.go index 29de14f35..0346324fe 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary_test.go +++ b/syft/pkg/cataloger/golang/parse_go_binary_test.go @@ -1080,6 +1080,18 @@ func Test_extractVersionFromLDFlags(t *testing.T) { wantMajorVersion: "4", wantFullVersion: "v4.5.7", }, + { + name: "TiDB 7.5.0 ldflags", + ldflags: `build -ldflags="-X \"github.com/pingcap/tidb/pkg/parser/mysql.TiDBReleaseVersion=v7.5.0\" -X \"github.com/pingcap/tidb/pkg/util/versioninfo.TiDBBuildTS=2023-11-24 08:51:04\" -X \"github.com/pingcap/tidb/pkg/util/versioninfo.TiDBGitHash=069631e2ecfedc000ffb92c67207bea81380f020\" -X \"github.com/pingcap/tidb/pkg/util/versioninfo.TiDBGitBranch=heads/refs/tags/v7.5.0\" -X \"github.com/pingcap/tidb/pkg/util/versioninfo.TiDBEdition=Community\" "`, + wantMajorVersion: "7", + wantFullVersion: "v7.5.0", + }, + { + name: "TiDB 6.1.7 ldflags", + ldflags: `build -ldflags="-X \"github.com/pingcap/tidb/parser/mysql.TiDBReleaseVersion=v6.1.7\" -X \"github.com/pingcap/tidb/util/versioninfo.TiDBBuildTS=2023-07-04 12:06:03\" -X \"github.com/pingcap/tidb/util/versioninfo.TiDBGitHash=613ecc5f731b2843e1d53a43915e2cd8da795936\" -X \"github.com/pingcap/tidb/util/versioninfo.TiDBGitBranch=heads/refs/tags/v6.1.7\" -X \"github.com/pingcap/tidb/util/versioninfo.TiDBEdition=Community\" "`, + wantMajorVersion: "6", + wantFullVersion: "v6.1.7", + }, ////////////////////////////////////////////////////////////////// // negative cases { From d5cd5f6091c267464804d089c58040b92525bb3b Mon Sep 17 00:00:00 2001 From: Weston Steimel Date: Fri, 14 Jun 2024 14:39:43 +0100 Subject: [PATCH 039/284] feat: index known CPEs for wordpress plugins and themes (#2963) Signed-off-by: Weston Steimel --- .../dictionary/data/cpe-index.json | 11605 ++++++++++++++++ .../dictionary/index-generator/generate.go | 74 +- .../index-generator/generate_test.go | 117 + .../testdata/expected-cpe-index.json | 52 + .../testdata/official-cpe-dictionary_v2.3.xml | 8 + .../internal/cpegenerate/dictionary/types.go | 20 +- .../internal/cpegenerate/generate.go | 7 + 7 files changed, 11860 insertions(+), 23 deletions(-) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index 5a72a546a..1af72da78 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -6906,6 +6906,11611 @@ "zeroize_derive": [ "cpe:2.3:a:zeroize_derive_project:zeroize_derive:*:*:*:*:*:rust:*:*" ] + }, + "wordpress_plugins": { + "0mk-shortener": [ + "cpe:2.3:a:0mk_shortener_project:0mk_shortener:*:*:*:*:*:wordpress:*:*" + ], + "1003-mortgage-application": [ + "cpe:2.3:a:lenderd:1003_mortgage_application:*:*:*:*:*:wordpress:*:*" + ], + "10to8-online-booking": [ + "cpe:2.3:a:10to8:sign_in_scheduling_online_appointment_booking_system:*:*:*:*:*:wordpress:*:*" + ], + "12-step-meeting-list": [ + "cpe:2.3:a:code4recovery:12_step_meeting_list:*:*:*:*:*:wordpress:*:*" + ], + "123-chat-videochat": [ + "cpe:2.3:a:123.chat:123.chat:*:*:*:*:*:wordpress:*:*" + ], + "1app-business-forms": [ + "cpe:2.3:a:1app:1app_business_forms:*:*:*:*:*:wordpress:*:*" + ], + "2j-slideshow": [ + "cpe:2.3:a:2joomla:2j_slideshow:*:*:*:*:*:wordpress:*:*" + ], + "2kb-amazon-affiliates-store": [ + "cpe:2.3:a:2kblater:2kb_amazon_affiliates_store:*:*:*:*:*:wordpress:*:*" + ], + "360-product-rotation": [ + "cpe:2.3:a:yofla:360_product_rotation:*:*:*:*:*:wordpress:*:*" + ], + "3com-asesor-de-cookies": [ + "cpe:2.3:a:3commarketing:3com-asesor-de-cookies:*:*:*:*:*:wordpress:*:*" + ], + "3d-cover-carousel": [ + "cpe:2.3:a:3d_cover_carousel_project:3d_cover_carousel:*:*:*:*:*:wordpress:*:*" + ], + "3d-flipbook-dflip-lite": [ + "cpe:2.3:a:dearhive:dearflip:*:*:*:*:*:wordpress:*:*" + ], + "3dprint-lite": [ + "cpe:2.3:a:wp3dprinting:3dprint_lite:*:*:*:*:*:wordpress:*:*" + ], + "3xsocializer": [ + "cpe:2.3:a:3xsocializer_project:3xsocializer:*:*:*:*:*:wordpress:*:*" + ], + "404-solution": [ + "cpe:2.3:a:ajexperience:404_solution:*:*:*:*:*:wordpress:*:*" + ], + "404-to-301": [ + "cpe:2.3:a:duckdev:404_to_301:*:*:*:*:*:wordpress:*:*" + ], + "404-to-start": [ + "cpe:2.3:a:404_to_start_project:404_to_start:*:*:*:*:*:wordpress:*:*" + ], + "404like": [ + "cpe:2.3:a:404like_project:404like:*:*:*:*:*:wordpress:*:*" + ], + "4ecps-webforms": [ + "cpe:2.3:a:jumpdemand:4ecps_web_forms:*:*:*:*:*:wordpress:*:*" + ], + "5-anker-connect": [ + "cpe:2.3:a:5-anker:5_anker_connect:*:*:*:*:*:wordpress:*:*" + ], + "59sec-lite-contact-form-7-push-notifications-on-ios-and-android": [ + "cpe:2.3:a:59sec:the_leads_management_system\\:_59sec_lite:*:*:*:*:*:wordpress:*:*" + ], + "8-degree-notification-bar": [ + "cpe:2.3:a:8degreethemes:notification_bar:*:*:*:*:*:wordpress:*:*" + ], + "99fy-core": [ + "cpe:2.3:a:hasthemes:free_woocommerce_theme_99fy_extension:*:*:*:*:*:wordpress:*:*" + ], + "a-forms": [ + "cpe:2.3:a:a-forms_project:a-forms:*:*:*:*:*:wordpress:*:*" + ], + "a2-optimized-wp": [ + "cpe:2.3:a:a2hosting:a2_optimized:*:*:*:*:*:wordpress:*:*" + ], + "aajoda-testimonials": [ + "cpe:2.3:a:aajoda:aajoda_testimonials:*:*:*:*:*:wordpress:*:*" + ], + "ab-google-map-travel": [ + "cpe:2.3:a:ab_google_map_travel_project:ab_google_map_travel:*:*:*:*:*:wordpress:*:*" + ], + "ab-press-optimizer-lite": [ + "cpe:2.3:a:abpressoptimizer:ab_press_optimizer:*:*:*:*:*:wordpress:*:*" + ], + "about-me": [ + "cpe:2.3:a:about-me_project:about-me:*:*:*:*:*:wordpress:*:*" + ], + "about-me-3000": [ + "cpe:2.3:a:wpmaniax:about_me_3000_widget:*:*:*:*:*:wordpress:*:*" + ], + "about-rentals": [ + "cpe:2.3:a:about-rentals_project:about-rentals:*:*:*:*:*:wordpress:*:*" + ], + "absolute-privacy": [ + "cpe:2.3:a:johnkolbert:absolute_privacy:*:*:*:*:*:wordpress:*:*" + ], + "absolute-reviews": [ + "cpe:2.3:a:ashstonestudios:absolute_reviews:*:*:*:*:*:wordpress:*:*" + ], + "abwp-simple-counter": [ + "cpe:2.3:a:ab-wp:simple_counter:*:*:*:*:*:wordpress:*:*" + ], + "academy": [ + "cpe:2.3:a:creativeitem:academy_lms:*:*:*:*:*:*:*:*" + ], + "accelerated-mobile-pages": [ + "cpe:2.3:a:ampforwp:accelerated_mobile_pages:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:magazine3:amp_for_wp:*:*:*:*:*:wordpress:*:*" + ], + "access-demo-importer": [ + "cpe:2.3:a:accesspressthemes:access_demo_importer:*:*:*:*:*:wordpress:*:*" + ], + "accessibility": [ + "cpe:2.3:a:accessibility_project:accessibility:*:*:*:*:*:wordpress:*:*" + ], + "accessibility-help-button": [ + "cpe:2.3:a:stpetedesign:call_now_accessibility_button:*:*:*:*:*:wordpress:*:*" + ], + "accesspress-anonymous-post": [ + "cpe:2.3:a:accesspressthemes:accesspress_anonymous_post:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:accesspressthemes:frontend_post_wordpress_plugin:*:*:*:*:*:wordpress:*:*" + ], + "accesspress-custom-css": [ + "cpe:2.3:a:accesspressthemes:accesspress_custom_css:*:*:*:*:*:wordpress:*:*" + ], + "accesspress-custom-post-type": [ + "cpe:2.3:a:accesspressthemes:accesspress_custom_post_type:*:*:*:*:*:wordpress:*:*" + ], + "accesspress-facebook-auto-post": [ + "cpe:2.3:a:accesspressthemes:social_auto_poster:*:*:*:*:*:wordpress:*:*" + ], + "accesspress-instagram-feed": [ + "cpe:2.3:a:accesspressthemes:accesspress_ifeeds:*:*:*:*:*:wordpress:*:*" + ], + "accesspress-pinterest": [ + "cpe:2.3:a:accesspressthemes:pi_button:*:*:*:*:*:wordpress:*:*" + ], + "accesspress-social-counter": [ + "cpe:2.3:a:accesspressthemes:accesspress_social_counter:*:*:*:*:*:wordpress:*:*" + ], + "accesspress-social-icons": [ + "cpe:2.3:a:accesspressthemes:accesspress_social_icons:*:*:*:*:*:wordpress:*:*" + ], + "accesspress-social-login-lite": [ + "cpe:2.3:a:accesspressthemes:accesspress_social_login_lite:*:*:*:*:*:wordpress:*:*" + ], + "accesspress-social-share": [ + "cpe:2.3:a:accesspressthemes:accesspress_social_share:*:*:*:*:*:wordpress:*:*" + ], + "accesspress-twitter-feed": [ + "cpe:2.3:a:accesspressthemes:wp_tfeed:*:*:*:*:*:wordpress:*:*" + ], + "accommodation-system": [ + "cpe:2.3:a:accommodation-system_project:accommodation-system:*:*:*:*:*:wordpress:*:*" + ], + "accordions": [ + "cpe:2.3:a:pickplugins:accordion:*:*:*:*:*:wordpress:*:*" + ], + "accordions-or-faqs": [ + "cpe:2.3:a:oxilab:accordions:*:*:*:*:*:wordpress:*:*" + ], + "accordions-wp": [ + "cpe:2.3:a:themepoints:accordion:*:*:*:*:*:wordpress:*:*" + ], + "accredible-certificates": [ + "cpe:2.3:a:accredible:accredible_certificates_\\\u0026_open_badges:*:*:*:*:*:wordpress:*:*" + ], + "accurate-form-data-real-time-form-validation": [ + "cpe:2.3:a:wp_accurate_form_data_project:wp_accurate_form_data:*:*:*:*:*:wordpress:*:*" + ], + "aceide": [ + "cpe:2.3:a:aceide_project:aceide:*:*:*:*:*:wordpress:*:*" + ], + "acf-better-search": [ + "cpe:2.3:a:acf-better-search_project:acf-better-search:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:acf\\:_better_search_project:acf\\:_better_search:*:*:*:*:*:wordpress:*:*" + ], + "acf-extended": [ + "cpe:2.3:a:acf-extended:advanced_custom_fields\\:extended:*:*:*:*:-:wordpress:*:*", + "cpe:2.3:a:acf-extended:advanced_custom_fields\\:extended:*:*:*:*:basic:wordpress:*:*", + "cpe:2.3:a:acf-extended:advanced_custom_fields\\:extended:*:*:*:*:free:wordpress:*:*", + "cpe:2.3:a:acf-extended:advanced_custom_fields\\:extended:*:*:*:*:pro:wordpress:*:*", + "cpe:2.3:a:acfextended:advanced_custom_fields_extended:*:*:*:*:*:wordpress:*:*" + ], + "acf-frontend-display": [ + "cpe:2.3:a:advancedcustomfields:acf_fronted_display:*:*:*:*:*:wordpress:*:*" + ], + "acf-frontend-form-element": [ + "cpe:2.3:a:dynamiapps:frontend_admin:*:*:*:*:*:wordpress:*:*" + ], + "acf-image-crop-add-on": [ + "cpe:2.3:a:andersthorborg:advanced_custom_fields\\:image_crop_add-on:*:*:*:*:*:wordpress:*:*" + ], + "acf-to-rest-api": [ + "cpe:2.3:a:acf_to_rest_api_project:acf_to_rest_api:*:*:*:*:*:wordpress:*:*" + ], + "aco-product-labels-for-woocommerce": [ + "cpe:2.3:a:acowebs:product_labels_for_woocommerce_\\(sale_badges\\):*:*:*:*:*:wordpress:*:*" + ], + "activecampaign-for-woocommerce": [ + "cpe:2.3:a:activecampaign:activecampaign_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "activecampaign-subscription-forms": [ + "cpe:2.3:a:activecampaign:activecampaign:*:*:*:*:*:wordpress:*:*" + ], + "activedemand": [ + "cpe:2.3:a:jumpdemand:activedemand:*:*:*:*:*:wordpress:*:*" + ], + "activity-reactions-for-buddypress": [ + "cpe:2.3:a:areteit:activity_reactions_for_buddypress:*:*:*:*:*:wordpress:*:*" + ], + "activitypub": [ + "cpe:2.3:a:automattic:activitypub:*:*:*:*:*:wordpress:*:*" + ], + "acurax-social-media-widget": [ + "cpe:2.3:a:acurax:social_media_widget:*:*:*:*:*:wordpress:*:*" + ], + "acymailing": [ + "cpe:2.3:a:acymailing:acymailing:*:*:*:*:*:wordpress:*:*" + ], + "ad-blocking-detector": [ + "cpe:2.3:a:getadmiral:ad_blocking_detector:*:*:*:*:*:wordpress:*:*" + ], + "ad-buttons": [ + "cpe:2.3:a:ad_buttons_project:ad_buttons:*:*:*:*:*:wordpress:*:*" + ], + "ad-injection": [ + "cpe:2.3:a:ad_injection_project:ad_injection:*:*:*:*:*:wordpress:*:*" + ], + "ad-inserter": [ + "cpe:2.3:a:ad_inserter_project:ad_inserter:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:ad_inserter_project:ad_inserter:*:*:*:*:free:wordpress:*:*" + ], + "ad-invalid-click-protector": [ + "cpe:2.3:a:acnam:ad_invalid_click_protector:*:*:*:*:*:wordpress:*:*" + ], + "ad-manager-for-wp": [ + "cpe:2.3:a:ad-manager_project:ad-manager:*:*:*:*:*:wordpress:*:*" + ], + "adamrob-parallax-scroll": [ + "cpe:2.3:a:parallax_scroll_project:parallax_scroll:*:*:*:*:*:wordpress:*:*" + ], + "adaptive-images": [ + "cpe:2.3:a:nevma:adaptive_images:*:*:*:*:*:wordpress:*:*" + ], + "add-actions-and-filters": [ + "cpe:2.3:a:add_shortcodes_actions_and_filters_project:add_shortcodes_actions_and_filters:*:*:*:*:*:wordpress:*:*" + ], + "add-any-extension-to-pages": [ + "cpe:2.3:a:infolific:add_any_extension_to_pages:*:*:*:*:*:wordpress:*:*" + ], + "add-comments": [ + "cpe:2.3:a:add_comments_project:add_comments:*:*:*:*:*:wordpress:*:*" + ], + "add-custom-body-class": [ + "cpe:2.3:a:anilankola:add_custom_body_class:*:*:*:*:*:wordpress:*:*" + ], + "add-customer-for-woocommerce": [ + "cpe:2.3:a:dans-art:add_customer_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "add-facebook": [ + "cpe:2.3:a:web-settler:social_feed:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:web-settler:social_feed_\\|_all_social_media_in_one_place:*:*:*:*:*:wordpress:*:*" + ], + "add-from-server": [ + "cpe:2.3:a:add_from_server_project:add_from_server:*:*:*:*:*:wordpress:*:*" + ], + "add-link-to-facebook": [ + "cpe:2.3:a:add_link_to_facebook_project:add_link_to_facebook:*:*:*:*:*:wordpress:*:*" + ], + "add-local-avatar": [ + "cpe:2.3:a:petersterling:add_local_avatar:*:*:*:*:*:wordpress:*:*" + ], + "add-multiple-marker": [ + "cpe:2.3:a:krishaweb:add_multiple_marker:*:*:*:*:*:wordpress:*:*" + ], + "add-posts-to-pages": [ + "cpe:2.3:a:webmechanix:add_posts_to_pages:*:*:*:*:*:wordpress:*:*" + ], + "add-search-to-menu": [ + "cpe:2.3:a:ivorysearch:ivory_search:*:*:*:*:*:wordpress:*:*" + ], + "add-social-share-buttons": [ + "cpe:2.3:a:dotstore:add_social_share_messenger_buttons_whatsapp_and_viber:*:*:*:*:*:wordpress:*:*" + ], + "add-subtitle": [ + "cpe:2.3:a:viitorcloud:add_subtitle:*:*:*:*:*:wordpress:*:*" + ], + "add-to-any": [ + "cpe:2.3:a:addtoany:addtoany_share_buttons:*:*:*:*:*:wordpress:*:*" + ], + "add-to-calendar-button": [ + "cpe:2.3:a:add-to-calendar-button-pro:add_to_calendar_button:*:*:*:*:*:wordpress:*:*" + ], + "add-to-cart-direct-checkout-for-woocommerce": [ + "cpe:2.3:a:piwebsolution:add-to-cart-direct-checkout-for-woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "addon-elements-for-elementor-page-builder": [ + "cpe:2.3:a:webtechstreet:elementor_addon_elements:*:*:*:*:*:wordpress:*:*" + ], + "addons-for-elementor": [ + "cpe:2.3:a:livemesh:elementor_addons:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:livemeshelementor:addons_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "addthis": [ + "cpe:2.3:a:addthis:addthis:*:*:*:*:*:wordpress:*:*" + ], + "adfoxly": [ + "cpe:2.3:a:wpfoxly:adfoxly:*:*:*:*:*:wordpress:*:*" + ], + "adl-team": [ + "cpe:2.3:a:wpwax:team:*:*:*:*:*:wordpress:*:*" + ], + "admin-bar-dashboard-control": [ + "cpe:2.3:a:properfraction:admin_bar_\\\u0026_dashboard_access_control:*:*:*:*:*:wordpress:*:*" + ], + "admin-block-country": [ + "cpe:2.3:a:admin_block_country_project:admin_block_country:*:*:*:*:*:wordpress:*:*" + ], + "admin-css-mu": [ + "cpe:2.3:a:millionclues:admin_css_mu:*:*:*:*:*:wordpress:*:*" + ], + "admin-custom-login": [ + "cpe:2.3:a:weblizar:admin_custom_login:*:*:*:*:*:wordpress:*:*" + ], + "admin-management-xtended": [ + "cpe:2.3:a:admin_management_xtended_project:admin_management_xtended:*:*:*:*:*:wordpress:*:*" + ], + "admin-menu": [ + "cpe:2.3:a:admin_menu_project:admin_menu:*:*:*:*:*:wordpress:*:*" + ], + "admin-renamer-extended": [ + "cpe:2.3:a:mijnpress:admin-renamer-extended:*:*:*:*:*:wordpress:*:*" + ], + "admin-side-data-storage-for-contact-form-7": [ + "cpe:2.3:a:zestard:admin_side_data_storage_for_contact_form_7:*:*:*:*:*:wordpress:*:*" + ], + "adminer": [ + "cpe:2.3:a:adminer_login_project:adminer_login:*:*:*:*:*:wordpress:*:*" + ], + "adminify": [ + "cpe:2.3:a:wpadminify:wp_adminify:*:*:*:*:*:wordpress:*:*" + ], + "adminpad": [ + "cpe:2.3:a:adminpad_project:adminpad:*:*:*:*:*:wordpress:*:*" + ], + "adrotate": [ + "cpe:2.3:a:adrotate_banner_manager_project:adrotate_banner_manager:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:adrotate_project:adrotate:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:ajdg:adrotate:*:*:*:*:*:wordpress:*:*" + ], + "ads-by-datafeedrcom": [ + "cpe:2.3:a:datafeedr:ads_by_datafeedr.com:*:*:*:*:*:wordpress:*:*" + ], + "ads-invalid-click-protection": [ + "cpe:2.3:a:impactpixel:ads_invalid_click_protection:*:*:*:*:*:wordpress:*:*" + ], + "adsense-click-fraud-monitoring": [ + "cpe:2.3:a:clickfraud-monitoring:adsense-click-fraud-monitoring:*:*:*:*:*:wordpress:*:*" + ], + "adsense-plugin": [ + "cpe:2.3:a:bestwebsoft:google_adsense:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:google_adsense_project:google_adsense:*:*:*:*:*:wordpress:*:*" + ], + "advance-search": [ + "cpe:2.3:a:advance_search_project:advance_search:*:*:*:*:*:wordpress:*:*" + ], + "advanced-access-manager": [ + "cpe:2.3:a:vasyltech:advanced_access_manager:*:*:*:*:*:wordpress:*:*" + ], + "advanced-admin-search": [ + "cpe:2.3:a:kuroit:advanced_admin_search:*:*:*:*:*:wordpress:*:*" + ], + "advanced-ads": [ + "cpe:2.3:a:wpadvancedads:advanced_ads_-_ad_manager_\\\u0026_adsense:*:*:*:*:*:wordpress:*:*" + ], + "advanced-ajax-page-loader": [ + "cpe:2.3:a:advanced_ajax_page_loader_project:advanced_ajax_page_loader:*:*:*:*:*:wordpress:*:*" + ], + "advanced-booking-calendar": [ + "cpe:2.3:a:elbtide:advanced_booking_calendar:*:*:*:*:*:wordpress:*:*" + ], + "advanced-category-template": [ + "cpe:2.3:a:praveengoswami:advanced_category_template:*:*:*:*:*:wordpress:*:*" + ], + "advanced-cf7-db": [ + "cpe:2.3:a:vsourz:advanced_cf7_db:*:*:*:*:*:wordpress:*:*" + ], + "advanced-cron-manager": [ + "cpe:2.3:a:bracketspace:advanced_cron_manager:*:*:*:*:-:wordpress:*:*" + ], + "advanced-custom-fields": [ + "cpe:2.3:a:advancedcustomfields:advanced_custom_fields:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:advancedcustomfields:advanced_custom_fields:*:*:*:*:-:wordpress:*:*", + "cpe:2.3:a:advancedcustomfields:advanced_custom_fields:*:*:*:*:pro:wordpress:*:*" + ], + "advanced-database-cleaner": [ + "cpe:2.3:a:sigmaplugin:advanced_database_cleaner:*:*:*:*:*:wordpress:*:*" + ], + "advanced-dynamic-pricing-for-woocommerce": [ + "cpe:2.3:a:algolplus:advanced_dynamic_pricing_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "advanced-form-integration": [ + "cpe:2.3:a:advancedformintegration:advanced_form_integration:*:*:*:*:*:wordpress:*:*" + ], + "advanced-free-flat-shipping-woocommerce": [ + "cpe:2.3:a:piwebsolution:advanced-free-flat-shipping-woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "advanced-iframe": [ + "cpe:2.3:a:tinywebgallery:advanced_iframe:*:*:*:*:*:wordpress:*:*" + ], + "advanced-import": [ + "cpe:2.3:a:addonspress:advanced_import:*:*:*:*:*:wordpress:*:*" + ], + "advanced-local-pickup-for-woocommerce": [ + "cpe:2.3:a:zorem:advanced_local_pickup_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "advanced-menu-widget": [ + "cpe:2.3:a:bocinec:advanced_menu_widget:*:*:*:*:*:wordpress:*:*" + ], + "advanced-nocaptcha-recaptcha": [ + "cpe:2.3:a:wpwhitesecurity:captcha_4wp:*:*:*:*:*:wordpress:*:*" + ], + "advanced-page-visit-counter": [ + "cpe:2.3:a:advanced_page_visit_counter_project:advanced_page_visit_counter:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:pagevisitcounter:advanced_page_visit_counter:*:*:*:*:*:wordpress:*:*" + ], + "advanced-popups": [ + "cpe:2.3:a:ashstonestudios:advanced_popups:*:*:*:*:*:wordpress:*:*" + ], + "advanced-quiz": [ + "cpe:2.3:a:markusbegerow:wp-adv-quiz:*:*:*:*:*:wordpress:*:*" + ], + "advanced-recent-posts": [ + "cpe:2.3:a:advanced_recent_posts_project:advanced_recent_posts:*:*:*:*:*:wordpress:*:*" + ], + "advanced-uploader": [ + "cpe:2.3:a:advanced_uploader_project:advanced_uploader:*:*:*:*:*:wordpress:*:*" + ], + "advanced-woo-search": [ + "cpe:2.3:a:advanced-woo-search:advanced_woo_search:*:*:*:*:*:wordpress:*:*" + ], + "advanced-wp-columns": [ + "cpe:2.3:a:advanced_wp_columns_project:advanced_wp_columns:*:*:*:*:*:wordpress:*:*" + ], + "advanced-wp-reset": [ + "cpe:2.3:a:sigmaplugin:advanced_wordpress_reset:*:*:*:*:*:wordpress:*:*" + ], + "affiliate-ads-builder-for-clickbank-products": [ + "cpe:2.3:a:clickbank:affiliate_ads_for_clickbank_products:*:*:*:*:*:wordpress:*:*" + ], + "affiliate-toolkit-starter": [ + "cpe:2.3:a:servit:affiliate-toolkit:*:*:*:*:*:wordpress:*:*" + ], + "affiliatebooster-blocks": [ + "cpe:2.3:a:affiliatebooster:affiliate_booster:*:*:*:*:*:wordpress:*:*" + ], + "affiliates-manager": [ + "cpe:2.3:a:wpaffiliatemanager:affiliates_manager:*:*:*:*:*:wordpress:*:*" + ], + "afterpay-gateway-for-woocommerce": [ + "cpe:2.3:a:afterpay:afterpay_gateway_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "ag-custom-admin": [ + "cpe:2.3:a:cusmin:absolutely_glamorous_custom_admin:*:*:*:*:*:wordpress:*:*" + ], + "agenteasy-properties": [ + "cpe:2.3:a:agenteasy_properties_project:agenteasy_properties:*:*:*:*:*:wordpress:*:*" + ], + "agile-store-locator": [ + "cpe:2.3:a:agilelogix:store_locator:*:*:*:*:*:wordpress:*:*" + ], + "agp-font-awesome-collection": [ + "cpe:2.3:a:profosbox:agp_font_awesome_collection:*:*:*:*:*:wordpress:*:*" + ], + "ai-assistant-by-10web": [ + "cpe:2.3:a:10web:ai_assistant:*:*:*:*:*:wordpress:*:*" + ], + "ai-contact-us": [ + "cpe:2.3:a:ai_contact_us_form_project:ai_contact_us_form:*:*:*:*:*:wordpress:*:*" + ], + "ai-engine": [ + "cpe:2.3:a:meowapps:ai_engine:*:*:*:*:*:wordpress:*:*" + ], + "ai-post-generator": [ + "cpe:2.3:a:autowriter:ai_post_generator_\\|_autowriter:*:*:*:*:*:wordpress:*:*" + ], + "aio-time-clock-lite": [ + "cpe:2.3:a:codebangers:all_in_one_time_clock_lite:*:*:*:*:*:wordpress:*:*" + ], + "ajax-archive-calendar": [ + "cpe:2.3:a:osmansorkar:ajax_archive_calendar:*:*:*:*:*:wordpress:*:*" + ], + "ajax-bootmodal-login": [ + "cpe:2.3:a:ajax_bootmodal_login_project:ajax_bootmodal_login:*:*:*:*:*:wordpress:*:*" + ], + "ajax-load-more": [ + "cpe:2.3:a:connekthq:ajax_load_more:*:*:*:*:*:wordpress:*:*" + ], + "ajax-pagination": [ + "cpe:2.3:a:ajax-pagination_project:ajax-pagination:*:*:*:*:*:wordpress:*:*" + ], + "ajax-random-post": [ + "cpe:2.3:a:ajax-random-post_project:ajax-random-post:*:*:*:*:*:wordpress:*:*" + ], + "ajax-search-for-woocommerce": [ + "cpe:2.3:a:fibosearch:fibosearch:*:*:*:*:*:wordpress:*:*" + ], + "ajax-search-lite": [ + "cpe:2.3:a:ajax_search_project:ajax_search:*:*:*:*:lite:wordpress:*:*" + ], + "ajax-upload-for-gravity-forms": [ + "cpe:2.3:a:ajax_upload_for_gravity_forms_project:ajax_upload_for_gravity_forms:*:*:*:*:*:wordpress:*:*" + ], + "akismet": [ + "cpe:2.3:a:automattic:akismet:*:*:*:*:*:wordpress:*:*" + ], + "akismet-privacy-policies": [ + "cpe:2.3:a:inpsyde:akismet_privacy_policies:*:*:*:*:*:wordpress:*:*" + ], + "albo-pretorio-on-line": [ + "cpe:2.3:a:albo_pretorio_on_line_project:albo_pretorio_on_line:*:*:*:*:*:wordpress:*:*" + ], + "alfred-click-collect": [ + "cpe:2.3:a:alfred24_click_\\\u0026_collect_project:alfred24_click_\\\u0026_collect:*:*:*:*:*:wordpress:*:*" + ], + "alipay": [ + "cpe:2.3:a:alipay_project:alipay:*:*:*:*:*:wordpress:*:*" + ], + "all-404-redirect-to-homepage": [ + "cpe:2.3:a:clogica:all_404_redirect_to_homepage:*:*:*:*:*:wordpress:*:*" + ], + "all-bootstrap-blocks": [ + "cpe:2.3:a:areoi:all_bootstrap_blocks:*:*:*:*:*:wordpress:*:*" + ], + "all-in-one-favicon": [ + "cpe:2.3:a:techotronic:all_in_one_favicon:*:*:*:*:*:wordpress:*:*" + ], + "all-in-one-redirection": [ + "cpe:2.3:a:vsourz:all_in_one_redirection:*:*:*:*:*:wordpress:*:*" + ], + "all-in-one-schemaorg-rich-snippets": [ + "cpe:2.3:a:brainstormforce:schema:*:*:*:*:*:wordpress:*:*" + ], + "all-in-one-seo-pack": [ + "cpe:2.3:a:aioseo:all_in_one_seo:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:semperplugins:all_in_one_seo_pack:*:*:*:*:*:wordpress:*:*" + ], + "all-in-one-video-gallery": [ + "cpe:2.3:a:plugins360:all-in-one_video_gallery:*:*:*:*:*:wordpress:*:*" + ], + "all-in-one-wp-migration": [ + "cpe:2.3:a:servmask:all-in-one_wp_migration:*:*:*:*:*:wordpress:*:*" + ], + "all-in-one-wp-security-and-firewall": [ + "cpe:2.3:a:tips_and_tricks_hq:all_in_one_wordpress_security_and_firewall:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:tipsandtricks-hq:all_in_one_wp_security_\\\u0026_firewall:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:tipsandtricks-hq:wp_security_\\\u0026_firewall:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:updraftplus:all-in-one_security:*:*:*:*:*:wordpress:*:*" + ], + "allow-php-in-posts-and-pages": [ + "cpe:2.3:a:hitreach:allow_php_in_posts_and_pages:*:*:*:*:*:wordpress:*:*" + ], + "alma-gateway-for-woocommerce": [ + "cpe:2.3:a:almapay:alma:*:*:*:*:*:wordpress:*:*" + ], + "alo-easymail": [ + "cpe:2.3:a:alo-easymail_project:alo-easymail:*:*:*:*:*:wordpress:*:*" + ], + "alojapro-widget": [ + "cpe:2.3:a:alojapro:alojapro_widget:*:*:*:*:*:wordpress:*:*" + ], + "alpine-photo-tile-for-instagram": [ + "cpe:2.3:a:thealpinepress:alpine-photo-tile-for-instagram:*:*:*:*:*:wordpress:*:*" + ], + "alpine-photo-tile-for-pinterest": [ + "cpe:2.3:a:thealpinepress:alpine_phototile_for_pinterest:*:*:*:*:*:wordpress:*:*" + ], + "alter": [ + "cpe:2.3:a:altersoftware:alter:*:*:*:*:*:wordpress:*:*" + ], + "altos-connect": [ + "cpe:2.3:a:altosresearch:altos-connect:*:*:*:*:*:wordpress:*:*" + ], + "am-hili-affiliate-manager-for-publishers": [ + "cpe:2.3:a:am-hili_project:am-hili:*:*:*:*:*:wordpress:*:*" + ], + "amazon-auto-links": [ + "cpe:2.3:a:michaeluno:auto_amazon_links:*:*:*:*:*:wordpress:*:*" + ], + "amazon-link": [ + "cpe:2.3:a:amazon_link_project:amazon_link:*:*:*:*:*:wordpress:*:*" + ], + "amazonify": [ + "cpe:2.3:a:gara:amazonify:*:*:*:*:*:wordpress:*:*" + ], + "amazonjs": [ + "cpe:2.3:a:amazonjs_project:amazonjs:*:*:*:*:*:wordpress:*:*" + ], + "amazonsimpleadmin": [ + "cpe:2.3:a:ifeelweb:affiliate_super_assistent:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:ifeelweb:post_status_notifier_lite:*:*:*:*:*:wordpress:*:*" + ], + "amcharts-charts-and-maps": [ + "cpe:2.3:a:amcharts:amcharts\\:_charts_and_maps:*:*:*:*:*:wordpress:*:*" + ], + "ameliabooking": [ + "cpe:2.3:a:tms-outsource:amelia:*:*:*:*:*:wordpress:*:*" + ], + "amministrazione-aperta": [ + "cpe:2.3:a:amministrazione_aperta_project:amministrazione_aperta:*:*:*:*:*:wordpress:*:*" + ], + "amministrazione-trasparente": [ + "cpe:2.3:a:amministrazione_trasparente_project:amministrazione_trasparente:*:*:*:*:*:wordpress:*:*" + ], + "amp-plus": [ + "cpe:2.3:a:amp-cloud:amp_plus:*:*:*:*:*:wordpress:*:*" + ], + "amp-toolbox": [ + "cpe:2.3:a:deano:amp_toolbox:*:*:*:*:*:wordpress:*:*" + ], + "ampedsense-adsense-split-tester": [ + "cpe:2.3:a:ezoic:ampedsense:*:*:*:*:*:wordpress:*:*" + ], + "amr-ical-events-list": [ + "cpe:2.3:a:amr-ical-events-list_project:amr-ical-events-list:*:*:*:*:*:wordpress:*:*" + ], + "amr-shortcode-any-widget": [ + "cpe:2.3:a:amr-shortcode-any-widget_project:amr-shortcode-any-widget:*:*:*:*:*:wordpress:*:*" + ], + "amr-users": [ + "cpe:2.3:a:anmari:amr_users:*:*:*:*:*:wordpress:*:*" + ], + "amty-thumb-recent-post": [ + "cpe:2.3:a:amtythumb_project:amtythumb:*:*:*:*:*:wordpress:*:*" + ], + "amtythumb": [ + "cpe:2.3:a:amtythumb_project:amtythumb:*:*:*:*:*:wordpress:*:*" + ], + "an-gradebook": [ + "cpe:2.3:a:an_gradebook_project:an_gradebook:*:*:*:*:*:wordpress:*:*" + ], + "analogwp-templates": [ + "cpe:2.3:a:analogwp:style_kits:*:*:*:*:*:wordpress:*:*" + ], + "analytics-cat": [ + "cpe:2.3:a:fatcatapps:analytics_cat:*:*:*:*:*:wordpress:*:*" + ], + "analytics-tracker": [ + "cpe:2.3:a:analytics_tracker_project:analytics_tracker:*:*:*:*:*:wordpress:*:*" + ], + "animate-it": [ + "cpe:2.3:a:eleopard:animate_it\\!:*:*:*:*:*:wordpress:*:*" + ], + "animated-counters": [ + "cpe:2.3:a:eralion:animated_counters:*:*:*:*:*:wordpress:*:*" + ], + "another-wordpress-classifieds-plugin": [ + "cpe:2.3:a:awpcp:another_wordpress_classifieds_plugin:*:*:*:*:*:wordpress:*:*" + ], + "anspress-question-answer": [ + "cpe:2.3:a:rahularyan:anspress:*:*:*:*:*:wordpress:*:*" + ], + "anthologize": [ + "cpe:2.3:a:anthologize_project:anthologize:*:*:*:*:*:wordpress:*:*" + ], + "antihacker": [ + "cpe:2.3:a:antihacker_project:antihacker:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:billminozzi:anti_hacker:*:*:*:*:*:wordpress:*:*" + ], + "anual-archive": [ + "cpe:2.3:a:twinpictures:annual_archive:*:*:*:*:*:wordpress:*:*" + ], + "any-hostname": [ + "cpe:2.3:a:any_hostname_project:any_hostname:*:*:*:*:*:wordpress:*:*" + ], + "anycomment": [ + "cpe:2.3:a:bologer:anycomment:*:*:*:*:*:wordpress:*:*" + ], + "anywhere-flash-embed": [ + "cpe:2.3:a:sureshkumarmukhiya:anywhere_flash_embed:*:*:*:*:*:wordpress:*:*" + ], + "ap-contact-form": [ + "cpe:2.3:a:accesspressthemes:ap_contact_form:*:*:*:*:*:wordpress:*:*" + ], + "ap-custom-testimonial": [ + "cpe:2.3:a:accesspressthemes:ap_custom_testimonial:*:*:*:*:*:wordpress:*:*" + ], + "ap-mega-menu": [ + "cpe:2.3:a:accesspressthemes:ap_mega_menu:*:*:*:*:*:wordpress:*:*" + ], + "ap-pricing-tables-lite": [ + "cpe:2.3:a:accesspressthemes:ap_pricing_tables_lite:*:*:*:*:*:wordpress:*:*" + ], + "apex-notification-bar-lite": [ + "cpe:2.3:a:accesspressthemes:apex_notification_bar_lite:*:*:*:*:*:wordpress:*:*" + ], + "api-bearer-auth": [ + "cpe:2.3:a:api_bearer_auth_project:api_bearer_auth:*:*:*:*:*:wordpress:*:*" + ], + "api-key-for-google-maps": [ + "cpe:2.3:a:ayecode:api_key_for_google_maps:*:*:*:*:*:wordpress:*:*" + ], + "api2cart-bridge-connector": [ + "cpe:2.3:a:api2cart:api2cart_bridge_connector:*:*:*:*:*:wordpress:*:*" + ], + "apollo13-framework-extensions": [ + "cpe:2.3:a:apollo13themes:apollo13_framework_extensions:*:*:*:*:*:wordpress:*:*" + ], + "apply-online": [ + "cpe:2.3:a:spiderteams:applyonline_-_application_form_builder_and_manager:*:*:*:*:*:wordpress:*:*" + ], + "appmysite": [ + "cpe:2.3:a:appmysite:appmysite:*:*:*:*:*:wordpress:*:*" + ], + "appointment-booking-calendar": [ + "cpe:2.3:a:codepeople:appointment_booking_calendar:*:*:*:*:*:wordpress:*:*" + ], + "appointment-calendar": [ + "cpe:2.3:a:apointzilla:appointment_calendar:*:*:*:*:*:wordpress:*:*" + ], + "appointment-hour-booking": [ + "cpe:2.3:a:dwbooster:appointment_hour_booking:*:*:*:*:*:wordpress:*:*" + ], + "apppresser": [ + "cpe:2.3:a:apppresser:apppresser:*:*:*:*:*:wordpress:*:*" + ], + "apptivo-business-site": [ + "cpe:2.3:a:apptivo:apptivo_business_site_crm:*:*:*:*:*:wordpress:*:*" + ], + "aprils-super-functions-pack": [ + "cpe:2.3:a:april\\'s_super_functions_pack_project:april\\'s_super_functions_pack:*:*:*:*:*:wordpress:*:*" + ], + "archivist-custom-archive-templates": [ + "cpe:2.3:a:archivist_-_custom_archive_templates_project:archivist_-_custom_archive_templates:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:ericteubert:archivist_-_custom_archive_templates:*:*:*:*:*:wordpress:*:*" + ], + "arconix-shortcodes": [ + "cpe:2.3:a:tychesoftwares:arconix_shortcodes:*:*:*:*:*:wordpress:*:*" + ], + "arforms-form-builder": [ + "cpe:2.3:a:reputeinfosystems:arforms_form_builder:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:reputeinfosystems:contact_form\\,_survey_\\\u0026_popup_form_plugin_for_wordpress_-_arforms_form_builder:*:*:*:*:*:wordpress:*:*" + ], + "ari-adminer": [ + "cpe:2.3:a:ari-soft:ari_adminer:*:*:*:*:*:wordpress:*:*" + ], + "ari-fancy-lightbox": [ + "cpe:2.3:a:ari-soft:ari_fancy_lightbox:*:*:*:*:*:wordpress:*:*" + ], + "ari-stream-quiz": [ + "cpe:2.3:a:ari-soft:ari_stream_quiz:*:*:*:*:*:wordpress:*:*" + ], + "armember-membership": [ + "cpe:2.3:a:armemberplugin:armember:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:reputeinfosystems:armember:*:*:*:*:*:wordpress:*:*" + ], + "arprice-responsive-pricing-table": [ + "cpe:2.3:a:reputeinfosystems:arprice_lite:*:*:*:*:*:wordpress:*:*" + ], + "article-directory": [ + "cpe:2.3:a:article_directory_project:article_directory:*:*:*:*:*:wordpress:*:*" + ], + "article-directory-redux": [ + "cpe:2.3:a:icontrolwp:article_directory_redux:*:*:*:*:*:wordpress:*:*" + ], + "article2pdf": [ + "cpe:2.3:a:article2pdf_project:article2pdf:*:*:*:*:*:wordpress:*:*" + ], + "artplacer-widget": [ + "cpe:2.3:a:artplacer:artplacer_widget:*:*:*:*:*:wordpress:*:*" + ], + "aruba-hispeed-cache": [ + "cpe:2.3:a:aruba:aruba_hispeed_cache:*:*:*:*:*:wordpress:*:*" + ], + "aryo-activity-log": [ + "cpe:2.3:a:pojo:activity_log:*:*:*:*:*:wordpress:*:*" + ], + "asf-allow-svg-files": [ + "cpe:2.3:a:allow_svg_files_project:allow_svg_files:*:*:*:*:*:wordpress:*:*" + ], + "asgaros-forum": [ + "cpe:2.3:a:asgaros:asgaros_forum:*:*:*:*:*:wordpress:*:*" + ], + "asmember": [ + "cpe:2.3:a:asmember_project:asmember:*:*:*:*:*:wordpress:*:*" + ], + "assistant": [ + "cpe:2.3:a:fastlinemedia:assistant:*:*:*:*:*:wordpress:*:*" + ], + "astra-import-export": [ + "cpe:2.3:a:brainstormforce:import_\\/_export_customizer_settings:*:*:*:*:*:wordpress:*:*" + ], + "astra-sites": [ + "cpe:2.3:a:brainstormforce:starter_templates:*:*:*:*:*:wordpress:*:*" + ], + "atarim-visual-collaboration": [ + "cpe:2.3:a:atarim:atarim:*:*:*:*:*:wordpress:*:*" + ], + "attendance-manager": [ + "cpe:2.3:a:sukimalab:attendance_manager:*:*:*:*:*:wordpress:*:*" + ], + "attire-blocks": [ + "cpe:2.3:a:wpattire:attire_blocks:*:*:*:*:*:wordpress:*:*" + ], + "audio-merchant": [ + "cpe:2.3:a:myaudiomerchant:audio_merchant:*:*:*:*:*:wordpress:*:*" + ], + "audio-player-with-playlist-ultimate": [ + "cpe:2.3:a:essentialplugin:audio_player_with_playlist_ultimate:*:*:*:*:*:wordpress:*:*" + ], + "authldap": [ + "cpe:2.3:a:heiglandreas:authldap:*:*:*:*:*:wordpress:*:*" + ], + "author-avatars": [ + "cpe:2.3:a:bearne:author_avatars_list\\/block:*:*:*:*:*:wordpress:*:*" + ], + "author-bio-box": [ + "cpe:2.3:a:author_bio_box_project:author_bio_box:*:*:*:*:*:wordpress:*:*" + ], + "authorizenet-payment-gateway-for-woocommerce": [ + "cpe:2.3:a:ithemes:authorize.net:*:*:*:*:*:wordpress:*:*" + ], + "authors-list": [ + "cpe:2.3:a:wpkube:authors_list:*:*:*:*:*:wordpress:*:*" + ], + "auto-delete-posts": [ + "cpe:2.3:a:auto_delete_posts_project:auto_delete_posts:*:*:*:*:*:wordpress:*:*" + ], + "auto-excerpt-everywhere": [ + "cpe:2.3:a:josie:auto_excerpt_everywhere:*:*:*:*:*:wordpress:*:*" + ], + "auto-hyperlink-urls": [ + "cpe:2.3:a:auto-hyperlink_urls_project:auto-hyperlink_urls:*:*:*:*:*:wordpress:*:*" + ], + "auto-limit-posts-reloaded": [ + "cpe:2.3:a:thefreewindows:auto_limit_posts_reloaded:*:*:*:*:*:wordpress:*:*" + ], + "auto-listings": [ + "cpe:2.3:a:wpautolistings:auto_listings:*:*:*:*:*:wordpress:*:*" + ], + "auto-login-new-user-after-registration": [ + "cpe:2.3:a:auto_login_new_user_after_registration_project:auto_login_new_user_after_registration:*:*:*:*:*:wordpress:*:*" + ], + "auto-login-when-resister": [ + "cpe:2.3:a:enable\\/disable_auto_login_when_register_project:enable\\/disable_auto_login_when_register:*:*:*:*:*:wordpress:*:*" + ], + "auto-more-tag": [ + "cpe:2.3:a:auto_more_tag_project:auto_more_tag:*:*:*:*:*:wordpress:*:*" + ], + "auto-post-thumbnail": [ + "cpe:2.3:a:cm-wp:auto_featured_image:*:*:*:*:*:wordpress:*:*" + ], + "auto-rename-media-on-upload": [ + "cpe:2.3:a:auto_rename_media_on_upload_project:auto_rename_media_on_upload:*:*:*:*:*:wordpress:*:*" + ], + "auto-thickbox-plus": [ + "cpe:2.3:a:attosoft:auto_thickbox_plus:*:*:*:*:*:wordpress:*:*" + ], + "auto-upload-images": [ + "cpe:2.3:a:auto_upload_images_project:auto_upload_images:*:*:*:*:*:wordpress:*:*" + ], + "auto-youtube-importer": [ + "cpe:2.3:a:secondlinethemes:auto_youtube_importer:*:*:*:*:*:wordpress:*:*" + ], + "autolinks": [ + "cpe:2.3:a:autolinks_project:autolinks:*:*:*:*:*:wordpress:*:*" + ], + "automatic-youtube-video-posts": [ + "cpe:2.3:a:ternstyle:automatic_youtube_video_posts:*:*:*:*:*:wordpress:*:*" + ], + "automatorwp": [ + "cpe:2.3:a:automatorwp:automatorwp:*:*:*:*:*:wordpress:*:*" + ], + "autoptimize": [ + "cpe:2.3:a:autoptimize:autoptimize:*:*:*:*:*:wordpress:*:*" + ], + "autotitle-for-wordpress": [ + "cpe:2.3:a:unalignedcode:autotitle:*:*:*:*:*:wordpress:*:*" + ], + "auxin-elements": [ + "cpe:2.3:a:averta:shortcodes_and_extra_features_for_phlox_theme:*:*:*:*:*:wordpress:*:*" + ], + "auyautochat-for-wp": [ + "cpe:2.3:a:autochat:automatic_conversation:*:*:*:*:*:wordpress:*:*" + ], + "availability-calendar": [ + "cpe:2.3:a:offshorewebmaster:availability_calendar:*:*:*:*:*:wordpress:*:*" + ], + "avalex": [ + "cpe:2.3:a:avalex:avalex:*:*:*:*:*:wordpress:*:*" + ], + "avartan-slider-lite": [ + "cpe:2.3:a:solwininfotech:avartan-slider-lite:*:*:*:*:*:wordpress:*:*" + ], + "avcp": [ + "cpe:2.3:a:wpgov:anac_xml_bandi_di_gara:*:*:*:*:*:wordpress:*:*" + ], + "avenirsoft-directdownload": [ + "cpe:2.3:a:avenirsoft:directdownload:*:*:*:*:*:wordpress:*:*" + ], + "aviary-image-editor-add-on-for-gravity-forms": [ + "cpe:2.3:a:aviary_image_editor_add-on_for_gravity_forms_project:aviary_image_editor_add-on_for_gravity_forms:*:*:*:*:*:wordpress:*:*" + ], + "aweber-web-form-widget": [ + "cpe:2.3:a:aweber:aweber:*:*:*:*:*:wordpress:*:*" + ], + "awesome-filterable-portfolio": [ + "cpe:2.3:a:awesome_filterable_portfolio_project:awesome_filterable_portfolio:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:brinidesigner:awesome_filterable_portfolio:*:*:*:*:*:wordpress:*:*" + ], + "awesome-support": [ + "cpe:2.3:a:awesomesupport:awesome_support_wordpress_helpdesk_\\\u0026_support:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:getawesomesupport:awesome_support:*:*:*:*:*:wordpress:*:*" + ], + "awesome-weather": [ + "cpe:2.3:a:awesome_weather_widget_project:awesome_weather_widget:*:*:*:*:*:wordpress:*:*" + ], + "awin-data-feed": [ + "cpe:2.3:a:awin:awin_data_feed:*:*:*:*:*:wordpress:*:*" + ], + "ays-facebook-popup-likebox": [ + "cpe:2.3:a:ays-pro:popup_box:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:aysproextensions:popup_like:*:*:*:*:*:wordpress:*:*" + ], + "ays-popup-box": [ + "cpe:2.3:a:ays-pro:popup_box:*:*:*:*:*:wordpress:*:*" + ], + "b2bking-wholesale-for-woocommerce": [ + "cpe:2.3:a:webwizards:b2bking:*:*:*:*:*:wordpress:*:*" + ], + "ba-plus-before-after-image-slider-free": [ + "cpe:2.3:a:aluka:ba_plus:*:*:*:*:*:wordpress:*:*" + ], + "back-button-widget": [ + "cpe:2.3:a:wpfactory:back_button_widget:*:*:*:*:*:wordpress:*:*" + ], + "back-to-the-top-button": [ + "cpe:2.3:a:yydevelopment:back_to_the_top_button:*:*:*:*:*:wordpress:*:*" + ], + "backup": [ + "cpe:2.3:a:backup-guard:backup_guard:*:*:*:*:*:wordpress:*:*" + ], + "backup-backup": [ + "cpe:2.3:a:backupbliss:backup_migration:*:*:*:*:*:wordpress:*:*" + ], + "backup-wd": [ + "cpe:2.3:a:web-dorado:backup-wd:*:*:*:*:*:wordpress:*:*" + ], + "backuply": [ + "cpe:2.3:a:softaculous:backuply:*:*:*:*:*:wordpress:*:*" + ], + "backupwordpress": [ + "cpe:2.3:a:xibodevelopment:backupwordpress:*:*:*:*:*:wordpress:*:*" + ], + "backwpup": [ + "cpe:2.3:a:inpsyde:backwpup:*:*:*:*:*:wordpress:*:*" + ], + "badgeos": [ + "cpe:2.3:a:badgeos:badgeos:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:badgeos:badgos:*:*:*:*:*:wordpress:*:*" + ], + "baidu-submit-link": [ + "cpe:2.3:a:wbolt:all-in-one_search_automatic_push_management:*:*:*:*:*:wordpress:*:*" + ], + "baidu-tongji-generator": [ + "cpe:2.3:a:baidu-tongji-generator_project:baidu-tongji-generator:*:*:*:*:*:wordpress:*:*" + ], + "bamboo-columns": [ + "cpe:2.3:a:bamboo_mcr:bamboo_columns:*:*:*:*:*:wordpress:*:*" + ], + "bank-mellat": [ + "cpe:2.3:a:bank_mellat_project:bank_mellat:*:*:*:*:*:wordpress:*:*" + ], + "banner-cycler": [ + "cpe:2.3:a:banner_cycler_project:banner_cycler:*:*:*:*:*:wordpress:*:*" + ], + "banner-effect-header": [ + "cpe:2.3:a:banner_effect_header_project:banner_effect_header:*:*:*:*:*:wordpress:*:*" + ], + "banner-management-for-woocommerce": [ + "cpe:2.3:a:dotstore:woocommerce_category_banner_management:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:multidots:banner_management_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "barcode-scanner-lite-pos-to-manage-products-inventory-and-orders": [ + "cpe:2.3:a:ukrsolution:barcode_scanner_and_inventory_manager:*:*:*:*:*:wordpress:*:*" + ], + "basic-interactive-world-map": [ + "cpe:2.3:a:wpmapplugins:basic_interactive_world_map:*:*:*:*:*:wordpress:*:*" + ], + "baslider": [ + "cpe:2.3:a:nextcode:image_slider_by_nextcode:*:*:*:*:*:wordpress:*:*" + ], + "batch-cat": [ + "cpe:2.3:a:batch_cat_project:batch_cat:*:*:*:*:*:wordpress:*:*" + ], + "bbp-move-topics": [ + "cpe:2.3:a:bbpress_move_topics_project:bbpress_move_topics:*:*:*:*:*:wordpress:*:*" + ], + "bbp-style-pack": [ + "cpe:2.3:a:rewweb:bbp_style_pack:*:*:*:*:*:wordpress:*:*" + ], + "bbp-toolkit": [ + "cpe:2.3:a:bbp-toolkit_project:bbp-toolkit:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:casier:bbpress_toolkit:*:*:*:*:*:wordpress:*:*" + ], + "bbp-voting": [ + "cpe:2.3:a:wpforthewin:bbpress_voting:*:*:*:*:*:wordpress:*:*" + ], + "bbpress": [ + "cpe:2.3:a:bbpress:bbpress:*:*:*:*:*:wordpress:*:*" + ], + "bcorp-shortcodes": [ + "cpe:2.3:a:bcorp_shortcodes_project:bcorp_shortcodes:*:*:*:*:*:wordpress:*:*" + ], + "bdvs-password-reset": [ + "cpe:2.3:a:bedevious:password_reset_with_code_for_wordpress_rest_api:*:*:*:*:*:wordpress:*:*" + ], + "be-popia-compliant": [ + "cpe:2.3:a:web-x:be-popia-compliant:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:web-x:be_popia_compliant:*:*:*:*:*:wordpress:*:*" + ], + "beautiful-and-responsive-cookie-consent": [ + "cpe:2.3:a:beautiful-cookie-banner:beautiful_cookie_consent_banner:*:*:*:*:*:wordpress:*:*" + ], + "beaver-builder-lite-version": [ + "cpe:2.3:a:fastlinemedia:beaver_builder:*:*:*:*:lite:wordpress:*:*" + ], + "beds24-online-booking": [ + "cpe:2.3:a:beds24:online_booking:*:*:*:*:*:wordpress:*:*" + ], + "before-after-image-slider": [ + "cpe:2.3:a:swadeshswain:before_after_image_slider:*:*:*:*:*:wordpress:*:*" + ], + "bellows-accordion-menu": [ + "cpe:2.3:a:sevenspark:bellows_accordion_menu:*:*:*:*:*:wordpress:*:*" + ], + "bertha-ai-free": [ + "cpe:2.3:a:bertha:bertha_ai:*:*:*:*:*:wordpress:*:*" + ], + "best-restaurant-menu-by-pricelisto": [ + "cpe:2.3:a:pricelisto:best_restaurant_menu_by_pricelisto:*:*:*:*:*:wordpress:*:*" + ], + "bestbooks": [ + "cpe:2.3:a:presspage:bestbooks:*:*:*:*:*:wordpress:*:*" + ], + "better-font-awesome": [ + "cpe:2.3:a:better_font_awesome_project:better_font_awesome:*:*:*:*:*:wordpress:*:*" + ], + "better-robots-txt": [ + "cpe:2.3:a:pagup:better_robots.txt:*:*:*:*:*:wordpress:*:*" + ], + "better-search": [ + "cpe:2.3:a:webberzone:better_search:*:*:*:*:*:wordpress:*:*" + ], + "better-search-replace": [ + "cpe:2.3:a:deliciousbrains:better_search_replace:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpengine:better_search_replace:*:*:*:*:*:wordpress:*:*" + ], + "better-wp-security": [ + "cpe:2.3:a:ithemes:ithemes_security:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:ithemes:security:*:*:*:*:*:wordpress:*:*" + ], + "betterlinks": [ + "cpe:2.3:a:wpdeveloper:betterlinks:*:*:*:*:*:wordpress:*:*" + ], + "bft-autoresponder": [ + "cpe:2.3:a:kibokolabs:arigato_autoresponder_and_newsletter:*:*:*:*:*:wordpress:*:*" + ], + "bg-biblie-references": [ + "cpe:2.3:a:bg_bible_references_project:bg_bible_references:*:*:*:*:*:wordpress:*:*" + ], + "bigbluebutton": [ + "cpe:2.3:a:blindsidenetworks:bigbluebutton:*:*:*:*:*:wordpress:*:*" + ], + "bigcommerce": [ + "cpe:2.3:a:bigcommerce:bigcommerce:*:*:*:*:*:wordpress:*:*" + ], + "bigcontact": [ + "cpe:2.3:a:bigcontact_contact_page_project:bigcontact_contact_page:*:*:*:*:*:wordpress:*:*" + ], + "billingo": [ + "cpe:2.3:a:official_integration_for_billingo_project:official_integration_for_billingo:*:*:*:*:*:wordpress:*:*" + ], + "bing-site-verification-using-meta-tag": [ + "cpe:2.3:a:bing_site_verification_plugin_using_meta_tag_project:bing_site_verification_plugin_using_meta_tag:*:*:*:*:*:wordpress:*:*" + ], + "birthdays-widget": [ + "cpe:2.3:a:birthdays_widget_project:birthdays_widget:*:*:*:*:*:wordpress:*:*" + ], + "bit-assist": [ + "cpe:2.3:a:bitapps:bit_assist:*:*:*:*:*:wordpress:*:*" + ], + "bit-form": [ + "cpe:2.3:a:bitapps:contact_form_builder:*:*:*:*:*:wordpress:*:*" + ], + "bitcoin-faucet": [ + "cpe:2.3:a:bitcoin\\/altcoin_faucet_project:bitcoin\\/altcoin_faucet:*:*:*:*:*:wordpress:*:*" + ], + "biteship": [ + "cpe:2.3:a:biteship:biteship:*:*:*:*:*:wordpress:*:*" + ], + "bj-lazy-load": [ + "cpe:2.3:a:angrycreative:bj_lazy_load:*:*:*:*:*:wordpress:*:*" + ], + "blackhole-bad-bots": [ + "cpe:2.3:a:plugin-planet:blackhole_for_bad_bots:*:*:*:*:*:wordpress:*:*" + ], + "block-options": [ + "cpe:2.3:a:extendify:editorskit:*:*:*:*:*:wordpress:*:*" + ], + "block-specific-plugin-updates": [ + "cpe:2.3:a:dineshkarki:block_plugin_update:*:*:*:*:*:wordpress:*:*" + ], + "blockonomics-bitcoin-payments": [ + "cpe:2.3:a:blockonomics:blockonomics:*:*:*:*:*:wordpress:*:*" + ], + "blocksy-companion": [ + "cpe:2.3:a:creativethemes:blocksy_companion:*:*:*:*:*:wordpress:*:*" + ], + "blog-designer-pack": [ + "cpe:2.3:a:infornweb:news_\\\u0026_blog_designer_pack:*:*:*:*:*:wordpress:*:*" + ], + "blog-filter": [ + "cpe:2.3:a:awplife:blog_filter:*:*:*:*:*:wordpress:*:*" + ], + "blog-floating-button": [ + "cpe:2.3:a:meril:blog_floating_button:*:*:*:*:*:wordpress:*:*" + ], + "blog-in-blog": [ + "cpe:2.3:a:blog-in-blog_project:blog-in-blog:*:*:*:*:*:wordpress:*:*" + ], + "blog2social": [ + "cpe:2.3:a:adenion:blog2social:*:*:*:*:*:wordpress:*:*" + ], + "blogger-importer": [ + "cpe:2.3:a:wordpress:blogger_importer:*:*:*:*:*:wordpress:*:*" + ], + "blue-admin": [ + "cpe:2.3:a:blue-admin_project:blue-admin:*:*:*:*:*:wordpress:*:*" + ], + "bluet-keywords-tooltip-generator": [ + "cpe:2.3:a:tooltipy:tooltipy:*:*:*:*:*:wordpress:*:*" + ], + "bmi-bmr-calculator": [ + "cpe:2.3:a:bmi_bmr_calculator_project:bmi_bmr_calculator:*:*:*:*:*:wordpress:*:*" + ], + "bmi-calculator-shortcode": [ + "cpe:2.3:a:bmicalculator:bmi-calculator-shortcode:*:*:*:*:*:wordpress:*:*" + ], + "bne-testimonials": [ + "cpe:2.3:a:bnecreative:bne_testimonials:*:*:*:*:*:wordpress:*:*" + ], + "bnfw": [ + "cpe:2.3:a:madewithfuel:better_notifications_for_wp:*:*:*:*:*:wordpress:*:*" + ], + "bold-page-builder": [ + "cpe:2.3:a:bold-themes:bold_page_builder:*:*:*:*:*:wordpress:*:*" + ], + "boldgrid-backup": [ + "cpe:2.3:a:boldgrid:total_upkeep:*:*:*:*:*:wordpress:*:*" + ], + "bonus-for-woo": [ + "cpe:2.3:a:computy:bonus_for_woo:*:*:*:*:*:wordpress:*:*" + ], + "book-appointment-online": [ + "cpe:2.3:a:oz-plugin:book_appointment_online:*:*:*:*:*:wordpress:*:*" + ], + "booking": [ + "cpe:2.3:a:booking_calendar_project:booking_calendar:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpbookingcalendar:booking_calendar:*:*:*:*:*:wordpress:*:*" + ], + "booking-and-rental-manager-for-woocommerce": [ + "cpe:2.3:a:magepeople:booking_\\\u0026_rental_manager:*:*:*:*:*:wordpress:*:*" + ], + "booking-calendar": [ + "cpe:2.3:a:wpdevart:booking_calendar:*:*:*:*:*:wordpress:*:*" + ], + "booking-calendar-contact-form": [ + "cpe:2.3:a:codepeople:booking_calendar_contact_form:*:*:*:*:*:wordpress:*:*" + ], + "booking-manager": [ + "cpe:2.3:a:oplugins:booking_manager:*:*:*:*:*:wordpress:*:*" + ], + "booking-package": [ + "cpe:2.3:a:saasproject:booking_package:*:*:*:*:*:wordpress:*:*" + ], + "booking-sms": [ + "cpe:2.3:a:mediaburst:booking_calendar:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:mediaburst:booking_calendar_sms:*:*:*:*:*:wordpress:*:*" + ], + "booking-system": [ + "cpe:2.3:a:pinpoint:pinpoint_booking_system:*:*:*:*:*:wordpress:*:*" + ], + "bookingcom-banner-creator": [ + "cpe:2.3:a:bookingholdings:booking.com_banner_creator:*:*:*:*:*:wordpress:*:*" + ], + "bookingcom-product-helper": [ + "cpe:2.3:a:bookingholdings:booking.com_product_helper:*:*:*:*:*:wordpress:*:*" + ], + "bookingpress-appointment-booking": [ + "cpe:2.3:a:reputeinfosystems:bookingpress:*:*:*:*:*:wordpress:*:*" + ], + "bookit": [ + "cpe:2.3:a:stylemixthemes:bookit:*:*:*:*:*:wordpress:*:*" + ], + "bookly-responsive-appointment-booking-tool": [ + "cpe:2.3:a:booking-wp-plugin:bookly:*:*:*:*:*:wordpress:*:*" + ], + "bookmarkify": [ + "cpe:2.3:a:bookmarkify_project:bookmarkify:*:*:*:*:*:wordpress:*:*" + ], + "bookshelf": [ + "cpe:2.3:a:bookshelf_project:bookshelf:*:*:*:*:*:wordpress:*:*" + ], + "boostify-header-footer-builder": [ + "cpe:2.3:a:woostify:boostify_header_footer_builder_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "border-loading-bar": [ + "cpe:2.3:a:border_loading_bar_project:border_loading_bar:*:*:*:*:*:wordpress:*:*" + ], + "borderless": [ + "cpe:2.3:a:visualmodo:borderless:*:*:*:*:*:wordpress:*:*" + ], + "bosa-elementor-for-woocommerce": [ + "cpe:2.3:a:bosathemes:bosa_elementor_addons_and_templates_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "boxzilla": [ + "cpe:2.3:a:ibericode:boxzilla:*:*:*:*:*:wordpress:*:*" + ], + "bp-better-messages": [ + "cpe:2.3:a:wordplus:better_messages:*:*:*:*:*:wordpress:*:*" + ], + "bp-cover": [ + "cpe:2.3:a:buddypress_cover_project:buddypress_cover:*:*:*:*:*:wordpress:*:*" + ], + "bp-profile-search": [ + "cpe:2.3:a:dontdream:bp_profile_search:*:*:*:*:*:wordpress:*:*" + ], + "bp-profile-shortcodes-extra": [ + "cpe:2.3:a:venutius:bp_profile_shortcodes_extra:*:*:*:*:*:wordpress:*:*" + ], + "bp-social-connect": [ + "cpe:2.3:a:vibethemes:bp_social_connect:*:*:*:*:*:wordpress:*:*" + ], + "brave-popup-builder": [ + "cpe:2.3:a:getbrave:brave:*:*:*:*:*:wordpress:*:*" + ], + "bravo-translate": [ + "cpe:2.3:a:guelbetech:bravo_translate:*:*:*:*:*:wordpress:*:*" + ], + "breadcrumbs-by-menu": [ + "cpe:2.3:a:holest:breadcrumbs_by_menu:*:*:*:*:*:wordpress:*:*" + ], + "brizy": [ + "cpe:2.3:a:brizy:brizy-page_builder:*:*:*:*:*:wordpress:*:*" + ], + "broken-link-checker": [ + "cpe:2.3:a:managewp:broken_link_checker:*:*:*:*:*:wordpress:*:*" + ], + "broken-link-checker-for-youtube": [ + "cpe:2.3:a:superblogme:broken_link_checker_for_youtube:*:*:*:*:*:wordpress:*:*" + ], + "broken-link-manager": [ + "cpe:2.3:a:broken_link_manager_project:broken_link_manager:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:k-78:broken_link_manager:*:*:*:*:*:wordpress:*:*" + ], + "browser-shots": [ + "cpe:2.3:a:prothemedesign:browser_screenshots:*:*:*:*:*:wordpress:*:*" + ], + "brute-force-login-protection": [ + "cpe:2.3:a:fresh-media:brute_force_login_protection:*:*:*:*:*:wordpress:*:*" + ], + "brutebank": [ + "cpe:2.3:a:brutebank:brutebank:*:*:*:*:*:wordpress:*:*" + ], + "bs-shortcode-ultimate": [ + "cpe:2.3:a:addonmaster:bootstrap_shortcodes_ultimate:*:*:*:*:*:wordpress:*:*" + ], + "bsk-contact-form-7-blacklist": [ + "cpe:2.3:a:bannersky:bsk_contact_form_7_blacklist:*:*:*:*:*:wordpress:*:*" + ], + "bsk-gravityforms-blacklist": [ + "cpe:2.3:a:bannersky:bsk_forms_blacklist:*:*:*:*:*:wordpress:*:*" + ], + "bsk-pdf-manager": [ + "cpe:2.3:a:bannersky:bsk_pdf_manager:*:*:*:*:*:wordpress:*:*" + ], + "bsuite": [ + "cpe:2.3:a:bsuite_project:bsuite:*:*:*:*:*:wordpress:*:*" + ], + "bubble-menu": [ + "cpe:2.3:a:wow-company:bubble_menu:*:*:*:*:free:wordpress:*:*" + ], + "buddybadges": [ + "cpe:2.3:a:buddybadges_project:buddybadges:*:*:*:*:*:wordpress:*:*" + ], + "buddyforms": [ + "cpe:2.3:a:themekraft:buddyforms:*:*:*:*:*:wordpress:*:*" + ], + "buddymeet": [ + "cpe:2.3:a:cytechmobile:buddymeet:*:*:*:*:*:wordpress:*:*" + ], + "buddypress": [ + "cpe:2.3:a:buddypress:buddypress:*:*:*:*:*:wordpress:*:*" + ], + "buddypress-activity-plus": [ + "cpe:2.3:a:incsub:buddypress-activity-plus:*:*:*:*:*:wordpress:*:*" + ], + "buddypress-global-search": [ + "cpe:2.3:a:buddyboss:buddypress_global_search:*:*:*:*:*:wordpress:*:*" + ], + "buddypress-media": [ + "cpe:2.3:a:rtcamp:rtmedia:*:*:*:*:*:wordpress:*:*" + ], + "bug-library": [ + "cpe:2.3:a:bug_library_project:bug_library:*:*:*:*:*:wordpress:*:*" + ], + "bulk-comment-remove": [ + "cpe:2.3:a:supremo:bulk_comment_remove:*:*:*:*:*:wordpress:*:*" + ], + "bulk-delete-users-by-email": [ + "cpe:2.3:a:speakdigital:bulk_delete_users_by_email:*:*:*:*:*:wordpress:*:*" + ], + "bulk-edit-user-profiles-in-spreadsheet": [ + "cpe:2.3:a:vegacorp:bulk_edit_and_create_user_profiles_-_wp_sheet_editor:*:*:*:*:*:wordpress:*:*" + ], + "bulk-editor": [ + "cpe:2.3:a:pluginus:wolf_-_wordpress_posts_bulk_editor_and_products_manager_professional:*:*:*:*:*:wordpress:*:*" + ], + "bulk-noindex-nofollow-toolkit-by-mad-fish": [ + "cpe:2.3:a:madfishdigital:bulk_noindex_\\\u0026_nofollow_toolkit:*:*:*:*:*:wordpress:*:*" + ], + "bulk-page-creator": [ + "cpe:2.3:a:bulk_page_creator_project:bulk_page_creator:*:*:*:*:*:wordpress:*:*" + ], + "bulletin-announcements": [ + "cpe:2.3:a:bulletin:announcement_\\\u0026_notification_banner_-_bulletin:*:*:*:*:*:wordpress:*:*" + ], + "bulletproof-security": [ + "cpe:2.3:a:ait-pro:bulletproof_security:*:*:*:*:*:wordpress:*:*" + ], + "burst-statistics": [ + "cpe:2.3:a:burst-statistics:burst_statistics:*:*:*:*:*:wordpress:*:*" + ], + "bus-ticket-booking-with-seat-reservation": [ + "cpe:2.3:a:mage-people:bus_ticket_booking_with_seat_reservation:*:*:*:*:*:wordpress:*:*" + ], + "business-directory-plugin": [ + "cpe:2.3:a:businessdirectoryplugin:business_directory:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:strategy11:business_directory_plugin_-_easy_listing_directories:*:*:*:*:*:wordpress:*:*" + ], + "business-hours-indicator": [ + "cpe:2.3:a:business_hours_indicator_project:business_hours_indicator:*:*:*:*:*:wordpress:*:*" + ], + "business-manager": [ + "cpe:2.3:a:linksoftwarellc:business_manager:*:*:*:*:*:wordpress:*:*" + ], + "button-generation": [ + "cpe:2.3:a:wow-company:button_generator:*:*:*:*:*:wordpress:*:*" + ], + "buttonizer-multifunctional-button": [ + "cpe:2.3:a:buttonizer:buttonizer:*:*:*:*:*:wordpress:*:*" + ], + "buttons-shortcode-and-widget": [ + "cpe:2.3:a:otwthemes:buttons_shortcode_and_widget:*:*:*:*:*:wordpress:*:*" + ], + "buymeacoffee": [ + "cpe:2.3:a:buymeacoffee:buy_me_a_coffee:*:*:*:*:*:wordpress:*:*" + ], + "buzzsprout-podcasting": [ + "cpe:2.3:a:buzzsprout:buzzsprout:*:*:*:*:*:wordpress:*:*" + ], + "bwp-google-xml-sitemaps": [ + "cpe:2.3:a:bwp-google-xml-sitemaps_project:bwp-google-xml-sitemaps:*:*:*:*:*:wordpress:*:*" + ], + "bws-featured-posts": [ + "cpe:2.3:a:bestwebsoft:featured_posts:*:*:*:*:*:wordpress:*:*" + ], + "bws-google-analytics": [ + "cpe:2.3:a:bestwebsoft:google_analytics:*:*:*:*:*:wordpress:*:*" + ], + "bws-google-maps": [ + "cpe:2.3:a:bestwebsoft:google_maps:*:*:*:*:*:wordpress:*:*" + ], + "bws-latest-posts": [ + "cpe:2.3:a:bestwebsoft:latest_posts:*:*:*:*:*:wordpress:*:*" + ], + "bws-linkedin": [ + "cpe:2.3:a:bestwebsoft:linkedin:*:*:*:*:*:wordpress:*:*" + ], + "bws-pinterest": [ + "cpe:2.3:a:bestwebsoft:pinterest:*:*:*:*:*:wordpress:*:*" + ], + "bws-popular-posts": [ + "cpe:2.3:a:bestwebsoft:popular_posts:*:*:*:*:*:wordpress:*:*" + ], + "bws-smtp": [ + "cpe:2.3:a:bestwebsoft:smtp:*:*:*:*:*:wordpress:*:*" + ], + "bws-testimonials": [ + "cpe:2.3:a:bestwebsoft:google_maps:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:bestwebsoft:testimonials:*:*:*:*:*:wordpress:*:*" + ], + "bxslider-wp": [ + "cpe:2.3:a:bxslider_wp_project:bxslider_wp:*:*:*:*:*:wordpress:*:*" + ], + "byconsole-woo-order-delivery-time": [ + "cpe:2.3:a:byconsole:wooodt_lite:*:*:*:*:*:wordpress:*:*" + ], + "cab-fare-calculator": [ + "cpe:2.3:a:kanev:cab_fare_calculator:*:*:*:*:*:wordpress:*:*" + ], + "cache-images": [ + "cpe:2.3:a:cache_images_project:cache_images:*:*:*:*:*:wordpress:*:*" + ], + "cafe-lite": [ + "cpe:2.3:a:cleversoft:clever_addons_for_elementor:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:download_clever_addons_for_elementor_project:download_clever_addons_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "calculated-fields-form": [ + "cpe:2.3:a:codepeople:calculated_fields_form:*:*:*:*:*:wordpress:*:*" + ], + "calculator-builder": [ + "cpe:2.3:a:wow-company:calculator-builder:*:*:*:*:*:wordpress:*:*" + ], + "caldera-forms": [ + "cpe:2.3:a:calderaforms:caldera_forms:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:calderalabs:caldera_forms:*:*:*:*:*:wordpress:*:*" + ], + "calendar": [ + "cpe:2.3:a:kieranoshea:calendar:*:*:*:*:*:wordpress:*:*" + ], + "calendar-booking": [ + "cpe:2.3:a:startbooking:scheduling_plugin:*:*:*:*:*:wordpress:*:*" + ], + "calendar-plugin": [ + "cpe:2.3:a:calendar_plugin_project:calendar_plugin:*:*:*:*:*:wordpress:*:*" + ], + "call-now-button": [ + "cpe:2.3:a:callnowbutton:call_now_button:*:*:*:*:*:wordpress:*:*" + ], + "callbook-mobile-bar": [ + "cpe:2.3:a:call\\\u0026book_mobile_bar_project:call\\\u0026book_mobile_bar:*:*:*:*:*:wordpress:*:*" + ], + "callrail-phone-call-tracking": [ + "cpe:2.3:a:callrail:callrail_phone_call_tracking:*:*:*:*:*:wordpress:*:*" + ], + "campaign-monitor-wp": [ + "cpe:2.3:a:fatcatapps:campaign_monitor_optin_cat:*:*:*:*:*:wordpress:*:*" + ], + "campaign-url-builder": [ + "cpe:2.3:a:campaign_url_builder_project:campaign_url_builder:*:*:*:*:*:wordpress:*:*" + ], + "camptix": [ + "cpe:2.3:a:automattic:camptix:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:automattic:camptix_event_ticketing:*:*:*:*:*:wordpress:*:*" + ], + "cancel-order-request-woocommerce": [ + "cpe:2.3:a:piwebsolution:cancel_order_request_\\/_return_order_\\/_repeat_order_\\/_reorder_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "candidate-application-form": [ + "cpe:2.3:a:candidate-application-form_project:candidate-application-form:*:*:*:*:*:wordpress:*:*" + ], + "canvasio3d-light": [ + "cpe:2.3:a:virtuellwerk:canvasio3d_light:*:*:*:*:*:wordpress:*:*" + ], + "capability-manager-enhanced": [ + "cpe:2.3:a:publishpress:capabilities:*:*:*:*:-:wordpress:*:*" + ], + "captain-slider": [ + "cpe:2.3:a:captain-slider_project:captain-slider:*:*:*:*:*:wordpress:*:*" + ], + "captainform": [ + "cpe:2.3:a:captainform:captainform:*:*:*:*:*:wordpress:*:*" + ], + "captcha": [ + "cpe:2.3:a:bestwebsoft:captcha:*:*:*:*:*:wordpress:*:*" + ], + "captchinoo-captcha-for-login-form-protection": [ + "cpe:2.3:a:wp-buy:captchinoo:*:*:*:*:*:wordpress:*:*" + ], + "car-rental": [ + "cpe:2.3:a:bestwebsoft:car_rental:*:*:*:*:*:wordpress:*:*" + ], + "cardealer": [ + "cpe:2.3:a:car_dealer_project:car_dealer:*:*:*:*:*:wordpress:*:*" + ], + "cardoza-ajax-search": [ + "cpe:2.3:a:ajax_search_project:ajax_search:*:*:*:*:*:wordpress:*:*" + ], + "cardoza-facebook-like-box": [ + "cpe:2.3:a:facebook_like_box_project:facebook_like_box:*:*:*:*:*:wordpress:*:*" + ], + "cardoza-wordpress-poll": [ + "cpe:2.3:a:cardozatechnologies:wordpress_poll:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wordpress_poll_project:wordpress_poll:*:*:*:*:*:wordpress:*:*" + ], + "caret-country-access-limit": [ + "cpe:2.3:a:caret:country_access_limit:*:*:*:*:*:wordpress:*:*" + ], + "carousel-ck": [ + "cpe:2.3:a:ceikay:carousel_ck:*:*:*:*:*:wordpress:*:*" + ], + "carrrot": [ + "cpe:2.3:a:carrrot:carrrot:*:*:*:*:*:wordpress:*:*" + ], + "cars-seller-auto-classifieds-script": [ + "cpe:2.3:a:cars-seller-auto-classifieds-script_project:cars-seller-auto-classifieds-script:*:*:*:*:*:wordpress:*:*" + ], + "cart66-lite": [ + "cpe:2.3:a:reality66:cart66_lite:*:*:*:*:*:wordpress:*:*" + ], + "cartflows": [ + "cpe:2.3:a:cartflows:cartflows:*:*:*:*:-:wordpress:*:*", + "cpe:2.3:a:cartflows:cartflows:*:*:*:*:pro:wordpress:*:*" + ], + "cashtomer": [ + "cpe:2.3:a:cashtomer_project:cashtomer:*:*:*:*:*:wordpress:*:*" + ], + "catalog": [ + "cpe:2.3:a:web-dorado:spidercatalog:*:*:*:*:*:wordpress:*:*" + ], + "catalyst-connect-client-portal": [ + "cpe:2.3:a:catalystconnect:catalyst_connect_zoho_crm_client_portal:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:catalystconnect:zoho_crm_client_portal:*:*:*:*:*:wordpress:*:*" + ], + "catch-breadcrumb": [ + "cpe:2.3:a:catchplugins:catch_breadcrumb:*:*:*:*:*:wordpress:*:*" + ], + "catch-scroll-progress-bar": [ + "cpe:2.3:a:catchplugins:catch_scroll_progress_bar:*:*:*:*:*:wordpress:*:*" + ], + "catch-sticky-menu": [ + "cpe:2.3:a:catchplugins:catch_sticky_menu:*:*:*:*:*:wordpress:*:*" + ], + "catch-themes-demo-import": [ + "cpe:2.3:a:catchplugins:catch_themes_demo_import:*:*:*:*:*:wordpress:*:*" + ], + "catch-under-construction": [ + "cpe:2.3:a:catchplugins:catch_under_construction:*:*:*:*:*:wordpress:*:*" + ], + "catch-web-tools": [ + "cpe:2.3:a:catchplugins:catch_web_tools:*:*:*:*:*:wordpress:*:*" + ], + "category-post-list-widget": [ + "cpe:2.3:a:starkdigital:category_post_list_widget:*:*:*:*:*:wordpress:*:*" + ], + "category-seo-meta-tags": [ + "cpe:2.3:a:bala-krishna:category_seo_meta_tags:*:*:*:*:*:wordpress:*:*" + ], + "category-specific-rss-feed-menu": [ + "cpe:2.3:a:tipsandtricks-hq:category_specific_rss_feed_subscription:*:*:*:*:*:wordpress:*:*" + ], + "cbxgooglemap": [ + "cpe:2.3:a:codeboxr:cbx_map:*:*:*:*:*:wordpress:*:*" + ], + "cbxpetition": [ + "cpe:2.3:a:codeboxr:cbx_petition_for_wordpress:*:*:*:*:*:wordpress:*:*" + ], + "cc-bmi-calculator": [ + "cpe:2.3:a:calculatorsworld:cc_bmi_calculator:*:*:*:*:*:wordpress:*:*" + ], + "cc-custom-taxonmy": [ + "cpe:2.3:a:cc_custom_taxonomy_project:cc_custom_taxonomy:*:*:*:*:*:wordpress:*:*" + ], + "cds-simple-seo": [ + "cpe:2.3:a:coleds:simple_seo:*:*:*:*:*:wordpress:*:*" + ], + "cf7-constant-contact": [ + "cpe:2.3:a:crmperks:integration_for_constant_contact_and_contact_form_7\\,_wpforms\\,_elementor\\,_ninja:*:*:*:*:*:wordpress:*:*" + ], + "cf7-google-sheets-connector": [ + "cpe:2.3:a:gsheetconnector:cf7_google_sheets_connector:*:*:*:*:free:wordpress:*:*" + ], + "cf7-invisible-recaptcha": [ + "cpe:2.3:a:vsourz:cf7_invisible_recaptcha:*:*:*:*:*:wordpress:*:*" + ], + "cf7-redirect-thank-you-page": [ + "cpe:2.3:a:wpplugin:contact_form_7_redirect_\\\u0026_thank_you_page:*:*:*:*:*:wordpress:*:*" + ], + "cf7-salesforce": [ + "cpe:2.3:a:crmperks:integration_for_salesforce_and_contact_form_7\\,_wpforms\\,_elementor\\,_ninja_forms:*:*:*:*:*:wordpress:*:*" + ], + "cf7-store-to-db-lite": [ + "cpe:2.3:a:accesspressthemes:form_store_to_db:*:*:*:*:*:wordpress:*:*" + ], + "cf7-widget-elementor": [ + "cpe:2.3:a:voidcoders:void_contact_form_7_widget_for_elementor_page_builder:*:*:*:*:*:wordpress:*:*" + ], + "cf7-zoho": [ + "cpe:2.3:a:crmperks:integration_for_contact_form_7_and_zoho_crm\\,_bigin:*:*:*:*:*:wordpress:*:*" + ], + "cforms2": [ + "cpe:2.3:a:cformsii_project:cformsii:*:*:*:*:*:wordpress:*:*" + ], + "chained-quiz": [ + "cpe:2.3:a:kibokolabs:chained_quiz:*:*:*:*:*:wordpress:*:*" + ], + "chamber-dashboard-business-directory": [ + "cpe:2.3:a:chamber_dashboard_business_directory_project:chamber_dashboard_business_directory:*:*:*:*:*:wordpress:*:*" + ], + "chameleon": [ + "cpe:2.3:a:chameleon_project:chameleon:*:*:*:*:*:wordpress:*:*" + ], + "chameleon-css": [ + "cpe:2.3:a:chameleon_css_project:chameleon_css:*:*:*:*:*:wordpress:*:*" + ], + "change-uploaded-file-permissions": [ + "cpe:2.3:a:change_uploaded_file_permissions_project:change_uploaded_file_permissions:*:*:*:*:*:wordpress:*:*" + ], + "change-wp-admin-login": [ + "cpe:2.3:a:change_wp-admin_login_project:change_wp-admin_login:*:*:*:*:*:wordpress:*:*" + ], + "charitable": [ + "cpe:2.3:a:wpcharitable:charitable:*:*:*:*:*:wordpress:*:*" + ], + "chart-builder": [ + "cpe:2.3:a:ays-pro:chartify:*:*:*:*:*:wordpress:*:*" + ], + "chat-bee": [ + "cpe:2.3:a:chat_bee_project:chat_bee:*:*:*:*:*:wordpress:*:*" + ], + "chatbot": [ + "cpe:2.3:a:quantumcloud:ai_chatbot:*:*:*:*:*:wordpress:*:*" + ], + "chaty": [ + "cpe:2.3:a:premio:chaty:*:*:*:*:*:wordpress:*:*" + ], + "check-email": [ + "cpe:2.3:a:check_email_project:check_email:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpchill:check_\\\u0026_log_email:*:*:*:*:*:wordpress:*:*" + ], + "checklist": [ + "cpe:2.3:a:checklist:checklist:*:*:*:*:*:wordpress:*:*" + ], + "checkout-for-paypal": [ + "cpe:2.3:a:noorsplugin:checkout_for_paypal:*:*:*:*:*:wordpress:*:*" + ], + "checkout-plugins-stripe-woo": [ + "cpe:2.3:a:checkoutplugins:stripe_payments_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "chp-ads-block-detector": [ + "cpe:2.3:a:sureshchand:chp_ads_block_detector:*:*:*:*:*:wordpress:*:*" + ], + "chronosly-events-calendar": [ + "cpe:2.3:a:chronosly-events-calendar_project:chronosly-events-calendar:*:*:*:*:*:wordpress:*:*" + ], + "church-admin": [ + "cpe:2.3:a:church_admin_project:church_admin:*:*:*:*:*:wordpress:*:*" + ], + "circles-gallery": [ + "cpe:2.3:a:greentreelabs:circles_gallery:*:*:*:*:*:wordpress:*:*" + ], + "cits-support-svg-webp-media-upload": [ + "cpe:2.3:a:ashik:cits_support_svg\\,_webp_media_and_ttf\\,otf_file_upload:*:*:*:*:*:wordpress:*:*" + ], + "ckeditor-for-wordpress": [ + "cpe:2.3:a:cksource:ckeditor:*:*:*:*:*:wordpress:*:*" + ], + "classic-editor-and-classic-widgets": [ + "cpe:2.3:a:wpgrim:classic_editor_and_classic_widgets:*:*:*:*:*:wordpress:*:*" + ], + "classified-listing": [ + "cpe:2.3:a:radiustheme:classified_listing_-_classified_ads_\\\u0026_business_directory:*:*:*:*:*:wordpress:*:*" + ], + "classyfrieds": [ + "cpe:2.3:a:classyfrieds_project:classyfrieds:*:*:*:*:*:wordpress:*:*" + ], + "clean-login": [ + "cpe:2.3:a:codection:clean_login:*:*:*:*:*:wordpress:*:*" + ], + "cleantalk-spam-protect": [ + "cpe:2.3:a:cleantalk:anti-spam:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:cleantalk:spam_protection\\,_antispam\\,_firewall:*:*:*:*:*:wordpress:*:*" + ], + "clerkio": [ + "cpe:2.3:a:clerk:clerk.io:*:*:*:*:*:wordpress:*:*" + ], + "click-datos-lopd": [ + "cpe:2.3:a:clickdatos:proteccion_de_datos_rgpd:*:*:*:*:*:wordpress:*:*" + ], + "click-pledge-wpjobboard": [ + "cpe:2.3:a:wpjobboard:wpjobboard:*:*:*:*:*:wordpress:*:*" + ], + "click-to-call-or-chat-buttons": [ + "cpe:2.3:a:digitalblue:click_to_call_or_chat_buttons:*:*:*:*:*:wordpress:*:*" + ], + "click-to-chat-for-whatsapp": [ + "cpe:2.3:a:holithemes:click_to_chat:*:*:*:*:*:wordpress:*:*" + ], + "click-to-tweet": [ + "cpe:2.3:a:clicktotweet:click_to_tweet:*:*:*:*:*:wordpress:*:*" + ], + "clickdesk-live-support-chat-plugin": [ + "cpe:2.3:a:clickdesk:clickdesk:*:*:*:*:*:wordpress:*:*" + ], + "clictracker": [ + "cpe:2.3:a:wp_clictracker_project:wp_clictracker:*:*:*:*:*:wordpress:*:*" + ], + "client-dash": [ + "cpe:2.3:a:realbigplugins:client_dash:*:*:*:*:*:wordpress:*:*" + ], + "client-portal": [ + "cpe:2.3:a:cozmoslabs:client_portal:*:*:*:*:*:wordpress:*:*" + ], + "client-portal-suitedash-login": [ + "cpe:2.3:a:suitedash:client_portal_\\:suitedash_direct_login:*:*:*:*:*:wordpress:*:*" + ], + "clio-grow-form": [ + "cpe:2.3:a:clio:clio_grow:*:*:*:*:*:wordpress:*:*" + ], + "clockwork-two-factor-authentication": [ + "cpe:2.3:a:mediaburst:two-factor_authentication:*:*:*:*:*:wordpress:*:*" + ], + "cloudnet-sync": [ + "cpe:2.3:a:cloudnet360:cloudnet360:*:*:*:*:*:wordpress:*:*" + ], + "clover-online-orders": [ + "cpe:2.3:a:zaytech:smart_online_order_for_clover:*:*:*:*:*:wordpress:*:*" + ], + "club-management-software": [ + "cpe:2.3:a:swiftcrm:club-management-software:*:*:*:*:*:wordpress:*:*" + ], + "cluevo-lms": [ + "cpe:2.3:a:cluevo:learning_management_system:*:*:*:*:*:wordpress:*:*" + ], + "cm-download-manager": [ + "cpe:2.3:a:cminds:cm_download_manager:*:*:*:*:*:wordpress:*:*" + ], + "cm-on-demand-search-and-replace": [ + "cpe:2.3:a:cminds:cm_on_demand_search_and_replace:*:*:*:*:*:wordpress:*:*" + ], + "cm-pop-up-banners": [ + "cpe:2.3:a:cminds:cm_popup:*:*:*:*:*:wordpress:*:*" + ], + "cm-video-lesson-manager": [ + "cpe:2.3:a:creativemindssolutions:video_lessons_manager:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:creativemindssolutions:video_lessons_manager_pro:*:*:*:*:*:wordpress:*:*" + ], + "cmp-coming-soon-maintenance": [ + "cpe:2.3:a:niteothemes:cmp:*:*:*:*:*:wordpress:*:*" + ], + "cms-commander-client": [ + "cpe:2.3:a:cmscommander:cms_commander:*:*:*:*:*:wordpress:*:*" + ], + "cms-press": [ + "cpe:2.3:a:cms_press_project:cms_press:*:*:*:*:*:wordpress:*:*" + ], + "cmyee-momentopress": [ + "cpe:2.3:a:chrisyee:momentopress_for_momento360:*:*:*:*:*:wordpress:*:*" + ], + "code-snippets": [ + "cpe:2.3:a:code_snippets:code_snippets:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:codesnippets:code_snippets:*:*:*:*:*:wordpress:*:*" + ], + "code-snippets-extended": [ + "cpe:2.3:a:code_snippets_extended_project:code_snippets_extended:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:codesnippets:code_snippets:*:*:*:*:*:wordpress:*:*" + ], + "codecolorer": [ + "cpe:2.3:a:codecolorer_project:codecolorer:*:*:*:*:*:wordpress:*:*" + ], + "codelights-shortcodes-and-widgets": [ + "cpe:2.3:a:codelights-shortcodes-and-widgets_project:codelights-shortcodes-and-widgets:*:*:*:*:*:wordpress:*:*" + ], + "codepress-admin-columns": [ + "cpe:2.3:a:admincolumns:admin_columns:*:*:*:*:free:wordpress:*:*", + "cpe:2.3:a:admincolumns:admin_columns:*:*:*:*:pro:wordpress:*:*" + ], + "codestyling-localization": [ + "cpe:2.3:a:codestyling_localization_project:codestyling_localization:*:*:*:*:*:wordpress:*:*" + ], + "colibri-page-builder": [ + "cpe:2.3:a:extendthemes:colibri_page_builder:*:*:*:*:*:wordpress:*:*" + ], + "colorful-categories": [ + "cpe:2.3:a:gesundheit-bewegt:colorful_categories:*:*:*:*:*:wordpress:*:*" + ], + "column-matic": [ + "cpe:2.3:a:column-matic_project:column-matic:*:*:*:*:*:wordpress:*:*" + ], + "comicbookmanagementsystemweeklypicks": [ + "cpe:2.3:a:inksplat:comic_book_management_system:*:*:*:*:*:wordpress:*:*" + ], + "coming-soon": [ + "cpe:2.3:a:seedprod:coming_soon_page\\,_under_construction_\\\u0026_maintenance_mode:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:seedprod:website_builder_by_seedprod:*:*:*:*:*:wordpress:*:*" + ], + "coming-soon-maintenance-mode-from-acurax": [ + "cpe:2.3:a:acurax:under_construction_\\/_maintenance_mode:*:*:*:*:*:wordpress:*:*" + ], + "coming-soon-page": [ + "cpe:2.3:a:wpdevart:coming_soon_and_maintenance_mode:*:*:*:*:*:wordpress:*:*" + ], + "coming-soon-wp": [ + "cpe:2.3:a:dazzlersoftware:coming_soon\\,_under_construction_\\\u0026_maintenance_mode_by_dazzler:*:*:*:*:*:wordpress:*:*" + ], + "coming-soons": [ + "cpe:2.3:a:rich_web:coming_soon_-_under_construction:*:*:*:*:*:wordpress:*:*" + ], + "comment-form": [ + "cpe:2.3:a:webgilde:advanced_comment_form:*:*:*:*:*:wordpress:*:*" + ], + "comment-highlighter": [ + "cpe:2.3:a:comment_highlighter_project:comment_highlighter:*:*:*:*:*:wordpress:*:*" + ], + "comment-license": [ + "cpe:2.3:a:comment_license_project:comment_license:*:*:*:*:*:wordpress:*:*" + ], + "comment-link-remove": [ + "cpe:2.3:a:quantumcloud:comment_link_remove_and_other_comment_tools:*:*:*:*:*:wordpress:*:*" + ], + "comment-reply-notification": [ + "cpe:2.3:a:comment_reply_notification_project:comment_reply_notification:*:*:*:*:*:wordpress:*:*" + ], + "comments-disable-accesspress": [ + "cpe:2.3:a:accesspressthemes:comments_disable_-_accesspress:*:*:*:*:*:wordpress:*:*" + ], + "comments-import-export-woocommerce": [ + "cpe:2.3:a:webtoffee:wordpress_comments_import_and_export:*:*:*:*:*:wordpress:*:*" + ], + "comments-like-dislike": [ + "cpe:2.3:a:wphappycoders:comments_like_dislike:*:*:*:*:*:wordpress:*:*" + ], + "comments-ratings": [ + "cpe:2.3:a:pixelgrade:comments_rating:*:*:*:*:*:wordpress:*:*" + ], + "commenttweets": [ + "cpe:2.3:a:theresehansen:commenttweets:*:*:*:*:*:wordpress:*:*" + ], + "commonsbooking": [ + "cpe:2.3:a:wielebenwir:commonsbooking:*:*:*:*:*:wordpress:*:*" + ], + "community-events": [ + "cpe:2.3:a:community_events_project:community_events:*:*:*:*:*:wordpress:*:*" + ], + "compact-wp-audio-player": [ + "cpe:2.3:a:tipsandtricks-hq:compact_wp_audio_player:*:*:*:*:*:wordpress:*:*" + ], + "companion-auto-update": [ + "cpe:2.3:a:codeermeneer:companion_auto_update:*:*:*:*:*:wordpress:*:*" + ], + "companion-sitemap-generator": [ + "cpe:2.3:a:codeermeneer:companion_sitemap_generator:*:*:*:*:*:wordpress:*:*" + ], + "complete-open-graph": [ + "cpe:2.3:a:alexmacarthur:complete_open_graph:*:*:*:*:*:wordpress:*:*" + ], + "complianz-gdpr": [ + "cpe:2.3:a:really-simple-plugins:complianz:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:really-simple-plugins:complianz:*:*:*:*:premium:wordpress:*:*" + ], + "conditional-extra-fees-for-woocommerce": [ + "cpe:2.3:a:piwebsolution:conditional_cart_fee_\\/_extra_charge_rule_for_woocommerce_extra_fees:*:*:*:*:*:wordpress:*:*" + ], + "conditional-marketing-mailer": [ + "cpe:2.3:a:wp-buy:woocommerce_conditional_marketing_mailer:*:*:*:*:*:wordpress:*:*" + ], + "conditional-shipping-for-woocommerce": [ + "cpe:2.3:a:wptrio:conditional_shipping_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "conference-scheduler": [ + "cpe:2.3:a:myceliumdesign:conference_scheduler:*:*:*:*:*:wordpress:*:*" + ], + "configurable-tag-cloud-widget": [ + "cpe:2.3:a:configurable_tag_cloud_project:configurable_tag_cloud:*:*:*:*:*:wordpress:*:*" + ], + "confirm-data": [ + "cpe:2.3:a:unihost:confirm_data:*:*:*:*:*:wordpress:*:*" + ], + "connect-daily-web-calendar": [ + "cpe:2.3:a:mhsoftware:wordpress_events_calendar_plugin:*:*:*:*:*:wordpress:*:*" + ], + "connections": [ + "cpe:2.3:a:connections-pro:connections_business_directory:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:zahmit_design:connections_business_directory_plugin:*:*:*:*:*:wordpress:*:*" + ], + "constant-contact-forms": [ + "cpe:2.3:a:constantcontact:constant_contact_forms:*:*:*:*:*:wordpress:*:*" + ], + "constant-contact-forms-by-mailmunch": [ + "cpe:2.3:a:mailmunch:constant_contact_forms:*:*:*:*:*:wordpress:*:*" + ], + "contact-bank": [ + "cpe:2.3:a:tech-banker:contact_bank:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-7": [ + "cpe:2.3:a:rocklobster:contact_form_7:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:rocklobster:contact_form_7_custom_validation:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-7-datepicker": [ + "cpe:2.3:a:contact-form-7-datepicker_project:contact-form-7-datepicker:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-7-integrations": [ + "cpe:2.3:a:contactus:contact_form_7_integrations:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-7-mailchimp-extension": [ + "cpe:2.3:a:renzojohnson:contact_form_7_extension_for_mailchimp:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-7-paypal-add-on": [ + "cpe:2.3:a:wpplugin:paypal_\\\u0026_stripe_add-on:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-7-simple-recaptcha": [ + "cpe:2.3:a:contact_form_7_captcha_project:contact_form_7_captcha:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-7-skins": [ + "cpe:2.3:a:cf7skins:contact_form_7_skins:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-7-sms-addon": [ + "cpe:2.3:a:mediaburst:contact_form_7_-_clockwork_sms:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:mediaburst:contact_form_7_sms:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-7-style": [ + "cpe:2.3:a:c7style:contact_form_7_style:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:cf7style:contact_form_7_style:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-7-to-database-extension": [ + "cpe:2.3:a:cfdbplugin:contact_form_db:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-add": [ + "cpe:2.3:a:web-settler:form_builder:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-advanced-database": [ + "cpe:2.3:a:contact_form_advanced_database_project:contact_form_advanced_database:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-builder": [ + "cpe:2.3:a:web-dorado:wp_form_builder:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-by-supsystic": [ + "cpe:2.3:a:supsystic:contact_form:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-cfdb7": [ + "cpe:2.3:a:ciphercoin:contact_form_7_database_addon:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-entries": [ + "cpe:2.3:a:crmperks:database_for_contact_form_7\\,_wpforms\\,_elementor_forms:*:*:*:*:*:*:*:*" + ], + "contact-form-generator": [ + "cpe:2.3:a:creative-solutions:contact_form_generator:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-integrated-with-google-maps": [ + "cpe:2.3:a:formget:contact_form_integrated_with_google_maps:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-maker": [ + "cpe:2.3:a:web-dorado:contact_form:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:web-dorado:contact_form_maker:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-manager": [ + "cpe:2.3:a:xyzscripts:contact_form_manager:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-multi": [ + "cpe:2.3:a:bestwebsoft:contact_form_multi:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-plugin": [ + "cpe:2.3:a:bestwebsoft:contact_form:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-ready": [ + "cpe:2.3:a:nickduncan:contact_form:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-submissions": [ + "cpe:2.3:a:contact_form_submissions_project:contact_form_submissions:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-to-any-api": [ + "cpe:2.3:a:itpathsolutions:contact_form_to_any_api:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-to-db": [ + "cpe:2.3:a:bestwebsoft:contact_form_to_db:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-to-email": [ + "cpe:2.3:a:codepeople:contact_form_email:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-with-a-meeting-scheduler-by-vcita": [ + "cpe:2.3:a:vcita:contact_form_builder_by_vcita:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-with-captcha": [ + "cpe:2.3:a:contact_form_with_captcha_project:contact_form_with_captcha:*:*:*:*:*:wordpress:*:*" + ], + "contact-form-x": [ + "cpe:2.3:a:contact_form_x_project:contact_form_x:*:*:*:*:*:wordpress:*:*" + ], + "contact-forms": [ + "cpe:2.3:a:cimatti:contact_forms:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:cimatti:wordpress_contact_forms:*:*:*:*:*:wordpress:*:*" + ], + "contact-forms-anti-spam": [ + "cpe:2.3:a:wpmaspik:maspik:*:*:*:*:*:wordpress:*:*" + ], + "contact-forms-builder": [ + "cpe:2.3:a:wpdevart:contact_form_builder:*:*:*:*:*:wordpress:*:*" + ], + "contact-us-page-contact-people": [ + "cpe:2.3:a:a3rev:contact_us_page_-_contact_people:*:*:*:*:*:wordpress:*:*" + ], + "content-audit": [ + "cpe:2.3:a:content_audit_project:content_audit:*:*:*:*:*:wordpress:*:*" + ], + "content-cards": [ + "cpe:2.3:a:content_cards_project:content_cards:*:*:*:*:*:wordpress:*:*" + ], + "content-control": [ + "cpe:2.3:a:code-atlantic:content_control:*:*:*:*:*:wordpress:*:*" + ], + "content-egg": [ + "cpe:2.3:a:keywordrush:content_egg:*:*:*:*:*:wordpress:*:*" + ], + "content-grabber": [ + "cpe:2.3:a:cybercraftit:content-grabber:*:*:*:*:*:wordpress:*:*" + ], + "content-mask": [ + "cpe:2.3:a:content_mask_project:content_mask:*:*:*:*:*:wordpress:*:*" + ], + "content-protector": [ + "cpe:2.3:a:passster_project:passter:*:*:*:*:*:wordpress:*:*" + ], + "content-repeater": [ + "cpe:2.3:a:content-repeater_project:content-repeater:*:*:*:*:*:wordpress:*:*" + ], + "content-staging": [ + "cpe:2.3:a:content_staging_project:content_staging:*:*:*:*:*:wordpress:*:*" + ], + "content-text-slider-on-post": [ + "cpe:2.3:a:content_text_slider_on_post_project:content_text_slider_on_post:*:*:*:*:*:wordpress:*:*" + ], + "content-views-query-and-display-post-page": [ + "cpe:2.3:a:contentviewspro:content_views:*:*:*:*:*:wordpress:*:*" + ], + "contentstudio": [ + "cpe:2.3:a:contentstudio:contentstudio:*:*:*:*:*:wordpress:*:*" + ], + "contest-gallery": [ + "cpe:2.3:a:contest-gallery:contest_gallery:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:contest-gallery:contest_gallery:*:*:*:*:pro:wordpress:*:*", + "cpe:2.3:a:contest_gallery:contest_gallery:*:*:*:*:*:wordpress:*:*" + ], + "contexture-page-security": [ + "cpe:2.3:a:contextureintl:page_security_\\\u0026_membership:*:*:*:*:*:wordpress:*:*" + ], + "continuous-image-carousel-with-lightbox": [ + "cpe:2.3:a:i13websolution:continuous_image_carosel_with_lightbox:*:*:*:*:*:wordpress:*:*" + ], + "controlled-admin-access": [ + "cpe:2.3:a:wpruby:controlled_admin_access:*:*:*:*:*:wordpress:*:*" + ], + "contus-hd-flv-player": [ + "cpe:2.3:a:contus:hd_flv_player:*:*:*:*:*:wordpress:*:*" + ], + "contus-video-comments": [ + "cpe:2.3:a:contussupport:contus-video-comments:*:*:*:*:*:wordpress:*:*" + ], + "contus-video-gallery": [ + "cpe:2.3:a:apptha:contus_video_gallery:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:apptha:wordpress_video_gallery:*:*:*:*:*:wordpress:*:*" + ], + "conversador": [ + "cpe:2.3:a:conversador_project:conversador:*:*:*:*:*:wordpress:*:*" + ], + "conversation-watson": [ + "cpe:2.3:a:ibm:chatbot_with_ibm_watson:*:*:*:*:*:wordpress:*:*" + ], + "conversational-forms": [ + "cpe:2.3:a:quantumcloud:conversational_forms_for_chatbot:*:*:*:*:*:wordpress:*:*" + ], + "convertbox-auto-embed": [ + "cpe:2.3:a:convertbox:convertbox_auto_embed:*:*:*:*:*:wordpress:*:*" + ], + "convertkit": [ + "cpe:2.3:a:convertkit:convertkit_-_email_marketing\\,_email_newsletter_and_landing_pages:*:*:*:*:*:wordpress:*:*" + ], + "cookie-bar": [ + "cpe:2.3:a:brontobytes:cookie_bar:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:cookie-bar_project:cookie-bar:*:*:*:*:*:wordpress:*:*" + ], + "cookie-law-info": [ + "cpe:2.3:a:cookielawinfo:gdpr_cookie_consent:*:*:*:*:*:wordpress:*:*" + ], + "cookie-notice": [ + "cpe:2.3:a:hu-manity:cookie_notice_\\\u0026_compliance_for_gdpr_\\/_ccpa:*:*:*:*:*:wordpress:*:*" + ], + "cookie-notice-and-consent-banner": [ + "cpe:2.3:a:gdprinfo:cookie_notice_\\\u0026_consent_banner_for_gdpr_\\\u0026_ccpa_compliance:*:*:*:*:*:wordpress:*:*" + ], + "cookie-notice-consent": [ + "cpe:2.3:a:christophrado:cookie_notice_\\\u0026_consent:*:*:*:*:*:wordpress:*:*" + ], + "cookiemonster": [ + "cpe:2.3:a:cookie_monster_project:cookie_monster:*:*:*:*:*:wordpress:*:*" + ], + "cookies-and-content-security-policy": [ + "cpe:2.3:a:followmedarling:cookies_and_content_security_policy:*:*:*:*:*:wordpress:*:*" + ], + "cool-tag-cloud": [ + "cpe:2.3:a:wpkube:cool_tag_cloud:*:*:*:*:*:wordpress:*:*" + ], + "cool-timeline": [ + "cpe:2.3:a:coolplugins:cool_timeline:*:*:*:*:*:wordpress:*:*" + ], + "coolclock": [ + "cpe:2.3:a:status301:coolclock:*:*:*:*:*:wordpress:*:*" + ], + "copy-delete-posts": [ + "cpe:2.3:a:copy-delete-posts:duplicate_post:*:*:*:*:*:wordpress:*:*" + ], + "copy-me": [ + "cpe:2.3:a:copy-me_project:copy-me:*:*:*:*:*:wordpress:*:*" + ], + "copy-or-move-comments": [ + "cpe:2.3:a:appjetty:copy_or_move_comments:*:*:*:*:*:wordpress:*:*" + ], + "copy-the-code": [ + "cpe:2.3:a:maheshwaghmare:copy_anything_to_clipboard:*:*:*:*:*:wordpress:*:*" + ], + "core-control": [ + "cpe:2.3:a:dd32:core_control:*:*:*:*:*:wordpress:*:*" + ], + "core-web-vitals-pagespeed-booster": [ + "cpe:2.3:a:magazine3:core_web_vitals_\\\u0026_pagespeed_booster:*:*:*:*:*:wordpress:*:*" + ], + "corner-ad": [ + "cpe:2.3:a:dwbooster:corner_ad:*:*:*:*:*:wordpress:*:*" + ], + "correos-express": [ + "cpe:2.3:a:correosexpress_project:correosexpress:*:*:*:*:*:wordpress:*:*" + ], + "coru-lfmember": [ + "cpe:2.3:a:marcorulicke:coru_lfmember:*:*:*:*:*:wordpress:*:*" + ], + "countdown-block": [ + "cpe:2.3:a:wpdeveloper:countdown_block:*:*:*:*:*:wordpress:*:*" + ], + "countdown-builder": [ + "cpe:2.3:a:edmonsoft:countdown_builder:*:*:*:*:*:wordpress:*:*" + ], + "countdown-wpdevart-extended": [ + "cpe:2.3:a:wpdevart:countdown_and_countup\\,_woocommerce_sales_timer:*:*:*:*:*:wordpress:*:*" + ], + "counter-box": [ + "cpe:2.3:a:wow-company:counter_box:*:*:*:*:*:wordpress:*:*" + ], + "coupon-creator": [ + "cpe:2.3:a:jesseeproductions:coupon_creator:*:*:*:*:*:wordpress:*:*" + ], + "coupon-zen": [ + "cpe:2.3:a:hasthemes:coupon_zen:*:*:*:*:*:wordpress:*:*" + ], + "cowidgets-elementor-addons": [ + "cpe:2.3:a:codeless:cowidgets_-_elementor:*:*:*:*:*:wordpress:*:*" + ], + "cp-appointment-calendar": [ + "cpe:2.3:a:codepeople:cp_appointment_calendar:*:*:*:*:*:wordpress:*:*" + ], + "cp-blocks": [ + "cpe:2.3:a:dwbooster:cp_blocks:*:*:*:*:*:wordpress:*:*" + ], + "cp-contact-form-with-paypal": [ + "cpe:2.3:a:codepeople:cp_contact_form_with_paypal:*:*:*:*:*:wordpress:*:*" + ], + "cp-image-store": [ + "cpe:2.3:a:dwbooster:cp_image_store_with_slideshow:*:*:*:*:*:wordpress:*:*" + ], + "cp-multi-view-calendar": [ + "cpe:2.3:a:cp_multi_view_event_calendar_project:cp_multi_view_event_calendar:*:*:*:*:wordpress:*:*:*", + "cpe:2.3:a:dwbooster:calendar_event_multi_view:*:*:*:*:*:wordpress:*:*" + ], + "cp-polls": [ + "cpe:2.3:a:codepeople:polls_cp:*:*:*:*:*:wordpress:*:*" + ], + "cpo-companion": [ + "cpe:2.3:a:machothemes:cpo_companion:*:*:*:*:*:wordpress:*:*" + ], + "cpo-content-types": [ + "cpe:2.3:a:wpchill:cpo_content_types:*:*:*:*:*:wordpress:*:*" + ], + "cpt-shortcode": [ + "cpe:2.3:a:anuragdeshmukh:cpt_shortcode_generator:*:*:*:*:*:wordpress:*:*" + ], + "cpt-speakers": [ + "cpe:2.3:a:9seeds:cpt_-_speakers:*:*:*:*:*:wordpress:*:*" + ], + "crafty-social-buttons": [ + "cpe:2.3:a:crafty_social_buttons_project:crafty_social_buttons:*:*:*:*:*:wordpress:*:*" + ], + "crayon-syntax-highlighter": [ + "cpe:2.3:a:crayon_syntax_highlighter_project:crayon_syntax_highlighter:*:*:*:*:*:wordpress:*:*" + ], + "crazy-bone": [ + "cpe:2.3:a:crazy_bone_project:crazy_bone:*:*:*:*:*:wordpress:*:*" + ], + "creative-mail-by-constant-contact": [ + "cpe:2.3:a:constantcontact:creative_mail:*:*:*:*:*:wordpress:*:*" + ], + "credit-tracker": [ + "cpe:2.3:a:labs64:credit_tracker:*:*:*:*:*:wordpress:*:*" + ], + "credova-financial": [ + "cpe:2.3:a:credova:financial:*:*:*:*:*:wordpress:*:*" + ], + "crelly-slider": [ + "cpe:2.3:a:crelly_slider_project:crelly_slider:*:*:*:*:*:wordpress:*:*" + ], + "crisp": [ + "cpe:2.3:a:crisp:live_chat:*:*:*:*:*:wordpress:*:*" + ], + "crm-customer-relationship-management-by-vcita": [ + "cpe:2.3:a:vcita:crm_and_lead_management_by_vcita:*:*:*:*:*:wordpress:*:*" + ], + "crm-memberships": [ + "cpe:2.3:a:ntzapps:crm_memberships:*:*:*:*:*:wordpress:*:*" + ], + "crm-perks-forms": [ + "cpe:2.3:a:crmperks:crm_perks_forms:*:*:*:*:*:wordpress:*:*" + ], + "crony": [ + "cpe:2.3:a:crony_cronjob_manager_project:crony_cronjob_manager:*:*:*:*:*:wordpress:*:*" + ], + "cross-linker": [ + "cpe:2.3:a:cross-linker_project:cross-linker:*:*:*:*:*:wordpress:*:*" + ], + "crossslide-jquery-plugin-for-wordpress": [ + "cpe:2.3:a:crossslide_jquery_project:crossslide_jquery:*:*:*:*:*:wordpress:*:*" + ], + "crypto-converter-widget": [ + "cpe:2.3:a:currencyratetoday:crypto_converter_widget:*:*:*:*:*:wordpress:*:*" + ], + "cryptocurrency-donation-box": [ + "cpe:2.3:a:adastracrypto:cryptocurrency_payment_\\\u0026_donation_box:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:cryptocurrency_payment_\\\u0026_donation_box_plugins:cryptocurrency_payment_\\\u0026_donation_box:*:*:*:*:*:wordpress:*:*" + ], + "cryptocurrency-price-ticker-widget": [ + "cpe:2.3:a:coolplugins:cryptocurrency_widgets:*:*:*:*:*:wordpress:*:*" + ], + "cryptocurrency-pricing-list": [ + "cpe:2.3:a:premium-themes:cryptocurrency_pricing_list_and_ticker:*:*:*:*:*:wordpress:*:*" + ], + "cryptocurrency-widgets-pack": [ + "cpe:2.3:a:blocksera:cryptocurrency_widgets_pack:*:*:*:*:*:wordpress:*:*" + ], + "css-adder-by-agence-press": [ + "cpe:2.3:a:agence-press:css_adder:*:*:*:*:*:wordpress:*:*" + ], + "css-javascript-toolbox": [ + "cpe:2.3:a:wipeoutmedia:css_\\\u0026_javascript_toolbox:*:*:*:*:*:wordpress:*:*" + ], + "csv-import-export": [ + "cpe:2.3:a:csv-import-export_project:csv-import-export:*:*:*:*:*:wordpress:*:*" + ], + "csv-importer": [ + "cpe:2.3:a:deniskobozev:csv_importer:*:*:*:*:*:wordpress:*:*" + ], + "ct-commerce": [ + "cpe:2.3:a:ujwolbastakoti:ct_commerce:*:*:*:*:*:wordpress:*:*" + ], + "ct-ultimate-gdpr": [ + "cpe:2.3:a:createit:ultimate_gdpr_\\\u0026_ccpa_compliance_toolkit:*:*:*:*:*:wordpress:*:*" + ], + "cta": [ + "cpe:2.3:a:inboundnow:call_to_action:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:inboundwp:calls_to_action:*:*:*:*:*:wordpress:*:*" + ], + "ctt-expresso-para-woocommerce": [ + "cpe:2.3:a:thisfunctional:ctt_expresso_para_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "cube-slider": [ + "cpe:2.3:a:webpsilon:cube_slider:*:*:*:*:*:wordpress:*:*" + ], + "currency-converter-calculator": [ + "cpe:2.3:a:currencyratetoday:currency_converter_calculator:*:*:*:*:*:wordpress:*:*" + ], + "currency-converter-widget": [ + "cpe:2.3:a:currencywiki:currency_converter_widget_-_exchange_rates:*:*:*:*:*:wordpress:*:*" + ], + "currency-switcher": [ + "cpe:2.3:a:pluginus:wordpress_currency_switcher:*:*:*:*:professional:wordpress:*:*" + ], + "currency-switcher-woocommerce": [ + "cpe:2.3:a:wpwham:currency_switcher_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "current-menu-item-for-custom-post-types": [ + "cpe:2.3:a:rolandmurg:current_menu_item_for_custom_post_types:*:*:*:*:*:wordpress:*:*" + ], + "curtain": [ + "cpe:2.3:a:curtain_project:curtain:*:*:*:*:*:wordpress:*:*" + ], + "custom-404-pro": [ + "cpe:2.3:a:kunalnagar:custom_404_pro:*:*:*:*:*:wordpress:*:*" + ], + "custom-admin-login-styler-wpzest": [ + "cpe:2.3:a:wpzest:custom_admin_login_page_\\|_wpzest_plugin:*:*:*:*:*:wordpress:*:*" + ], + "custom-admin-page": [ + "cpe:2.3:a:bestwebsoft:custom_admin:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:bestwebsoft:custom_admin_page:*:*:*:*:*:wordpress:*:*" + ], + "custom-banners": [ + "cpe:2.3:a:goldplugins:custom_banners:*:*:*:*:*:wordpress:*:*" + ], + "custom-content-shortcode": [ + "cpe:2.3:a:custom_content_shortcode_project:custom_content_shortcode:*:*:*:*:*:wordpress:*:*" + ], + "custom-content-type-manager": [ + "cpe:2.3:a:custom_content_type_manager_project:custom_content_type_manager:*:*:*:*:*:wordpress:*:*" + ], + "custom-css": [ + "cpe:2.3:a:wpfactory:custom_css\\,_js_\\\u0026_php:*:*:*:*:*:wordpress:*:*" + ], + "custom-css-js": [ + "cpe:2.3:a:silkypress:simple_custom_css_and_js:*:*:*:*:*:wordpress:*:*" + ], + "custom-css-js-php": [ + "cpe:2.3:a:flippercode:custom_css-js-php:*:*:*:*:*:wordpress:*:*" + ], + "custom-css-pro": [ + "cpe:2.3:a:yellowpencil:custom_css_pro:*:*:*:*:*:wordpress:*:*" + ], + "custom-dashboard-widgets": [ + "cpe:2.3:a:custom_dashboard_widgets_project:custom_dashboard_widgets:*:*:*:*:*:wordpress:*:*" + ], + "custom-facebook-feed": [ + "cpe:2.3:a:smashballoon:smash_balloon_social_post_feed:*:*:*:*:*:wordpress:*:*" + ], + "custom-field-for-wp-job-manager": [ + "cpe:2.3:a:custom_field_for_wp_job_manager_project:custom_field_for_wp_job_manager:*:*:*:*:*:wordpress:*:*" + ], + "custom-field-suite": [ + "cpe:2.3:a:custom_field_suite_project:custom_field_suite:*:*:*:*:*:wordpress:*:*" + ], + "custom-field-template": [ + "cpe:2.3:a:wpgogo:custom_field_template:*:*:*:*:*:wordpress:*:*" + ], + "custom-fields-search": [ + "cpe:2.3:a:bestwebsoft:custom_fields_search:*:*:*:*:*:wordpress:*:*" + ], + "custom-font-uploader": [ + "cpe:2.3:a:wbcomdesigns:custom_font_uploader:*:*:*:*:*:wordpress:*:*" + ], + "custom-global-variables": [ + "cpe:2.3:a:newtarget:custom_global_variables:*:*:*:*:*:wordpress:*:*" + ], + "custom-header-images": [ + "cpe:2.3:a:blackbam:custom_header_images:*:*:*:*:*:wordpress:*:*" + ], + "custom-landing-pages-leadmagic": [ + "cpe:2.3:a:metagauss:leadmagic:*:*:*:*:*:wordpress:*:*" + ], + "custom-login-admin-front-end-css-with-multisite-support": [ + "cpe:2.3:a:millionclues:custom_login_admin_front-end_css:*:*:*:*:*:wordpress:*:*" + ], + "custom-map": [ + "cpe:2.3:a:webdesi9:custom_map:*:*:*:*:*:wordpress:*:*" + ], + "custom-my-account-for-woocommerce": [ + "cpe:2.3:a:phoeniixx:custom_my_account_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "custom-options-plus": [ + "cpe:2.3:a:leocaseiro:custom_options_plus:*:*:*:*:*:wordpress:*:*" + ], + "custom-post-type-cpt-cusom-taxonomy-ct-manager": [ + "cpe:2.3:a:custom_post_type_and_taxonomy_gui_manager_project:custom_post_type_and_taxonomy_gui_manager:*:*:*:*:*:wordpress:*:*" + ], + "custom-post-type-generator": [ + "cpe:2.3:a:custom_post_type_generator_project:custom_post_type_generator:*:*:*:*:*:wordpress:*:*" + ], + "custom-post-type-relations": [ + "cpe:2.3:a:custom_post_type_relations_project:custom_post_type_relations:*:*:*:*:*:wordpress:*:*" + ], + "custom-post-type-ui": [ + "cpe:2.3:a:webdevstudios:custom_post_type_ui:*:*:*:*:*:wordpress:*:*" + ], + "custom-post-view-generator": [ + "cpe:2.3:a:custom_post_view_generator_project:custom_post_view_generator:*:*:*:*:*:wordpress:*:*" + ], + "custom-registration-form-builder-with-submission-manager": [ + "cpe:2.3:a:metagauss:registrationmagic:*:*:*:*:*:wordpress:*:*" + ], + "custom-search-plugin": [ + "cpe:2.3:a:bestwebsoft:custom_search:*:*:*:*:*:wordpress:*:*" + ], + "custom-searchable-data-entry-system": [ + "cpe:2.3:a:custom_searchable_data_entry_system_project:custom_searchable_data_entry_system:*:*:*:*:*:wordpress:*:*" + ], + "custom-share-buttons-with-floating-sidebar": [ + "cpe:2.3:a:wp-experts:custom_share_buttons_with_floating_sidebar:*:*:*:*:*:wordpress:*:*" + ], + "custom-sidebars": [ + "cpe:2.3:a:wpmudev:custom_sidebars:*:*:*:*:*:wordpress:*:*" + ], + "custom-simple-rss": [ + "cpe:2.3:a:custom_simple_rss_project:custom_simple_rss:*:*:*:*:*:wordpress:*:*" + ], + "custom-sub-menus": [ + "cpe:2.3:a:custom-sub-menus_project:custom-sub-menus:*:*:*:*:*:wordpress:*:*" + ], + "custom-tinymce-shortcode-button": [ + "cpe:2.3:a:custom_tinymce_shortcode_button_project:custom_tinymce_shortcode_button:*:*:*:*:*:wordpress:*:*" + ], + "custom-twitter-feeds": [ + "cpe:2.3:a:smashballoon:custom_twitter_feeds:*:*:*:*:*:wordpress:*:*" + ], + "customer-area": [ + "cpe:2.3:a:marvinlabs:wp_customer_area:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wp-customerarea:wp_customer_area:*:*:*:*:*:wordpress:*:*" + ], + "customer-reviews-woocommerce": [ + "cpe:2.3:a:cusrev:customer_reviews_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "customize-login-image": [ + "cpe:2.3:a:apasionados:customize_login_image:*:*:*:*:*:wordpress:*:*" + ], + "customizer-export-import": [ + "cpe:2.3:a:fastlinemedia:customizer_export\\/import:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpbeaverbuilder:customizer_export\\/import:*:*:*:*:*:wordpress:*:*" + ], + "cybersoldier": [ + "cpe:2.3:a:webbigt:cybersoldier:*:*:*:*:*:wordpress:*:*" + ], + "cyberus-key": [ + "cpe:2.3:a:cyberuslabs:cyberus_key:*:*:*:*:*:wordpress:*:*" + ], + "cyr3lat": [ + "cpe:2.3:a:cyr_to_lat_project:cyr_to_lat:*:*:*:*:*:wordpress:*:*" + ], + "cysteme-finder": [ + "cpe:2.3:a:cysteme:cysteme-finder:*:*:*:*:*:wordpress:*:*" + ], + "daext-autolinks-manager": [ + "cpe:2.3:a:daext:autolinks_manager:*:*:*:*:*:wordpress:*:*" + ], + "daggerhart-openid-connect-generic": [ + "cpe:2.3:a:daggerhartlab:openid_connect_generic_client:*:*:*:*:*:wordpress:*:*" + ], + "daily-prayer-time-for-mosques": [ + "cpe:2.3:a:daily_prayer_time_project:daily_prayer_time:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:mmrs151:daily_prayer_time:*:*:*:*:*:wordpress:*:*" + ], + "dans-gcal": [ + "cpe:2.3:a:dandulaney:dan\\'s_embedder_for_google_calendar:*:*:*:*:*:wordpress:*:*" + ], + "dark-mode": [ + "cpe:2.3:a:dark_mode_project:dark_mode:*:*:*:*:*:wordpress:*:*" + ], + "dashboard-to-do-list": [ + "cpe:2.3:a:arwebdesign:dashboard_to-do_list:*:*:*:*:*:wordpress:*:*" + ], + "dashboard-widgets-suite": [ + "cpe:2.3:a:plugin-planet:dashboard_widget_suite:*:*:*:*:*:wordpress:*:*" + ], + "dashicons-cpt": [ + "cpe:2.3:a:halgatewood:dashicons_\\+_custom_post_types:*:*:*:*:*:wordpress:*:*" + ], + "data-tables-generator-by-supsystic": [ + "cpe:2.3:a:supsystic:data_tables_generator:*:*:*:*:*:wordpress:*:*" + ], + "database-backups": [ + "cpe:2.3:a:database-backups_project:database-backups:*:*:*:*:*:wordpress:*:*" + ], + "database-cleaner": [ + "cpe:2.3:a:meowapps:database_cleaner:*:*:*:*:*:wordpress:*:*" + ], + "database-collation-fix": [ + "cpe:2.3:a:database_collation_fix_project:database_collation_fix:*:*:*:*:*:wordpress:*:*" + ], + "database-peek": [ + "cpe:2.3:a:database_peek_project:database_peek:*:*:*:*:*:wordpress:*:*" + ], + "dc-woocommerce-multi-vendor": [ + "cpe:2.3:a:multivendorx:multivendorx:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wc-marketplace:multivendor_marketplace_solution_for_woocommerce_-_wc_marketplace:*:*:*:*:*:wordpress:*:*" + ], + "dd-post-carousel": [ + "cpe:2.3:a:howardehrenberg:custom_post_carousels_with_owl:*:*:*:*:*:wordpress:*:*" + ], + "dearpdf-lite": [ + "cpe:2.3:a:dearhive:dearpdf:*:*:*:*:*:wordpress:*:*" + ], + "debug-assistant": [ + "cpe:2.3:a:wpindeed:debug_assistant:*:*:*:*:*:wordpress:*:*" + ], + "debug-bar": [ + "cpe:2.3:a:wordpress:debug_bar:*:*:*:*:*:wordpress:*:*" + ], + "debug-log-manager": [ + "cpe:2.3:a:bowo:debug_log_manager:*:*:*:*:*:wordpress:*:*" + ], + "debug-meta-data": [ + "cpe:2.3:a:debug_meta_data_project:debug_meta_data:*:*:*:*:*:wordpress:*:*" + ], + "decon-wp-sms": [ + "cpe:2.3:a:decondigital:decon_wp_sms:*:*:*:*:*:wordpress:*:*" + ], + "decorator-woocommerce-email-customizer": [ + "cpe:2.3:a:webtoffee:decorator:*:*:*:*:*:wordpress:*:*" + ], + "defender-security": [ + "cpe:2.3:a:wmpudev:defender_security:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpmudev:defender_security:*:*:*:*:*:wordpress:*:*" + ], + "delete-all-comments-easily": [ + "cpe:2.3:a:delete_all_comments_easily_project:delete_all_comments_easily:*:*:*:*:*:wordpress:*:*" + ], + "delete-duplicate-posts": [ + "cpe:2.3:a:cleverplugins:delete_duplicate_posts:*:*:*:*:*:wordpress:*:*" + ], + "delete-me": [ + "cpe:2.3:a:cmc3215:delete_me:*:*:*:*:*:wordpress:*:*" + ], + "delete-old-orders": [ + "cpe:2.3:a:deleteoldorders_project:delete_old_orders:*:*:*:*:*:wordpress:*:*" + ], + "delete-post-revisions-on-single-click": [ + "cpe:2.3:a:wapnepal:delete_post_revisions:*:*:*:*:*:wordpress:*:*" + ], + "delete-usermetas": [ + "cpe:2.3:a:joselazo:delete_usermeta:*:*:*:*:*:wordpress:*:*" + ], + "delhivery-logistics-courier": [ + "cpe:2.3:a:delhivery:logistics_courier:*:*:*:*:*:wordpress:*:*" + ], + "democracy-poll": [ + "cpe:2.3:a:wp-kama:democracy_poll:*:*:*:*:*:wordpress:*:*" + ], + "demomentsomtres-wp-export": [ + "cpe:2.3:a:demomentsomtres:export_posts_with_images:*:*:*:*:*:wordpress:*:*" + ], + "demon-image-annotation": [ + "cpe:2.3:a:superwhite:demon_image_annotation:*:*:*:*:*:wordpress:*:*" + ], + "deny-all-firewall": [ + "cpe:2.3:a:deny_all_firewall_project:deny_all_firewall:*:*:*:*:*:wordpress:*:*" + ], + "depicter": [ + "cpe:2.3:a:averta:depicter_slider:*:*:*:*:*:wordpress:*:*" + ], + "dethemekit-for-elementor": [ + "cpe:2.3:a:dethemekit_for_elementor_project:dethemekit_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "diary-availability-calendar": [ + "cpe:2.3:a:roosty:diary-availability-calendar:*:*:*:*:*:wordpress:*:*" + ], + "digiproveblog": [ + "cpe:2.3:a:digiprove:copyright_proof:*:*:*:*:*:wordpress:*:*" + ], + "digirisk": [ + "cpe:2.3:a:evarisk:digirisk:*:*:*:*:*:wordpress:*:*" + ], + "digital-publications-by-supsystic": [ + "cpe:2.3:a:supsystic:digital_publications_by_supsystic:*:*:*:*:*:wordpress:*:*" + ], + "directorist": [ + "cpe:2.3:a:wpwax:directorist:*:*:*:*:*:wordpress:*:*" + ], + "disable-comments": [ + "cpe:2.3:a:disable_comments:disable_comments_project:*:*:*:*:*:wordpress:*:*" + ], + "disable-update-notifications": [ + "cpe:2.3:a:disable_wordpress_update_notifications_and_auto-update_email_notifications_project:disable_wordpress_update_notifications_and_auto-update_email_notifications:*:*:*:*:*:wordpress:*:*" + ], + "display-custom-post": [ + "cpe:2.3:a:vikasvatsa:display_custom_post:*:*:*:*:*:wordpress:*:*" + ], + "display-metadata": [ + "cpe:2.3:a:display_post_meta\\,_term_meta\\,_comment_meta\\,_and_user_meta_project:display_post_meta\\,_term_meta\\,_comment_meta\\,_and_user_meta:*:*:*:*:*:wordpress:*:*" + ], + "display-post-metadata": [ + "cpe:2.3:a:display_post_metadata_project:display_post_metadata:*:*:*:*:*:wordpress:*:*" + ], + "display-widgets": [ + "cpe:2.3:a:display-widgets_project:display-widgets:*:*:*:*:*:wordpress:*:*" + ], + "disqus-comment-system": [ + "cpe:2.3:a:disqus:disqus_comment_system:*:*:*:*:*:wordpress:*:*" + ], + "disqus-conditional-load": [ + "cpe:2.3:a:disqus_conditional_load_project:disqus_conditional_load:*:*:*:*:*:wordpress:*:*" + ], + "ditty-news-ticker": [ + "cpe:2.3:a:metaphorcreations:ditty:*:*:*:*:*:wordpress:*:*" + ], + "divebook": [ + "cpe:2.3:a:divebook_project:divebook:*:*:*:*:*:wordpress:*:*" + ], + "dj-email-publish": [ + "cpe:2.3:a:dj_emailpublish_project:dj_emailpublish:*:*:*:*:*:wordpress:*:*" + ], + "dk-pricr-responsive-pricing-table": [ + "cpe:2.3:a:wpdarko:responsive_pricing_table:*:*:*:*:*:wordpress:*:*" + ], + "dmsguestbook": [ + "cpe:2.3:a:dmsguestbook_project:dmsguestbook:*:*:*:*:*:wordpress:*:*" + ], + "document-emberdder": [ + "cpe:2.3:a:bplugins:document_embedder:*:*:*:*:*:wordpress:*:*" + ], + "documentor-lite": [ + "cpe:2.3:a:documentor_project:documentor:*:*:*:*:*:wordpress:*:*" + ], + "dofollow-case-by-case": [ + "cpe:2.3:a:apasionados:dofollow_case_by_case:*:*:*:*:*:wordpress:*:*" + ], + "dokan-lite": [ + "cpe:2.3:a:wedevs:dokan:*:*:*:*:*:wordpress:*:*" + ], + "dologin": [ + "cpe:2.3:a:wpdo:dologin_security:*:*:*:*:*:wordpress:*:*" + ], + "domain-check": [ + "cpe:2.3:a:domaincheckplugin:domain_check:*:*:*:*:*:wordpress:*:*" + ], + "don8": [ + "cpe:2.3:a:don8_project:don8:*:*:*:*:*:wordpress:*:*" + ], + "donate-button": [ + "cpe:2.3:a:bestwebsoft:donate:*:*:*:*:*:wordpress:*:*" + ], + "donate-extra": [ + "cpe:2.3:a:donate_extra_project:donate_extra:*:*:*:*:*:wordpress:*:*" + ], + "donation-button": [ + "cpe:2.3:a:donation_button_project:donation_button:*:*:*:*:*:wordpress:*:*" + ], + "donation-thermometer": [ + "cpe:2.3:a:donation_thermometer_project:donation_thermometer:*:*:*:*:*:wordpress:*:*" + ], + "donations-for-woocommerce": [ + "cpe:2.3:a:wpzone:potent_donations_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "donorbox-donation-form": [ + "cpe:2.3:a:donorbox:donorbox:*:*:*:*:*:wordpress:*:*" + ], + "doofinder-for-woocommerce": [ + "cpe:2.3:a:doofinder:doofinder:*:*:*:*:*:wordpress:*:*" + ], + "double-opt-in-for-download": [ + "cpe:2.3:a:labwebdevelopment:double_opt-in_for_download:*:*:*:*:*:wordpress:*:*" + ], + "dovetail": [ + "cpe:2.3:a:rigorous-digital:dovetail:*:*:*:*:*:wordpress:*:*" + ], + "download-attachments": [ + "cpe:2.3:a:dfactory:download_attachments:*:*:*:*:*:wordpress:*:*" + ], + "download-manager": [ + "cpe:2.3:a:wpdownloadmanager:download_manager:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpdownloadmanager:wordpress_download_manager:*:*:*:*:*:wordpress:*:*" + ], + "download-monitor": [ + "cpe:2.3:a:never5:download_monitor:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpchill:download_monitor:*:*:*:*:*:wordpress:*:*" + ], + "download-plugin": [ + "cpe:2.3:a:metagauss:download_plugin:*:*:*:*:*:wordpress:*:*" + ], + "download-plugins-dashboard": [ + "cpe:2.3:a:wpfactory:download_plugins_and_themes_from_dashboard:*:*:*:*:*:wordpress:*:*" + ], + "download-theme": [ + "cpe:2.3:a:metagauss:download_theme:*:*:*:*:*:wordpress:*:*" + ], + "download-zip-attachments": [ + "cpe:2.3:a:download_zip_attachments_project:download_zip_attachments:*:*:*:*:*:wordpress:*:*" + ], + "drag-and-drop-multiple-file-upload-contact-form-7": [ + "cpe:2.3:a:codedropz:drag_and_drop_multiple_file_upload_-_contact_form_7:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:codedropz:drag_and_drop_multiple_file_upload_-_contact_form_7:*:*:*:*:pro:wordpress:*:*", + "cpe:2.3:a:codedropz:drag_and_drop_multiple_file_upload_-_contact_form_7:*:*:*:*:standard:wordpress:*:*" + ], + "drag-and-drop-multiple-file-upload-for-woocommerce": [ + "cpe:2.3:a:codedropz:drag_and_drop_multiple_file_upload_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "drawblog": [ + "cpe:2.3:a:drawblog_project:drawblog:*:*:*:*:*:wordpress:*:*" + ], + "droit-dark-mode": [ + "cpe:2.3:a:droitthemes:droit_dark_mode:*:*:*:*:*:wordpress:*:*" + ], + "droit-elementor-addons": [ + "cpe:2.3:a:droitthemes:droit_elementor_addons:*:*:*:*:*:wordpress:*:*" + ], + "drop-shadow-boxes": [ + "cpe:2.3:a:stevenhenty:drop_shadow_boxes:*:*:*:*:*:wordpress:*:*" + ], + "dropbox-folder-share": [ + "cpe:2.3:a:hynotech:dropbox_folder_share:*:*:*:*:*:wordpress:*:*" + ], + "dropdown-and-scrollable-text": [ + "cpe:2.3:a:webodid:dropdown_and_scrollable_text:*:*:*:*:*:wordpress:*:*" + ], + "dropdown-menu-widget": [ + "cpe:2.3:a:dropdown_menu_widget_project:dropdown_menu_widget:*:*:*:*:*:wordpress:*:*" + ], + "dsgvo-all-in-one-for-wp": [ + "cpe:2.3:a:dsgvo-for-wp:dsgvo_all_in_one_for_wp:*:*:*:*:*:wordpress:*:*" + ], + "dtabs": [ + "cpe:2.3:a:dtabs_project:dtabs:*:*:*:*:*:wordpress:*:*" + ], + "dukapress": [ + "cpe:2.3:a:dukapress:dukapress:*:*:*:*:*:wordpress:*:*" + ], + "dupeoff": [ + "cpe:2.3:a:dupeoff_project:dupeoff:*:*:*:*:*:wordpress:*:*" + ], + "duplicate-page": [ + "cpe:2.3:a:duplicatepro:duplicate_page:*:*:*:*:*:wordpress:*:*" + ], + "duplicate-post": [ + "cpe:2.3:a:duplicate_post_project:duplicate_post:*:*:*:*:*:wordpress:*:*" + ], + "duplicate-post-page-menu-custom-post-type": [ + "cpe:2.3:a:inqsys:duplicate_post_page_menu_\\\u0026_custom_post_type:*:*:*:*:*:wordpress:*:*" + ], + "duplicate-theme": [ + "cpe:2.3:a:mullerdigital:duplicate_theme:*:*:*:*:*:wordpress:*:*" + ], + "duplicate-wp-page-post": [ + "cpe:2.3:a:duplicate_page_and_post_project:duplicate_page_and_post:*:*:*:*:*:wordpress:*:*" + ], + "duplicator": [ + "cpe:2.3:a:snapcreek:duplicator:*:*:*:*:lite:wordpress:*:*", + "cpe:2.3:a:snapcreek:duplicator:*:*:*:*:pro:wordpress:*:*" + ], + "duracelltomi-google-tag-manager": [ + "cpe:2.3:a:gtm4wp:google_tag_manager:*:*:*:*:*:wordpress:*:*" + ], + "dw-promobar": [ + "cpe:2.3:a:designwall:dw_promobar:*:*:*:*:*:wordpress:*:*" + ], + "dw-question-answer": [ + "cpe:2.3:a:designwall:dw_question_\\\u0026_answer:*:*:*:*:pro:wordpress:*:*" + ], + "dwnldr": [ + "cpe:2.3:a:findshorty:dwnldr:*:*:*:*:*:wordpress:*:*" + ], + "dx-auto-save-images": [ + "cpe:2.3:a:daxiawp:dx-auto-save-images:*:*:*:*:*:wordpress:*:*" + ], + "dx-share-selection": [ + "cpe:2.3:a:devrix:dx_share_selection:*:*:*:*:*:wordpress:*:*" + ], + "dynamic-widgets": [ + "cpe:2.3:a:qurl:dynamic_widgets:*:*:*:*:*:wordpress:*:*" + ], + "e-unlocked-student-result": [ + "cpe:2.3:a:e_unlocked_-_student_result_project:e_unlocked_-_student_result:*:*:*:*:*:wordpress:*:*" + ], + "e2pdf": [ + "cpe:2.3:a:e2pdf:e2pdf:*:*:*:*:*:wordpress:*:*" + ], + "ean-for-woocommerce": [ + "cpe:2.3:a:wpfactory:ean_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "easing-slider": [ + "cpe:2.3:a:easing_slider:easing_slider:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:easing_slider_project:easing_slider:*:*:*:*:*:wordpress:*:*" + ], + "easy-accordion-free": [ + "cpe:2.3:a:techearty:easy_accordion:*:*:*:*:*:wordpress:*:*" + ], + "easy-appointments": [ + "cpe:2.3:a:easy_appointments_project:easy_appointments:*:*:*:*:*:wordpress:*:*" + ], + "easy-bootstrap-shortcodes": [ + "cpe:2.3:a:easy_bootstrap_shortcode_project:easy_bootstrap_shortcode:*:*:*:*:*:wordpress:*:*" + ], + "easy-call-now": [ + "cpe:2.3:a:dangngocbinh:easy_call_now_by_thikshare:*:*:*:*:*:wordpress:*:*" + ], + "easy-captcha": [ + "cpe:2.3:a:easy_captcha_project:easy_captcha:*:*:*:*:*:wordpress:*:*" + ], + "easy-career-openings": [ + "cpe:2.3:a:easy_career_openings_project:easy_career_openings:*:*:*:*:*:wordpress:*:*" + ], + "easy-contact-form-solution": [ + "cpe:2.3:a:formget:easy_contact_form_solution:*:*:*:*:*:wordpress:*:*" + ], + "easy-custom-auto-excerpt": [ + "cpe:2.3:a:tonjoostudio:easy_custom_auto_excerpt:*:*:*:*:*:wordpress:*:*" + ], + "easy-digital-downloads": [ + "cpe:2.3:a:sandhillsdev:easy_digital_downloads:*:*:*:*:*:wordpress:*:*" + ], + "easy-event-calendar": [ + "cpe:2.3:a:easy_event_calendar_project:easy_event_calendar:*:*:*:*:*:wordpress:*:*" + ], + "easy-facebook-like-box": [ + "cpe:2.3:a:easy_social_box_project:easy_social_box:*:*:*:*:*:wordpress:*:*" + ], + "easy-facebook-likebox": [ + "cpe:2.3:a:easysocialfeed:easy_social_feed:*:*:*:*:free:wordpress:*:*" + ], + "easy-fancybox": [ + "cpe:2.3:a:status301:easy_fancybox:*:*:*:*:*:wordpress:*:*" + ], + "easy-faq-with-expanding-text": [ + "cpe:2.3:a:easy_faq_with_expanding_text_project:easy_faq_with_expanding_text:*:*:*:*:*:wordpress:*:*" + ], + "easy-form-builder": [ + "cpe:2.3:a:whitestudio:easy_form_builder:*:*:*:*:*:wordpress:*:*" + ], + "easy-form-builder-by-bitware": [ + "cpe:2.3:a:easy-form-builder-by-bitware_project:easy-form-builder-by-bitware:*:*:*:*:*:wordpress:*:*" + ], + "easy-hide-login": [ + "cpe:2.3:a:ciphercoin:easy_hide_login:*:*:*:*:*:wordpress:*:*" + ], + "easy-login-woocommerce": [ + "cpe:2.3:a:xootix:login\\/signup_popup:*:*:*:*:*:wordpress:*:*" + ], + "easy-media-download": [ + "cpe:2.3:a:easy_media_download_project:easy_media_download:*:*:*:*:*:wordpress:*:*" + ], + "easy-media-gallery": [ + "cpe:2.3:a:ghozylab:gallery_-_photo_albums_-_portfolio:*:*:*:*:*:wordpress:*:*" + ], + "easy-modal": [ + "cpe:2.3:a:easy_modal_project:easy_modal:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:easymodal_project:easy_modal:*:*:*:*:*:wordpress:*:*" + ], + "easy-newsletter-signups": [ + "cpe:2.3:a:alphabpo:easy_newsletter_signups:*:*:*:*:*:wordpress:*:*" + ], + "easy-paypal-donation": [ + "cpe:2.3:a:wpplugin:accept_donations_with_paypal:*:*:*:*:*:wordpress:*:*" + ], + "easy-pdf-restaurant-menu-upload": [ + "cpe:2.3:a:easy_pdf_restaurant_menu_upload_project:easy_pdf_restaurant_menu_upload:*:*:*:*:*:wordpress:*:*" + ], + "easy-pie-coming-soon": [ + "cpe:2.3:a:snapcreek:ezp_coming_soon_page:*:*:*:*:*:wordpress:*:*" + ], + "easy-pricing-tables": [ + "cpe:2.3:a:fatcatapps:easy_pricing_tables:*:*:*:*:*:wordpress:*:*" + ], + "easy-property-listings": [ + "cpe:2.3:a:realestateconnected:easy_property_listings:*:*:*:*:*:wordpress:*:*" + ], + "easy-registration-forms": [ + "cpe:2.3:a:easyregistrationforms:easy_registration_forms:*:*:*:*:*:wordpress:*:*" + ], + "easy-side-tab-cta": [ + "cpe:2.3:a:accesspressthemes:easy_side_tab:*:*:*:*:*:wordpress:*:*" + ], + "easy-smooth-scroll-links": [ + "cpe:2.3:a:pootlepress:easy_smooth_scroll_links:*:*:*:*:*:wordpress:*:*" + ], + "easy-social-icons": [ + "cpe:2.3:a:cybernetikz:easy_social_icons:*:*:*:*:*:wordpress:*:*" + ], + "easy-student-results": [ + "cpe:2.3:a:easy_student_results_project:easy_student_results:*:*:*:*:*:wordpress:*:*" + ], + "easy-svg": [ + "cpe:2.3:a:benjaminzekavica:easy_svg_support:*:*:*:*:*:wordpress:*:*" + ], + "easy-table": [ + "cpe:2.3:a:easy_table_project:easy_table:*:*:*:*:*:wordpress:*:*" + ], + "easy-testimonial-manager": [ + "cpe:2.3:a:easy_testimonial_manager_project:easy_testimonial_manager:*:*:*:*:*:wordpress:*:*" + ], + "easy-testimonial-rotator": [ + "cpe:2.3:a:i13websolution:easy_testimonial_slider_and_form:*:*:*:*:*:wordpress:*:*" + ], + "easy-testimonials": [ + "cpe:2.3:a:goldplugins:easy_testimonials:*:*:*:*:*:wordpress:*:*" + ], + "easy-twitter-feeds": [ + "cpe:2.3:a:bplugins:easy_twitter_feed:*:*:*:*:*:wordpress:*:*" + ], + "easy-video-player": [ + "cpe:2.3:a:noorsplugin:easy_video_player:*:*:*:*:*:wordpress:*:*" + ], + "easy-wp-cleaner": [ + "cpe:2.3:a:nikunjsoni:easy_wp_cleaner:*:*:*:*:*:wordpress:*:*" + ], + "easy-wp-smtp": [ + "cpe:2.3:a:wp-ecommerce:easy_wp_smtp:*:*:*:*:*:wordpress:*:*" + ], + "easy2map": [ + "cpe:2.3:a:easy2map:easy2map:*:*:*:*:*:wordpress:*:*" + ], + "easy2map-photos": [ + "cpe:2.3:a:easy2map-photos_project:easy2map-photos:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:easy2map:easy2map-photos:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:steven_ellis:easy2map_photos:*:*:*:*:*:wordpress:*:*" + ], + "easyappointments": [ + "cpe:2.3:a:easyappointments:easy\\!appointments:*:*:*:*:*:wordpress:*:*" + ], + "easyjobs": [ + "cpe:2.3:a:easy.jobs:easy.jobs:*:*:*:*:*:wordpress:*:*" + ], + "easync-booking": [ + "cpe:2.3:a:syntactics:free_booking_plugin_for_hotels\\,_restaurant_and_car_rental:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:syntacticsinc:easync:*:*:*:*:*:wordpress:*:*" + ], + "easyrecipe": [ + "cpe:2.3:a:easyrecipe_project:easyrecipe:*:*:*:*:*:wordpress:*:*" + ], + "eazydocs": [ + "cpe:2.3:a:spider-themes:eazydocs:*:*:*:*:*:wordpress:*:*" + ], + "ebay-feeds-for-wordpress": [ + "cpe:2.3:a:winwar:wp_ebay_product_feeds:*:*:*:*:*:wordpress:*:*" + ], + "ebook-download": [ + "cpe:2.3:a:zedna_ebook_download_project:zedna_ebook_download:*:*:*:*:*:wordpress:*:*" + ], + "ebook-store": [ + "cpe:2.3:a:shopfiles:ebook_store:*:*:*:*:*:wordpress:*:*" + ], + "echosign": [ + "cpe:2.3:a:smackcoders:echo_sign:*:*:*:*:*:wordpress:*:*" + ], + "ecommerce-product-catalog": [ + "cpe:2.3:a:implecode:ecommerce_product_catalog:*:*:*:*:*:*:*:*", + "cpe:2.3:a:implecode:ecommerce_product_catalog:*:*:*:*:*:wordpress:*:*" + ], + "ecwid-shopping-cart": [ + "cpe:2.3:a:lightspeedhq:ecwid_ecommerce_shopping_cart:*:*:*:*:*:wordpress:*:*" + ], + "edd-recent-purchases": [ + "cpe:2.3:a:wow-company:easy_digital_downloads:*:*:*:*:*:wordpress:*:*" + ], + "edit-comments": [ + "cpe:2.3:a:edit_comments_project:edit_comments:*:*:*:*:*:wordpress:*:*" + ], + "edit-comments-xt": [ + "cpe:2.3:a:sw-guide:edit_comments_xt:*:*:*:*:*:wordpress:*:*" + ], + "editorial-calendar": [ + "cpe:2.3:a:editorial_calendar_project:editorial_calendar:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:zackgrossbart:editorial_calendar:*:*:*:*:*:wordpress:*:*" + ], + "educare": [ + "cpe:2.3:a:fixbd:educare:*:*:*:*:*:wordpress:*:*" + ], + "edwiser-bridge": [ + "cpe:2.3:a:edwiser:bridge:*:*:*:*:*:wordpress:*:*" + ], + "eelv-newsletter": [ + "cpe:2.3:a:eelv_newsletter_project:eelv_newsletter:*:*:*:*:*:wordpress:*:*" + ], + "eexamhall": [ + "cpe:2.3:a:online_exam_software_\\:_eexamhall_project:online_exam_software_\\:_eexamhall:*:*:*:*:*:wordpress:*:*" + ], + "eg-attachments": [ + "cpe:2.3:a:egeorjon:eg-attachments:*:*:*:*:*:wordpress:*:*" + ], + "elastic-email-sender": [ + "cpe:2.3:a:elasticemail:elastic_email_sender:*:*:*:*:*:wordpress:*:*" + ], + "elasticpress": [ + "cpe:2.3:a:10up:elasticpress:*:*:*:*:*:wordpress:*:*" + ], + "electric-studio-client-login": [ + "cpe:2.3:a:electric_studio_client_login_project:electric_studio_client_login:*:*:*:*:*:wordpress:*:*" + ], + "elegant-custom-fonts": [ + "cpe:2.3:a:breakdance:elegant_custom_fonts:*:*:*:*:*:wordpress:*:*" + ], + "elementor": [ + "cpe:2.3:a:elementor:elementor_page_builder:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:elementor:elementor_page_builder:*:*:*:*:pro:wordpress:*:*", + "cpe:2.3:a:elementor:page_builder:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:elementor:website_builder:*:*:*:*:*:wordpress:*:*" + ], + "elementor-pro": [ + "cpe:2.3:a:elementor:elementor_pro:*:*:*:*:*:wordpress:*:*" + ], + "elementskit-lite": [ + "cpe:2.3:a:wpmet:elements_kit_elementor_addons:*:*:*:*:*:wordpress:*:*" + ], + "emag-marketplace-connector": [ + "cpe:2.3:a:zitec:emag_marketplace_connector:*:*:*:*:*:wordpress:*:*" + ], + "email-address-encoder": [ + "cpe:2.3:a:tillkruss:email_address_encoder:*:*:*:*:*:wordpress:*:*" + ], + "email-artillery": [ + "cpe:2.3:a:email_artillery_project:email_artillery:*:*:*:*:*:wordpress:*:*" + ], + "email-encoder-bundle": [ + "cpe:2.3:a:jannisthuemmig:email_encoder:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wp-webhooks:email_encoder:*:*:*:*:*:wordpress:*:*" + ], + "email-log": [ + "cpe:2.3:a:email_log_project:email_log:*:*:*:*:*:wordpress:*:*" + ], + "email-newsletter": [ + "cpe:2.3:a:email-newsletter_project:email-newsletter:*:*:*:*:*:wordpress:*:*" + ], + "email-posts-to-subscribers": [ + "cpe:2.3:a:gopiplus:email_posts_to_subscribers:*:*:*:*:*:wordpress:*:*" + ], + "email-queue": [ + "cpe:2.3:a:bestwebsoft:email_queue:*:*:*:*:*:wordpress:*:*" + ], + "email-subscribe": [ + "cpe:2.3:a:i13websolution:email_subscription_popup:*:*:*:*:*:wordpress:*:*" + ], + "email-subscriber": [ + "cpe:2.3:a:email-subscriber_project:email-subscriber:*:*:*:*:*:wordpress:*:*" + ], + "email-subscribers": [ + "cpe:2.3:a:icegram:email_subscribers_\\\u0026_newsletters:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:icegram:icegram_express:*:*:*:*:*:wordpress:*:*" + ], + "email-users": [ + "cpe:2.3:a:email_users_project:email_users:*:*:*:*:*:wordpress:*:*" + ], + "embed-any-document": [ + "cpe:2.3:a:awsm:embed_any_document:*:*:*:*:*:wordpress:*:*" + ], + "embed-calendly-scheduling": [ + "cpe:2.3:a:embedcalendly:embed_calendly:*:*:*:*:*:wordpress:*:*" + ], + "embed-comment-images": [ + "cpe:2.3:a:embed_images_in_comments_project:embed_images_in_comments:*:*:*:*:*:wordpress:*:*" + ], + "embed-swagger": [ + "cpe:2.3:a:embed_swagger_project:embed_swagger:*:*:*:*:*:wordpress:*:*" + ], + "embed-youtube-video": [ + "cpe:2.3:a:geekwebsolution:embed_youtube_video:*:*:*:*:*:wordpress:*:*" + ], + "embedpress": [ + "cpe:2.3:a:wpdeveloper:embedpress:*:*:*:*:*:wordpress:*:*" + ], + "enable-accessibility": [ + "cpe:2.3:a:upress:enable_accessibility:*:*:*:*:*:wordpress:*:*" + ], + "enable-media-replace": [ + "cpe:2.3:a:shortpixel:enable_media_replace:*:*:*:*:*:wordpress:*:*" + ], + "enable-svg": [ + "cpe:2.3:a:room_34_creative_services:enable_svg:*:*:*:*:*:wordpress:*:*" + ], + "enable-svg-uploads": [ + "cpe:2.3:a:enable_svg_uploads_project:enable_svg_uploads:*:*:*:*:*:wordpress:*:*" + ], + "enable-svg-webp-ico-upload": [ + "cpe:2.3:a:ideastocode:enable_svg\\,_webp_\\\u0026_ico_upload:*:*:*:*:*:wordpress:*:*" + ], + "english-wp-admin": [ + "cpe:2.3:a:english_wordpress_admin_project:english_wordpress_admin:*:*:*:*:*:wordpress:*:*" + ], + "enhanced-e-commerce-for-woocommerce-store": [ + "cpe:2.3:a:conversios:google_analytics_integration_for_woocommerce:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:tatvic:conversios.io:*:*:*:*:*:wordpress:*:*" + ], + "enhanced-plugin-admin": [ + "cpe:2.3:a:infolific:enhanced_plugin_admin:*:*:*:*:*:wordpress:*:*" + ], + "enhanced-text-widget": [ + "cpe:2.3:a:themecheck:enhanced_text_widget:*:*:*:*:*:wordpress:*:*" + ], + "enhanced-tooltipglossary": [ + "cpe:2.3:a:cminds:tooltip_glossary:*:*:*:*:*:wordpress:*:*" + ], + "enqueue-anything": [ + "cpe:2.3:a:enqueue_anything_project:enqueue_anything:*:*:*:*:*:wordpress:*:*" + ], + "enquiry-quotation-for-woocommerce": [ + "cpe:2.3:a:piwebsolution:product_enquiry_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "envato-elements": [ + "cpe:2.3:a:envato:envato_elements:*:*:*:*:*:wordpress:*:*" + ], + "envira-gallery-lite": [ + "cpe:2.3:a:enviragallery:envira_gallery:*:*:*:*:lite:wordpress:*:*" + ], + "envo-extra": [ + "cpe:2.3:a:envothemes:envo_extra:*:*:*:*:*:wordpress:*:*" + ], + "eonet-manual-user-approve": [ + "cpe:2.3:a:xtendify:eonet_manual_user_approve:*:*:*:*:*:wordpress:*:*" + ], + "eps-301-redirects": [ + "cpe:2.3:a:webfactoryltd:301_redirects:*:*:*:*:*:wordpress:*:*" + ], + "erident-custom-login-and-dashboard": [ + "cpe:2.3:a:erident_custom_login_and_dashboard_project:erident_custom_login_and_dashboard:*:*:*:*:*:wordpress:*:*" + ], + "erp": [ + "cpe:2.3:a:wedevs:wp_erp:*:*:*:*:*:wordpress:*:*" + ], + "error-log-viewer": [ + "cpe:2.3:a:bestwebsoft:error_log_viewer:*:*:*:*:*:wordpress:*:*" + ], + "eshop": [ + "cpe:2.3:a:elfden:eshop_plugin:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:eshop_project:eshop:*:*:*:*:*:wordpress:*:*" + ], + "essential-addons-for-elementor-lite": [ + "cpe:2.3:a:wpdeveloper:essential_addons_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "essential-blocks": [ + "cpe:2.3:a:wpdeveloper:essential_blocks:*:*:*:*:*:wordpress:*:*" + ], + "essential-content-types": [ + "cpe:2.3:a:catchplugins:essential_content_types:*:*:*:*:*:wordpress:*:*" + ], + "essential-real-estate": [ + "cpe:2.3:a:g5plus:essential_real_estate:*:*:*:*:*:wordpress:*:*" + ], + "essential-widgets": [ + "cpe:2.3:a:catchplugins:essential_widgets:*:*:*:*:*:wordpress:*:*" + ], + "estatik": [ + "cpe:2.3:a:estatik:estatik:*:*:*:*:*:wordpress:*:*" + ], + "estatik-mortgage-calculator": [ + "cpe:2.3:a:estatik:estatik_mortgage_calculator:*:*:*:*:*:wordpress:*:*" + ], + "etsy-shop": [ + "cpe:2.3:a:etsy_shop_project:etsy_shop:*:*:*:*:*:wordpress:*:*" + ], + "eu-cookie-law": [ + "cpe:2.3:a:eu_cookie_law_project:eu_cookie_law:*:*:*:*:*:wordpress:*:*" + ], + "eupago-gateway-for-woocommerce": [ + "cpe:2.3:a:eupago:eupago_gateway_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "evaluate": [ + "cpe:2.3:a:evaluate_project:evaluate:*:*:*:*:*:wordpress:*:*" + ], + "event-calendar-wd": [ + "cpe:2.3:a:web-dorado:event_calendar_wd:*:*:*:*:*:wordpress:*:*" + ], + "event-espresso-decaf": [ + "cpe:2.3:a:eventespresso:event_espresso:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:eventespresso:event_espresso_4_decaf:*:*:*:*:*:wordpress:*:*" + ], + "event-espresso-free": [ + "cpe:2.3:a:eventespresso:event_espresso:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:eventespresso:event_espresso:*:*:*:*:free:wordpress:*:*", + "cpe:2.3:a:eventespresso:event_espresso_lite:*:*:*:*:*:wordpress:*:*" + ], + "event-geek": [ + "cpe:2.3:a:event_geek_project:event_geek:*:*:*:*:*:wordpress:*:*" + ], + "event-list": [ + "cpe:2.3:a:event_list_project:event_list:*:*:*:*:*:wordpress:*:*" + ], + "event-monster": [ + "cpe:2.3:a:awplife:event_monster:*:*:*:*:*:wordpress:*:*" + ], + "event-notifier": [ + "cpe:2.3:a:event_notifier_project:event_notifier:*:*:*:*:*:wordpress:*:*" + ], + "event-post": [ + "cpe:2.3:a:avecnous:event_post:*:*:*:*:*:wordpress:*:*" + ], + "event-registration-calendar-by-vcita": [ + "cpe:2.3:a:vcita:event_registration_calendar_by_vcita:*:*:*:*:*:wordpress:*:*" + ], + "event-tickets": [ + "cpe:2.3:a:tri:event_tickets:*:*:*:*:*:wordpress:*:*" + ], + "event-tickets-with-ticket-scanner": [ + "cpe:2.3:a:vollstart:event_tickets_with_ticket_scanner:*:*:*:*:*:wordpress:*:*" + ], + "eventify": [ + "cpe:2.3:a:eventify_project:eventify:*:*:*:*:*:wordpress:*:*" + ], + "eventon-lite": [ + "cpe:2.3:a:myeventon:eventon-lite:*:*:*:*:*:wordpress:*:*" + ], + "eventprime-event-calendar-management": [ + "cpe:2.3:a:metagauss:eventprime:*:*:*:*:*:wordpress:*:*" + ], + "eventr": [ + "cpe:2.3:a:eventr_project:eventr:*:*:*:*:*:wordpress:*:*" + ], + "events-addon-for-elementor": [ + "cpe:2.3:a:nicheaddons:events_addon_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "events-made-easy": [ + "cpe:2.3:a:e-dynamics:events_made_easy:*:*:*:*:*:wordpress:*:*" + ], + "events-manager": [ + "cpe:2.3:a:wp-events-plugin:events_manager:*:*:*:*:*:wordpress:*:*" + ], + "ever-compare": [ + "cpe:2.3:a:hasthemes:ever_compare:*:*:*:*:*:wordpress:*:*" + ], + "everest-admin-theme-lite": [ + "cpe:2.3:a:accesspressthemes:everest_admin_theme_lite:*:*:*:*:*:wordpress:*:*" + ], + "everest-backup": [ + "cpe:2.3:a:everestthemes:everest_backup:*:*:*:*:*:wordpress:*:*" + ], + "everest-coming-soon-lite": [ + "cpe:2.3:a:accesspressthemes:everest_coming_soon_lite:*:*:*:*:*:wordpress:*:*" + ], + "everest-comment-rating-lite": [ + "cpe:2.3:a:accesspressthemes:everest_comment_rating_lite:*:*:*:*:*:wordpress:*:*" + ], + "everest-counter-lite": [ + "cpe:2.3:a:accesspressthemes:everest_counter_lite:*:*:*:*:*:wordpress:*:*" + ], + "everest-faq-manager-lite": [ + "cpe:2.3:a:accesspressthemes:everest_faq_manager_lite:*:*:*:*:*:wordpress:*:*" + ], + "everest-gallery-lite": [ + "cpe:2.3:a:accesspressthemes:everest_gallery_lite:*:*:*:*:*:wordpress:*:*" + ], + "everest-google-places-reviews-lite": [ + "cpe:2.3:a:accesspressthemes:everest_gplaces_business_reviews:*:*:*:*:*:wordpress:*:*" + ], + "everest-review-lite": [ + "cpe:2.3:a:accesspressthemes:everest_review_lite:*:*:*:*:*:wordpress:*:*" + ], + "everest-tab-lite": [ + "cpe:2.3:a:accesspressthemes:everest_tab_lite:*:*:*:*:*:wordpress:*:*" + ], + "everest-timeline-lite": [ + "cpe:2.3:a:accesspressthemes:everest_timeline_lite:*:*:*:*:*:wordpress:*:*" + ], + "ewww-image-optimizer": [ + "cpe:2.3:a:ewww:image_optimizer:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:ewww_image_optimizer_plugin_project:ewww_image_optimizer_plugin:*:*:*:*:*:wordpress:*:*" + ], + "exchange-addon-exporter": [ + "cpe:2.3:a:ithemes:ithemes_exchange:*:*:*:*:*:wordpress:*:*" + ], + "exclusive-addons-for-elementor": [ + "cpe:2.3:a:devscred:exclusive_addons_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "exit-intent-popups-by-optimonk": [ + "cpe:2.3:a:optimonk:optimonk\\:popups\\,_personalization_\\\u0026_a\\/b_testing:*:*:*:*:*:wordpress:*:*" + ], + "exmage-wp-image-links": [ + "cpe:2.3:a:villatheme:exmage:*:*:*:*:*:wordpress:*:*" + ], + "expand-maker": [ + "cpe:2.3:a:edmonsoft:read_more_\\\u0026_accordion:*:*:*:*:*:wordpress:*:*" + ], + "export-all-urls": [ + "cpe:2.3:a:atlasgondal:export_all_urls:*:*:*:*:*:wordpress:*:*" + ], + "export-post-info": [ + "cpe:2.3:a:apasionados:export_post_info:*:*:*:*:*:wordpress:*:*" + ], + "export-users-to-csv": [ + "cpe:2.3:a:export_users_to_csv_project:export_users_to_csv:*:*:*:*:*:wordpress:*:*" + ], + "export-woocommerce": [ + "cpe:2.3:a:wpfactory:products\\,_order_\\\u0026_customers_export_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "export-woocommerce-customer-list": [ + "cpe:2.3:a:piwebsolution:export_customers_list_csv_for_woocommerce:*:*:*:*:*:*:*:*" + ], + "export-wp-page-to-static-html": [ + "cpe:2.3:a:myrecorp:export_wp_page_to_static_html\\/css:*:*:*:*:*:wordpress:*:*" + ], + "exportfeed-for-woocommerce-google-product-feed": [ + "cpe:2.3:a:dpl:sync_woocommerce_product_feed_to_google_shopping:*:*:*:*:*:wordpress:*:*" + ], + "exportfeed-for-woocommerce-product-to-etsy": [ + "cpe:2.3:a:exportfeed:woocommerce_etsy_integration:*:*:*:*:*:wordpress:*:*" + ], + "exports-and-reports": [ + "cpe:2.3:a:exports_and_reports_project:exports_and_reports:*:*:*:*:*:wordpress:*:*" + ], + "exquisite-paypal-donation": [ + "cpe:2.3:a:exquisite_paypal_donation_project:exquisite_paypal_donation:*:*:*:*:*:wordpress:*:*" + ], + "extensions-for-cf7": [ + "cpe:2.3:a:hasthemes:extensions_for_cf7:*:*:*:*:*:wordpress:*:*" + ], + "extensive-vc-addon": [ + "cpe:2.3:a:wprealize:extensive_vc_addons_for_wpbakery_page_builder:*:*:*:*:*:wordpress:*:*" + ], + "external-media": [ + "cpe:2.3:a:external_media_project:external_media:*:*:*:*:*:wordpress:*:*" + ], + "external-videos": [ + "cpe:2.3:a:gingertech:external_videos:*:*:*:*:*:wordpress:*:*" + ], + "extra-product-options-for-woocommerce": [ + "cpe:2.3:a:actpro:extra_product_options_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "extra-user-details": [ + "cpe:2.3:a:vadimk:extra_user_details:*:*:*:*:*:wordpress:*:*" + ], + "ezoic-integration": [ + "cpe:2.3:a:ezoic:ezoic:*:*:*:*:*:wordpress:*:*" + ], + "ezpz-one-click-backup": [ + "cpe:2.3:a:ezpz-one-click-backup_project:ezpz-one-click-backup:*:*:*:*:*:wordpress:*:*" + ], + "facebook-button-plugin": [ + "cpe:2.3:a:bestwebsoft:facebook_button:*:*:*:*:*:wordpress:*:*" + ], + "facebook-by-weblizar": [ + "cpe:2.3:a:weblizar:social_likebox_\\\u0026_feed:*:*:*:*:*:wordpress:*:*" + ], + "facebook-conversion-pixel": [ + "cpe:2.3:a:fatcatapps:pixel_cat:*:*:*:*:*:wordpress:*:*" + ], + "facebook-for-woocommerce": [ + "cpe:2.3:a:facebook:facebook_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "facebook-page-feed-graph-api": [ + "cpe:2.3:a:mongoosemarketplace:mongoose_page_plugin:*:*:*:*:*:wordpress:*:*" + ], + "facebook-wall-and-social-integration": [ + "cpe:2.3:a:facebook-wall-and-social-integration_project:facebook-wall-and-social-integration:*:*:*:*:*:wordpress:*:*" + ], + "fancier-author-box": [ + "cpe:2.3:a:thematosoup:fancier_author_box:*:*:*:*:*:wordpress:*:*" + ], + "fancy-facebook-comments": [ + "cpe:2.3:a:heateor:fancy_comments:*:*:*:*:*:wordpress:*:*" + ], + "fancy-gallery": [ + "cpe:2.3:a:fancy_gallery_project:fancy_gallery:*:*:*:*:*:wordpress:*:*" + ], + "fancybox-for-wordpress": [ + "cpe:2.3:a:colorlib:fancybox:*:*:*:*:*:wordpress:*:*" + ], + "faq-builder-ays": [ + "cpe:2.3:a:ays-pro:faq_builder:*:*:*:*:*:wordpress:*:*" + ], + "far-future-expiry-header": [ + "cpe:2.3:a:tipsandtricks-hq:far_future_expiry_header:*:*:*:*:*:wordpress:*:*" + ], + "fareharbor": [ + "cpe:2.3:a:fareharbor:fareharbor:*:*:*:*:*:wordpress:*:*" + ], + "fast-custom-social-share-by-codebard": [ + "cpe:2.3:a:codebard:fast_custom_social_share:*:*:*:*:*:wordpress:*:*" + ], + "fast-flow-dashboard": [ + "cpe:2.3:a:fastflow:fastflow:*:*:*:*:*:wordpress:*:*" + ], + "fast-search-powered-by-solr": [ + "cpe:2.3:a:fast-search-powered-by-solr_project:fast-search-powered-by-solr:*:*:*:*:*:wordpress:*:*" + ], + "fast-velocity-minify": [ + "cpe:2.3:a:fastvelocity:minify:*:*:*:*:*:wordpress:*:*" + ], + "fast-wp-speed": [ + "cpe:2.3:a:fastwpspeed:fast_wp_speed:*:*:*:*:*:wordpress:*:*" + ], + "fastdup": [ + "cpe:2.3:a:ninjateam:fastdup:*:*:*:*:*:wordpress:*:*" + ], + "fastly": [ + "cpe:2.3:a:fastly:fastly:*:*:*:*:*:wordpress:*:*" + ], + "fathom-analytics": [ + "cpe:2.3:a:conva:fathom_analytics:*:*:*:*:*:wordpress:*:*" + ], + "fattura24": [ + "cpe:2.3:a:fattura24:fattura24:*:*:*:*:*:wordpress:*:*" + ], + "favicon-by-realfavicongenerator": [ + "cpe:2.3:a:realfavicongenerator:favicon_by_realfavicongenerator:*:*:*:*:*:wordpress:*:*" + ], + "favicon-switcher": [ + "cpe:2.3:a:favicon-switcher_project:favicon-switcher:*:*:*:*:*:wordpress:*:*" + ], + "favorites": [ + "cpe:2.3:a:favorites_project:favorites:*:*:*:*:*:wordpress:*:*" + ], + "feather-login-page": [ + "cpe:2.3:a:featherplugins:custom_login_page_\\|_temporary_users_\\|_rebrand_login_\\|_login_captcha:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:featherplugins:feather_login_page:*:*:*:*:*:wordpress:*:*" + ], + "feature-comments": [ + "cpe:2.3:a:pippinsplugins:featured_comments:*:*:*:*:*:wordpress:*:*" + ], + "featured-image-caption": [ + "cpe:2.3:a:christiaanconover:featured_image_caption:*:*:*:*:*:wordpress:*:*" + ], + "featured-image-from-url": [ + "cpe:2.3:a:fifu:featured_image_from_url:*:*:*:*:*:wordpress:*:*" + ], + "feed-changer": [ + "cpe:2.3:a:wp-master:feed_changer_\\\u0026_remover:*:*:*:*:*:wordpress:*:*" + ], + "feed-instagram-lite": [ + "cpe:2.3:a:ghozylab:gallery_for_social_photo:*:*:*:*:*:wordpress:*:*" + ], + "feed-them-social": [ + "cpe:2.3:a:slickremix:feed_them_social:*:*:*:*:*:wordpress:*:*" + ], + "feedburner-alternative-and-rss-redirect": [ + "cpe:2.3:a:inisev:rss_redirect_\\\u0026_feedburner_alternative:*:*:*:*:*:wordpress:*:*" + ], + "feedwordpress": [ + "cpe:2.3:a:feedwordpress_project:feedwordpress:*:*:*:*:*:wordpress:*:*" + ], + "feedzy-rss-feeds": [ + "cpe:2.3:a:themeisle:rss_aggregator_by_feedzy:*:*:*:*:*:wordpress:*:*" + ], + "fgallery": [ + "cpe:2.3:a:fgallery_project:fgallery:*:*:*:*:*:wordpress:*:*" + ], + "file-away": [ + "cpe:2.3:a:file_away_project:file_away:*:*:*:*:*:wordpress:*:*" + ], + "file-gallery": [ + "cpe:2.3:a:file_gallery_project:file_gallery:*:*:*:*:*:wordpress:*:*" + ], + "file-manager": [ + "cpe:2.3:a:bitapps:file_manager:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:giribaz:file_manager:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpjos:library_file_manager:*:*:*:*:*:wordpress:*:*" + ], + "file-manager-advanced": [ + "cpe:2.3:a:advancedfilemanager:advanced_file_manager:*:*:*:*:*:wordpress:*:*" + ], + "filebird": [ + "cpe:2.3:a:ninjateam:filebird:*:*:*:*:*:wordpress:*:*" + ], + "filedownload": [ + "cpe:2.3:a:filedownload_project:filedownload:*:*:*:*:*:wordpress:*:*" + ], + "fileorganizer": [ + "cpe:2.3:a:fileorganizer:fileorganizer:*:*:*:*:*:wordpress:*:*" + ], + "filester": [ + "cpe:2.3:a:ninjateam:filester:*:*:*:*:*:wordpress:*:*" + ], + "fileviewer": [ + "cpe:2.3:a:fileviewer_project:fileviewer:*:*:*:*:*:wordpress:*:*" + ], + "filr-protection": [ + "cpe:2.3:a:filr_project:filr:*:*:*:*:*:wordpress:*:*" + ], + "filter-custom-fields-taxonomies-light": [ + "cpe:2.3:a:websupporter_filter_custom_fields_\\\u0026_taxonomies_light_project:websupporter_filter_custom_fields_\\\u0026_taxonomies_light:*:*:*:*:*:wordpress:*:*" + ], + "filter-portfolio-gallery": [ + "cpe:2.3:a:phoeniixx:filter_portfolio_gallery:*:*:*:*:*:wordpress:*:*" + ], + "final-tiles-grid-gallery-lite": [ + "cpe:2.3:a:machothemes:image_photo_gallery_final_tiles_grid:*:*:*:*:*:wordpress:*:*" + ], + "find-and-replace-all": [ + "cpe:2.3:a:find_and_replace_all_project:find_and_replace_all:*:*:*:*:*:wordpress:*:*" + ], + "find-any-think": [ + "cpe:2.3:a:wpmk_ajax_finder_project:wpmk_ajax_finder:*:*:*:*:*:wordpress:*:*" + ], + "find-my-blocks": [ + "cpe:2.3:a:find_my_blocks_project:find_my_blocks:*:*:*:*:*:wordpress:*:*" + ], + "fitness-calculators": [ + "cpe:2.3:a:codeinitiator:fitness_calculators:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:codeinitiator:fitness_calculators_plugin:*:*:*:*:*:wordpress:*:*" + ], + "five-minute-webshop": [ + "cpe:2.3:a:five_minute_webshop_project:five_minute_webshop:*:*:*:*:*:wordpress:*:*" + ], + "fl3r-feelbox": [ + "cpe:2.3:a:fl3r-feelbox_project:fl3r-feelbox:*:*:*:*:*:wordpress:*:*" + ], + "flash-album-gallery": [ + "cpe:2.3:a:codeasily:grand_flagallery:*:*:*:*:*:wordpress:*:*" + ], + "flat-preloader": [ + "cpe:2.3:a:flat_preloader_project:flat_preloader:*:*:*:*:*:wordpress:*:*" + ], + "flexi": [ + "cpe:2.3:a:odude:flexi:*:*:*:*:*:wordpress:*:*" + ], + "flexi-quote-rotator": [ + "cpe:2.3:a:flexi_quote_rotator_project:flexi_quote_rotator:*:*:*:*:*:wordpress:*:*" + ], + "flexible-elementor-panel": [ + "cpe:2.3:a:webmat:flexible_elementor_panel:*:*:*:*:*:wordpress:*:*" + ], + "flickr-justified-gallery": [ + "cpe:2.3:a:flickr_justified_gallery_project:flickr_justified_gallery:*:*:*:*:*:wordpress:*:*" + ], + "flickr-rss": [ + "cpe:2.3:a:flickrrss_project:flickrrss:*:*:*:*:*:wordpress:*:*" + ], + "flightlog": [ + "cpe:2.3:a:zavedil:flightlog:*:*:*:*:*:wordpress:*:*" + ], + "float-menu": [ + "cpe:2.3:a:wow-company:float_menu:*:*:*:*:*:wordpress:*:*" + ], + "floating-action-button": [ + "cpe:2.3:a:floating_action_button_project:floating_action_button:*:*:*:*:*:wordpress:*:*" + ], + "floating-button": [ + "cpe:2.3:a:wow-company:floating_button:*:*:*:*:*:wordpress:*:*" + ], + "floating-div": [ + "cpe:2.3:a:floating_div_project:floating_div:*:*:*:*:*:wordpress:*:*" + ], + "floating-social-bar": [ + "cpe:2.3:a:floating_social_bar_project:floating_social_bar:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpbeginner:floating_social_bar:*:*:*:*:wordpress:*:*:*" + ], + "floating-social-media-icon": [ + "cpe:2.3:a:acurax:floating_social_media_icon:*:*:*:*:*:wordpress:*:*" + ], + "flog": [ + "cpe:2.3:a:flog_project:flog:*:*:*:*:*:*:*:*" + ], + "flower-delivery-by-florist-one": [ + "cpe:2.3:a:floristone:flower_delivery:*:*:*:*:*:wordpress:*:*" + ], + "flowpaper-lite-pdf-flipbook": [ + "cpe:2.3:a:flowpaper:flowpaper:*:*:*:*:*:wordpress:*:*" + ], + "flowplayer6-video-player": [ + "cpe:2.3:a:wphowto:flowplayer_video_player:*:*:*:*:*:wordpress:*:*" + ], + "fluent-crm": [ + "cpe:2.3:a:wpmanageninja:fluentcrm:*:*:*:*:*:wordpress:*:*" + ], + "fluent-security": [ + "cpe:2.3:a:wpmanageninja:fluentauth:*:*:*:*:*:wordpress:*:*" + ], + "fluent-smtp": [ + "cpe:2.3:a:wpmanageninja:fluentsmtp:*:*:*:*:*:wordpress:*:*" + ], + "fluent-support": [ + "cpe:2.3:a:wpmanageninja:fluent_support:*:*:*:*:*:wordpress:*:*" + ], + "fluentform": [ + "cpe:2.3:a:fluentforms:contact_form:*:*:*:*:*:wordpress:*:*" + ], + "fluentforms-pdf": [ + "cpe:2.3:a:wpmanageninja:pdf_generator_for_fluent_forms:*:*:*:*:*:wordpress:*:*" + ], + "fluid-responsive-slideshow": [ + "cpe:2.3:a:tonjoostudio:fluid-responsive-slideshow:*:*:*:*:*:wordpress:*:*" + ], + "folders": [ + "cpe:2.3:a:premio:folders:*:*:*:*:*:wordpress:*:*" + ], + "follow-me": [ + "cpe:2.3:a:follow_me_plugin_project:follow_me_plugin:*:*:*:*:*:wordpress:*:*" + ], + "font": [ + "cpe:2.3:a:font_project:font:*:*:*:*:*:wordpress:*:*" + ], + "font-awesome": [ + "cpe:2.3:a:fontawesome:font_awesome:*:*:*:*:*:wordpress:*:*" + ], + "font-awesome-4-menus": [ + "cpe:2.3:a:newnine:font_awesome_4_menus:*:*:*:*:*:wordpress:*:*" + ], + "fontmeister": [ + "cpe:2.3:a:fontmeister_project:fontmeister:*:*:*:*:*:wordpress:*:*" + ], + "fontsy": [ + "cpe:2.3:a:fontsy_project:fontsy:*:*:*:*:*:wordpress:*:*" + ], + "food-and-drink-menu": [ + "cpe:2.3:a:fivestarplugins:five_star_restaurant_menu:*:*:*:*:*:wordpress:*:*" + ], + "foogallery": [ + "cpe:2.3:a:fooplugins:foogallery:*:*:*:*:*:wordpress:*:*" + ], + "foogallery-premium": [ + "cpe:2.3:a:fooplugins:foogallery:*:*:*:*:*:wordpress:*:*" + ], + "football-pool": [ + "cpe:2.3:a:football_pool_project:football_pool:*:*:*:*:*:wordpress:*:*" + ], + "footer-putter": [ + "cpe:2.3:a:diywebmastery:footer_putter:*:*:*:*:*:wordpress:*:*" + ], + "footer-text": [ + "cpe:2.3:a:footer-text_project:footer-text:*:*:*:*:*:wordpress:*:*" + ], + "for-the-visually-impaired": [ + "cpe:2.3:a:984.ru:for_the_visually_impaired:*:*:*:*:*:wordpress:*:*" + ], + "force-first-last": [ + "cpe:2.3:a:strangerstudios:force_display_name:*:*:*:*:*:wordpress:*:*" + ], + "forget-about-shortcode-buttons": [ + "cpe:2.3:a:designsandcode:forget_about_shortcode_buttons:*:*:*:*:*:wordpress:*:*" + ], + "form-maker": [ + "cpe:2.3:a:10web:form_maker:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:web-dorado:form_maker:*:*:*:*:*:wordpress:*:*" + ], + "form-vibes": [ + "cpe:2.3:a:wpvibes:form_vibes:*:*:*:*:*:wordpress:*:*" + ], + "formbuilder": [ + "cpe:2.3:a:formbuilder_project:formbuilder:*:*:*:*:*:wordpress:*:*" + ], + "formcraft-form-builder": [ + "cpe:2.3:a:formcrafts:formcraft:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:ncrafts:formcraft:*:*:*:*:*:wordpress:*:*" + ], + "formforall": [ + "cpe:2.3:a:formforall:formforall:*:*:*:*:*:wordpress:*:*" + ], + "formget-contact-form": [ + "cpe:2.3:a:formget:contact_form_by_formget:*:*:*:*:*:wordpress:*:*" + ], + "formidable": [ + "cpe:2.3:a:strategy11:formidable_form_builder:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:strategy11:formidable_forms:*:*:*:*:*:wordpress:*:*" + ], + "formidable-sms": [ + "cpe:2.3:a:mediaburst:formidable:*:*:*:*:*:wordpress:*:*" + ], + "formidablepro-2-pdf": [ + "cpe:2.3:a:formidablepro2pdf:formidable_pro2pdf:*:*:*:*:*:wordpress:*:*" + ], + "formilla-live-chat": [ + "cpe:2.3:a:formilla:live_chat:*:*:*:*:*:wordpress:*:*" + ], + "forminator": [ + "cpe:2.3:a:incsub:forminator:*:*:*:*:*:wordpress:*:*" + ], + "forms-ada-form-builder": [ + "cpe:2.3:a:monitorclick:forms_ada:*:*:*:*:*:wordpress:*:*" + ], + "forms-by-made-it": [ + "cpe:2.3:a:madeit:forms:*:*:*:*:*:wordpress:*:*" + ], + "forms-for-campaign-monitor": [ + "cpe:2.3:a:campaignmonitor:campaign_monitor:*:*:*:*:*:wordpress:*:*" + ], + "formzu-wp": [ + "cpe:2.3:a:formzu:formzu_wp:*:*:*:*:*:wordpress:*:*" + ], + "fossura-tag-miner": [ + "cpe:2.3:a:fossura:tag_miner:*:*:*:*:*:wordpress:*:*" + ], + "fotobook": [ + "cpe:2.3:a:fotobook_project:fotobook:*:*:*:*:*:wordpress:*:*" + ], + "foxyshop": [ + "cpe:2.3:a:foxy:foxyshop:*:*:*:*:*:wordpress:*:*" + ], + "free-comments-for-wordpress-vuukle": [ + "cpe:2.3:a:vuukle:vuukle_comments\\,_reactions\\,_share_bar\\,_revenue:*:*:*:*:*:wordpress:*:*" + ], + "free-sales-funnel-squeeze-pages-landing-page-builder-templates-make": [ + "cpe:2.3:a:wpleadplus:wp_lead_plus_x:*:*:*:*:*:wordpress:*:*" + ], + "freemind-wp-browser": [ + "cpe:2.3:a:freemind_wp_browser_project:freemind_wp_browser:*:*:*:*:*:wordpress:*:*" + ], + "freshdesk-support": [ + "cpe:2.3:a:freshworks:freshdesk:*:*:*:*:*:wordpress:*:*" + ], + "freshmail-newsletter": [ + "cpe:2.3:a:borbis:freshmail_for_wordpress:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:freshmail:freshmail-newsletter:*:*:*:*:*:wordpress:*:*" + ], + "front-end-pm": [ + "cpe:2.3:a:shamimsplugins:front_end_pm:*:*:*:*:*:wordpress:*:*" + ], + "frontend-uploader": [ + "cpe:2.3:a:frontend_uploader_project:frontend_uploader:*:*:*:*:*:wordpress:*:*" + ], + "frontier-post": [ + "cpe:2.3:a:wpfrontier:frontier_post:*:*:*:*:*:wordpress:*:*" + ], + "fs-shopping-cart": [ + "cpe:2.3:a:firestormplugins:fs-shopping-cart:*:*:*:*:*:wordpress:*:*" + ], + "fscf-sms": [ + "cpe:2.3:a:mediaburst:fast_secure_contact_form_sms:*:*:*:*:*:wordpress:*:*" + ], + "fsflex-local-fonts": [ + "cpe:2.3:a:flex_local_fonts_project:flex_local_fonts:*:*:*:*:*:wordpress:*:*" + ], + "ftp-access": [ + "cpe:2.3:a:danialhatami:ftp_access:*:*:*:*:*:wordpress:*:*" + ], + "full-customer": [ + "cpe:2.3:a:full:full_-_customer:*:*:*:*:*:wordpress:*:*" + ], + "full-site-editing": [ + "cpe:2.3:a:automattic:wordpress.com_editing_toolkit:*:*:*:*:*:wordpress:*:*" + ], + "funnel-builder": [ + "cpe:2.3:a:funnelkit:funnel_builder:*:*:*:*:*:wordpress:*:*" + ], + "funnelforms-free": [ + "cpe:2.3:a:funnelforms:funnelforms_free:*:*:*:*:*:wordpress:*:*" + ], + "furikake": [ + "cpe:2.3:a:furikake_project:furikake:*:*:*:*:*:wordpress:*:*" + ], + "futurio-extra": [ + "cpe:2.3:a:futuriowp:futurio_extra:*:*:*:*:*:wordpress:*:*" + ], + "fv-wordpress-flowplayer": [ + "cpe:2.3:a:foliovision:fv_flowplayer_video_player:*:*:*:*:*:wordpress:*:*" + ], + "g-auto-hyperlink": [ + "cpe:2.3:a:g_auto-hyperlink_project:g_auto-hyperlink:*:*:*:*:*:wordpress:*:*" + ], + "galleria": [ + "cpe:2.3:a:galleria_project:galleria:*:*:*:*:*:wordpress:*:*" + ], + "gallery-album": [ + "cpe:2.3:a:wpdevart:gallery:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpdevart:responsive_image_gallery:*:*:*:*:*:wordpress:*:*" + ], + "gallery-bank": [ + "cpe:2.3:a:tech-banker:gallery_bank:*:*:*:*:*:wordpress:*:*" + ], + "gallery-by-supsystic": [ + "cpe:2.3:a:supsystic:photo_gallery:*:*:*:*:*:wordpress:*:*" + ], + "gallery-categories": [ + "cpe:2.3:a:bestwebsoft:gallery_categories:*:*:*:*:*:wordpress:*:*" + ], + "gallery-image-gallery-photo": [ + "cpe:2.3:a:rich-web:image_gallery:*:*:*:*:*:wordpress:*:*" + ], + "gallery-images": [ + "cpe:2.3:a:huge-it:image_gallery:*:*:*:*:*:wordpress:*:*" + ], + "gallery-images-ape": [ + "cpe:2.3:a:robogallery:gallery_images_ape:*:*:*:*:*:wordpress:*:*" + ], + "gallery-metabox": [ + "cpe:2.3:a:gallery-metabox_project:gallery-metabox:*:*:*:*:*:wordpress:*:*" + ], + "gallery-photo-gallery": [ + "cpe:2.3:a:ays-pro:photo_gallery:*:*:*:*:*:wordpress:*:*" + ], + "gallery-plugin": [ + "cpe:2.3:a:bestwebsoft:gallery:*:*:*:*:*:wordpress:*:*" + ], + "gallery-videos": [ + "cpe:2.3:a:total-soft:video_gallery:*:*:*:*:*:wordpress:*:*" + ], + "gallery-with-thumbnail-slider": [ + "cpe:2.3:a:galaxyweblinks:gallery_with_thumbnail_slider:*:*:*:*:*:wordpress:*:*" + ], + "game-server-status": [ + "cpe:2.3:a:game-server-status_project:game-server-status:*:*:*:*:*:wordpress:*:*" + ], + "gamepress": [ + "cpe:2.3:a:gamepress_project:gamepress:*:*:*:*:*:wordpress:*:*" + ], + "gamipress": [ + "cpe:2.3:a:gamipress:gamipress:*:*:*:*:*:wordpress:*:*" + ], + "gamipress-link": [ + "cpe:2.3:a:gamipress:gamipress_-_link:*:*:*:*:*:wordpress:*:*" + ], + "garden-gnome-package": [ + "cpe:2.3:a:ggnome:garden_gnome_package:*:*:*:*:*:wordpress:*:*" + ], + "gc-testimonials": [ + "cpe:2.3:a:gc_testimonials_project:gc_testimonials:*:*:*:*:*:wordpress:*:*" + ], + "gd-bbpress-attachments": [ + "cpe:2.3:a:dev4press:gd_bbpress_attachments:*:*:*:*:*:wordpress:*:*" + ], + "gd-mail-queue": [ + "cpe:2.3:a:dev4press:gd_mail_queue:*:*:*:*:*:wordpress:*:*" + ], + "gd-mylist": [ + "cpe:2.3:a:gd-mylist_project:gd-mylist:*:*:*:*:*:wordpress:*:*" + ], + "gd-rating-system": [ + "cpe:2.3:a:gdragon:gd_rating_system:*:*:*:*:*:wordpress:*:*" + ], + "gd-security-headers": [ + "cpe:2.3:a:dev4press:gd_security_headers:*:*:*:*:*:wordpress:*:*" + ], + "gdpr-compliance-by-supsystic": [ + "cpe:2.3:a:supsystic:gdpr_cookie_consent:*:*:*:*:*:wordpress:*:*" + ], + "gdpr-compliance-cookie-consent": [ + "cpe:2.3:a:stylemixthemes:gdpr_compliance_\\\u0026_cookie_consent:*:*:*:*:*:wordpress:*:*" + ], + "gdpr-cookie-consent": [ + "cpe:2.3:a:wpeka:wp_cookie_consent:*:*:*:*:-:wordpress:*:*" + ], + "gdpr-data-request-form": [ + "cpe:2.3:a:whodunit:gdpr_data_request_form:*:*:*:*:*:wordpress:*:*" + ], + "gecka-terms-thumbnails": [ + "cpe:2.3:a:gecka:terms_thumbnails:*:*:*:*:*:wordpress:*:*" + ], + "generate-child-theme": [ + "cpe:2.3:a:catchplugins:generate_child_theme:*:*:*:*:*:wordpress:*:*" + ], + "generate-pdf-using-contact-form-7": [ + "cpe:2.3:a:zealousweb:generate_pdf_using_contact_form_7:*:*:*:*:*:wordpress:*:*" + ], + "generatepress-premium": [ + "cpe:2.3:a:generatepress:generatepress:*:*:*:*:premium:wordpress:*:*" + ], + "genesis-columns-advanced": [ + "cpe:2.3:a:genesis_columns_advanced_project:genesis_columns_advanced:*:*:*:*:*:wordpress:*:*" + ], + "genesis-simple-love": [ + "cpe:2.3:a:phpbits:genesis_simple_love:*:*:*:*:*:wordpress:*:*" + ], + "genie-wp-favicon": [ + "cpe:2.3:a:genie_wp_favicon_project:genie_wp_favicon:*:*:*:*:*:wordpress:*:*" + ], + "genki-pre-publish-reminder": [ + "cpe:2.3:a:genki_pre-publish_reminder_project:genki_pre-publish_reminder:*:*:*:*:*:wordpress:*:*" + ], + "geo-mashup": [ + "cpe:2.3:a:geo_mashup_project:geo_mashup:*:*:*:*:*:wordpress:*:*" + ], + "geo-my-wp": [ + "cpe:2.3:a:geomywp:geo_my_wordpress:*:*:*:*:*:wordpress:*:*" + ], + "geodirectory": [ + "cpe:2.3:a:ayecode:geodirectory:*:*:*:*:*:wordpress:*:*" + ], + "get-custom-field-values": [ + "cpe:2.3:a:get_custom_field_values_project:get_custom_field_values:*:*:*:*:*:wordpress:*:*" + ], + "get-site-to-phone-by-qr-code": [ + "cpe:2.3:a:showing_url_in_qr_code_project:showing_url_in_qr_code:*:*:*:*:*:wordpress:*:*" + ], + "get-your-number": [ + "cpe:2.3:a:punchcreative:get_your_number:*:*:*:*:*:wordpress:*:*" + ], + "getresponse-integration": [ + "cpe:2.3:a:getresponse:getresponse:*:*:*:*:*:wordpress:*:*" + ], + "gettext-override-translations": [ + "cpe:2.3:a:gettext_override_translations_project:gettext_override_translations:*:*:*:*:*:wordpress:*:*" + ], + "getwid": [ + "cpe:2.3:a:motopress:getwid_-_gutenberg_blocks:*:*:*:*:*:wordpress:*:*" + ], + "getyourguide-ticketing": [ + "cpe:2.3:a:getyourguide_ticketing_project:getyourguide_ticketing:*:*:*:*:*:wordpress:*:*" + ], + "gf-block-ips": [ + "cpe:2.3:a:brightplugins:block_ips_for_gravity_forms:*:*:*:*:*:wordpress:*:*" + ], + "gg-woo-feed": [ + "cpe:2.3:a:gutengeek:gg_woo_feed:*:*:*:*:*:wordpress:*:*" + ], + "ghost": [ + "cpe:2.3:a:ghost:ghost:*:*:*:*:*:node.js:*:*", + "cpe:2.3:a:ghost:ghost:*:*:*:*:*:wordpress:*:*" + ], + "gift-certificate-creator": [ + "cpe:2.3:a:bobcares:gift-certificate-creator:*:*:*:*:*:wordpress:*:*" + ], + "gift-up": [ + "cpe:2.3:a:giftup:gift_up_gift_cards_for_wordpress_and_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "gift-voucher": [ + "cpe:2.3:a:codemenschen:gift_vouchers:*:*:*:*:*:wordpress:*:*" + ], + "gigpress": [ + "cpe:2.3:a:liquidweb:gigpress:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:tri:gigpress:*:*:*:*:*:wordpress:*:*" + ], + "give": [ + "cpe:2.3:a:givewp:givewp:*:*:*:*:*:wordpress:*:*" + ], + "giveasap": [ + "cpe:2.3:a:ibenic:simple_giveaways:*:*:*:*:*:wordpress:*:*" + ], + "giveaway": [ + "cpe:2.3:a:satollo:giveaway:*:*:*:*:*:wordpress:*:*" + ], + "glass": [ + "cpe:2.3:a:codeblab:glass:*:*:*:*:*:wordpress:*:*" + ], + "global-content-blocks": [ + "cpe:2.3:a:global_content_blocks_project:global_content_blocks:*:*:*:*:*:wordpress:*:*" + ], + "glossary-by-codeat": [ + "cpe:2.3:a:codeat:glossary:*:*:*:*:*:wordpress:*:*" + ], + "gm-woocommerce-quote-popup": [ + "cpe:2.3:a:gravitymaster:product_enquiry_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "gmace": [ + "cpe:2.3:a:gmace_project:gmace:*:*:*:*:*:wordpress:*:*" + ], + "gn-publisher": [ + "cpe:2.3:a:gnpublisher:gn_publisher:*:*:*:*:*:wordpress:*:*" + ], + "gnu-mailman-integration": [ + "cpe:2.3:a:gnu-mailman_integration_project:gnu-mailman_integration:*:*:*:*:*:wordpress:*:*" + ], + "gnucommerce": [ + "cpe:2.3:a:sir:gnucommerce:*:*:*:*:*:wordpress:*:*" + ], + "gocodes": [ + "cpe:2.3:a:webmaster-source:gocodes:*:*:*:*:*:wordpress:*:*" + ], + "godaddy-email-marketing-sign-up-forms": [ + "cpe:2.3:a:godaddy:godaddy_email_marketing:*:*:*:*:*:wordpress:*:*" + ], + "gold-price-chart-widget": [ + "cpe:2.3:a:goldbroker:live_gold_price_\\\u0026_silver_price_charts_widgets:*:*:*:*:*:wordpress:*:*" + ], + "good-bad-comments": [ + "cpe:2.3:a:good-bad-comments_project:good-bad-comments:*:*:*:*:*:wordpress:*:*" + ], + "google-analyticator": [ + "cpe:2.3:a:sumo:google_analyticator:*:*:*:*:*:wordpress:*:*" + ], + "google-analytics-dashboard": [ + "cpe:2.3:a:yoast:google_analytics_dashboard:*:*:*:*:*:wordpress:*:*" + ], + "google-analytics-dashboard-for-wp": [ + "cpe:2.3:a:monsterinsights:exactmetrics:*:*:*:*:*:wordpress:*:*" + ], + "google-analytics-for-wordpress": [ + "cpe:2.3:a:monsterinsights:monsterinsights:*:*:*:*:*:wordpress:*:*" + ], + "google-analytics-opt-out": [ + "cpe:2.3:a:wp-buddy:google_analytics_opt-out:*:*:*:*:*:wordpress:*:*" + ], + "google-analytics-top-posts-widget": [ + "cpe:2.3:a:google_analytics_top_content_widget_project:google_analytics_top_content_widget:*:*:*:*:*:wordpress:*:*" + ], + "google-apps-login": [ + "cpe:2.3:a:wp-glogin:login_for_google_apps:*:*:*:*:*:wordpress:*:*" + ], + "google-authenticator": [ + "cpe:2.3:a:miniorange:google_authenticator:*:*:*:*:*:wordpress:*:*" + ], + "google-calendar-events": [ + "cpe:2.3:a:google_calendar_events_project:google_calendar_events:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:xtendify:simple_calendar:*:*:*:*:*:wordpress:*:*" + ], + "google-captcha": [ + "cpe:2.3:a:bestwebsoft:google_captcha:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:bestwebsoft:google_captcha_\\(recaptcha\\):*:*:*:*:*:wordpress:*:*" + ], + "google-cse": [ + "cpe:2.3:a:erikeng:google_cse:*:*:*:*:*:wordpress:*:*" + ], + "google-document-embedder": [ + "cpe:2.3:a:google_doc_embedder:google_doc_embedder:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:google_doc_embedder_project:google_doc_embedder:*:*:*:*:*:wordpress:*:*" + ], + "google-drive-embedder": [ + "cpe:2.3:a:google_doc_embedder_project:google_doc_embedder:*:*:*:*:*:wordpress:*:*" + ], + "google-language-translator": [ + "cpe:2.3:a:gtranslate:google_language_translator:*:*:*:*:*:wordpress:*:*" + ], + "google-map-shortcode": [ + "cpe:2.3:a:web-argument:google-map-shortcode:*:*:*:*:*:wordpress:*:*" + ], + "google-maps-advanced": [ + "cpe:2.3:a:inline_google_maps_project:inline_google_maps:*:*:*:*:*:wordpress:*:*" + ], + "google-maps-anywhere": [ + "cpe:2.3:a:google_maps_anywhere_project:google_maps_anywhere:*:*:*:*:*:wordpress:*:*" + ], + "google-maps-easy": [ + "cpe:2.3:a:supsystic:easy_google_maps:*:*:*:*:*:wordpress:*:*" + ], + "google-maps-v3-shortcode": [ + "cpe:2.3:a:google_maps_v3_shortcode_project:google_maps_v3_shortcode:*:*:*:*:*:wordpress:*:*" + ], + "google-maps-widget": [ + "cpe:2.3:a:webfactoryltd:maps_widget_for_google_maps:*:*:*:*:*:wordpress:*:*" + ], + "google-mobile-sitemap": [ + "cpe:2.3:a:digitalinspiration:google_xml_sitemap_for_mobile:*:*:*:*:*:wordpress:*:*" + ], + "google-news-sitemap": [ + "cpe:2.3:a:google-news-sitemap_project:google-news-sitemap:*:*:*:*:*:wordpress:*:*" + ], + "google-one": [ + "cpe:2.3:a:bestwebsoft:google_\\+1:*:*:*:*:*:wordpress:*:*" + ], + "google-pagespeed-insights": [ + "cpe:2.3:a:insights_from_google_pagespeed_project:insights_from_google_pagespeed:*:*:*:*:*:wordpress:*:*" + ], + "google-picasa-albums-viewer": [ + "cpe:2.3:a:nakunakifi:google_photos_gallery_with_shortcodes:*:*:*:*:*:wordpress:*:*" + ], + "google-shortlink": [ + "cpe:2.3:a:bestwebsoft:google_shortlink:*:*:*:*:*:wordpress:*:*" + ], + "google-site-kit": [ + "cpe:2.3:a:google:site_kit:*:*:*:*:*:wordpress:*:*" + ], + "google-site-verification-using-meta-tag": [ + "cpe:2.3:a:himanshuparashar:google_site_verification_plugin_using_meta_tag:*:*:*:*:*:wordpress:*:*" + ], + "google-sitemap-generator": [ + "cpe:2.3:a:google_xml_sitemaps_project:google_xml_sitemaps:*:*:*:*:*:wordpress:*:*" + ], + "google-sitemap-plugin": [ + "cpe:2.3:a:bestwebsoft:google_sitemap:*:*:*:*:*:wordpress:*:*" + ], + "googleanalytics": [ + "cpe:2.3:a:sharethis:dashboard_for_google_analytics:*:*:*:*:*:wordpress:*:*" + ], + "googmonify": [ + "cpe:2.3:a:googmonify_project:googmonify:*:*:*:*:*:wordpress:*:*" + ], + "goolytics-simple-google-analytics": [ + "cpe:2.3:a:goolytics_project:goolytics:*:*:*:*:*:wordpress:*:*" + ], + "gotmls": [ + "cpe:2.3:a:anti-malware_security_and_brute-force_firewall_project:anti-malware_security_and_brute-force_firewall:*:*:*:*:*:wordpress:*:*" + ], + "gotowp": [ + "cpe:2.3:a:gotowp:gotowp:*:*:*:*:*:wordpress:*:*" + ], + "gourl-bitcoin-payment-gateway-paid-downloads-membership": [ + "cpe:2.3:a:gorul:gourl:*:*:*:*:*:wordpress:*:*" + ], + "gpt3-ai-content-generator": [ + "cpe:2.3:a:aipower:aipower:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:gptaipower:gpt_ai_power:*:*:*:*:*:wordpress:*:*" + ], + "gracemedia-media-player": [ + "cpe:2.3:a:gracemedia_media_player_project:gracemedia_media_player:*:*:*:*:*:wordpress:*:*" + ], + "grand-media": [ + "cpe:2.3:a:codeasily:gmedia_gallery:*:*:*:*:*:wordpress:*:*" + ], + "gravitate-qa-tracker": [ + "cpe:2.3:a:gravitatedesign:gravitate_qa_tracker:*:*:*:*:*:wordpress:*:*" + ], + "gravity-forms-dps-pxpay": [ + "cpe:2.3:a:webaware:gf_windcave_free:*:*:*:*:*:wordpress:*:*" + ], + "gravity-forms-sms-notifications": [ + "cpe:2.3:a:mediaburst:gravity_forms:*:*:*:*:*:wordpress:*:*" + ], + "great-quotes": [ + "cpe:2.3:a:great-quotes_project:great-quotes:*:*:*:*:*:wordpress:*:*" + ], + "greeklish-permalink": [ + "cpe:2.3:a:greeklish-permalink_project:greeklish-permalink:*:*:*:*:*:wordpress:*:*" + ], + "greenshift-animation-and-page-builder-blocks": [ + "cpe:2.3:a:greenshiftwp:greenshift_-_animation_and_page_builder_blocks:*:*:*:*:*:wordpress:*:*" + ], + "greenwallet-gateway": [ + "cpe:2.3:a:envision\\\u0026company:woocommerce_green_wallet_gateway:*:*:*:*:*:wordpress:*:*" + ], + "gregs-high-performance-seo": [ + "cpe:2.3:a:greg\\'s_high_performance_seo_project:greg\\'s_high_performance_seo:*:*:*:*:*:wordpress:*:*" + ], + "grid-plus": [ + "cpe:2.3:a:g5theme:grid_plus:*:*:*:*:*:wordpress:*:*" + ], + "groundhogg": [ + "cpe:2.3:a:groundhogg:groundhogg:*:*:*:*:*:wordpress:*:*" + ], + "gs-logo-slider": [ + "cpe:2.3:a:gsplugins:gs_logo_slider:*:*:*:*:*:wordpress:*:*" + ], + "gs-portfolio": [ + "cpe:2.3:a:gsplugins:gs_filterable_portfolio:*:*:*:*:*:wordpress:*:*" + ], + "gs-testimonial": [ + "cpe:2.3:a:gsplugins:gs_testimonial_slider:*:*:*:*:*:wordpress:*:*" + ], + "gs-woocommerce-products-slider": [ + "cpe:2.3:a:gsplugins:gs_products_slider:*:*:*:*:*:wordpress:*:*" + ], + "gseor": [ + "cpe:2.3:a:bestiaweb:gseor:*:*:*:*:*:wordpress:*:*" + ], + "gsheetconnector-caldera-forms": [ + "cpe:2.3:a:gsheetconnector:caldera_forms_google_sheets_connector:*:*:*:*:*:wordpress:*:*" + ], + "gsheetconnector-gravity-forms": [ + "cpe:2.3:a:gsheetconnector:gravity_forms_google_sheets_connector:*:*:*:*:*:wordpress:*:*" + ], + "gsheetconnector-ninja-forms": [ + "cpe:2.3:a:gsheetconnector:ninja_forms_google_sheet_connector:*:*:*:*:free:wordpress:*:*" + ], + "gsheetconnector-wpforms": [ + "cpe:2.3:a:gsheetconnector:wpforms_google_sheet_connector:*:*:*:*:free:wordpress:*:*" + ], + "gtmetrix-for-wordpress": [ + "cpe:2.3:a:gtmetrix:gtmetrix:*:*:*:*:*:wordpress:*:*" + ], + "gtranslate": [ + "cpe:2.3:a:gtranslate:gtranslate:*:*:*:*:enterprise:wordpress:*:*", + "cpe:2.3:a:gtranslate:gtranslate:*:*:*:*:pro:wordpress:*:*", + "cpe:2.3:a:gtranslate:translate_wordpress_with_gtranslate:*:*:*:*:*:wordpress:*:*" + ], + "guardgiant": [ + "cpe:2.3:a:guardgiant:guardgiant:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:guardgiant:wordpress_brute_force_protection_-_stop_brute_force_attacks:*:*:*:*:*:wordpress:*:*" + ], + "guest-author": [ + "cpe:2.3:a:webfactoryltd:guest_author:*:*:*:*:*:wordpress:*:*" + ], + "guest-author-name": [ + "cpe:2.3:a:shooflysolutions:\\(simply\\)_guest_author_name:*:*:*:*:*:wordpress:*:*" + ], + "guruwalk-affiliates": [ + "cpe:2.3:a:guruwalk:guruwalk_affiliates:*:*:*:*:*:wordpress:*:*" + ], + "gutenberg": [ + "cpe:2.3:a:wordpress:gutenberg:*:*:*:*:*:wordpress:*:*" + ], + "gutenslider": [ + "cpe:2.3:a:gutenslider:gutenslider:*:*:*:*:*:wordpress:*:*" + ], + "gwa-autoresponder": [ + "cpe:2.3:a:\\[gwa\\]_autoresponder_project:\\[gwa\\]_autoresponder:*:*:*:*:*:wordpress:*:*" + ], + "gwolle-gb": [ + "cpe:2.3:a:gwolle_guestbook_project:gwolle_guestbook:*:*:*:*:*:wordpress:*:*" + ], + "gwyns-imagemap-selector": [ + "cpe:2.3:a:gwyn\\'s_imagemap_selector_project:gwyn\\'s_imagemap_selector:*:*:*:*:*:wordpress:*:*" + ], + "hal": [ + "cpe:2.3:a:cnrs:hal:*:*:*:*:*:wordpress:*:*" + ], + "hana-flv-player": [ + "cpe:2.3:a:hana_flv_player_project:hana_flv_player:*:*:*:*:*:wordpress:*:*" + ], + "handl-utm-grabber": [ + "cpe:2.3:a:haktansuren:handl_utm_grabber:*:*:*:*:*:wordpress:*:*" + ], + "handsome-testimonials": [ + "cpe:2.3:a:handsome_testimonials_\\\u0026_reviews_project:handsome_testimonials_\\\u0026_reviews:*:*:*:*:*:wordpress:*:*" + ], + "happy-elementor-addons": [ + "cpe:2.3:a:wedevs:happy_addons_for_elementor:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wedevs:happy_addons_for_elementor:*:*:*:*:-:wordpress:*:*" + ], + "happyforms": [ + "cpe:2.3:a:happyforms:happyforms:*:*:*:*:*:wordpress:*:*" + ], + "hashbar-wp-notification-bar": [ + "cpe:2.3:a:hasthemes:hashbar:*:*:*:*:*:wordpress:*:*" + ], + "hashthemes-demo-importer": [ + "cpe:2.3:a:hashthemes:hashthemes_demo_importer:*:*:*:*:*:wordpress:*:*" + ], + "hc-custom-wp-admin-url": [ + "cpe:2.3:a:hc_custom_wp-admin_url_project:hc_custom_wp-admin_url:*:*:*:*:*:wordpress:*:*" + ], + "hd-quiz": [ + "cpe:2.3:a:harmonicdesign:hd_quiz:*:*:*:*:*:wordpress:*:*" + ], + "hdw-player-video-player-video-gallery": [ + "cpe:2.3:a:hdwplayer:hdw_player:*:*:*:*:*:wordpress:*:*" + ], + "header-enhancement": [ + "cpe:2.3:a:catchplugins:header_enhancement:*:*:*:*:*:wordpress:*:*" + ], + "header-footer-code-manager": [ + "cpe:2.3:a:draftpress:header_footer_code_manager:*:*:*:*:*:wordpress:*:*" + ], + "header-footer-elementor": [ + "cpe:2.3:a:brainstormforce:elementor_-_header\\,_footer_\\\u0026_blocks_template:*:*:*:*:*:wordpress:*:*" + ], + "heat-trackr": [ + "cpe:2.3:a:heat-trackr_project:heat-trackr:*:*:*:*:*:wordpress:*:*" + ], + "heateor-social-comments": [ + "cpe:2.3:a:heateor:social_comments:*:*:*:*:*:wordpress:*:*" + ], + "heateor-social-login": [ + "cpe:2.3:a:heateor:social_login:*:*:*:*:*:wordpress:*:*" + ], + "helloprint": [ + "cpe:2.3:a:helloprint:helloprint:*:*:*:*:*:wordpress:*:*" + ], + "helpie-faq": [ + "cpe:2.3:a:helpiewp:accordion_\\\u0026_faq:*:*:*:*:*:wordpress:*:*" + ], + "hermit": [ + "cpe:2.3:a:hermit_project:hermit:*:*:*:*:*:wordpress:*:*" + ], + "hero-banner-ultimate": [ + "cpe:2.3:a:essentialplugin:hero_banner_ultimate:*:*:*:*:*:wordpress:*:*" + ], + "highlight": [ + "cpe:2.3:a:dna88:highlight:*:*:*:*:*:wordpress:*:*" + ], + "highlight-focus": [ + "cpe:2.3:a:highlight_focus_project:highlight_focus:*:*:*:*:*:wordpress:*:*" + ], + "hiweb-migration-simple": [ + "cpe:2.3:a:hiweb:migration_simple:*:*:*:*:*:wordpress:*:*" + ], + "hk-exif-tags": [ + "cpe:2.3:a:hk_exif_tags_project:hk_exif_tags:*:*:*:*:*:wordpress:*:*" + ], + "hk-filter-and-search": [ + "cpe:2.3:a:jonashjalmarsson:html_filter_and_csv-file_search:*:*:*:*:*:wordpress:*:*" + ], + "hms-testimonials": [ + "cpe:2.3:a:hitmyserver:hms_testimonials:*:*:*:*:*:wordpress:*:*" + ], + "homepage-product-organizer-for-woocommerce": [ + "cpe:2.3:a:homepage_product_organizer_for_woocommerce_project:homepage_product_organizer_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "honeypot-for-wp-comment": [ + "cpe:2.3:a:prasidhdamalla:honeypot_for_wp_comment:*:*:*:*:*:wordpress:*:*" + ], + "horizontal-scrolling-announcement": [ + "cpe:2.3:a:gopiplus:horizontal_scrolling_announcement:*:*:*:*:*:wordpress:*:*" + ], + "host-analyticsjs-local": [ + "cpe:2.3:a:daan:complete_analytics_optimization_suite:*:*:*:*:*:wordpress:*:*" + ], + "host-webfonts-local": [ + "cpe:2.3:a:daan:omgf:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:ffw:optimize_my_google_fonts:*:*:*:*:*:wordpress:*:*" + ], + "hostel": [ + "cpe:2.3:a:kibokolabs:hostel:*:*:*:*:*:wordpress:*:*" + ], + "hostinger": [ + "cpe:2.3:a:hostinger:hostinger:*:*:*:*:*:wordpress:*:*" + ], + "hot-linked-image-cacher": [ + "cpe:2.3:a:hot_linked_image_cacher_project:hot_linked_image_cacher:*:*:*:*:*:wordpress:*:*" + ], + "hotjar": [ + "cpe:2.3:a:hotjar:hotjar:*:*:*:*:*:wordpress:*:*" + ], + "hotjar-connecticator": [ + "cpe:2.3:a:bluemedicinelabs:hotjar_connecticator:*:*:*:*:*:wordpress:*:*" + ], + "hotscot-contact-form": [ + "cpe:2.3:a:hotscot:contact_form:*:*:*:*:*:wordpress:*:*" + ], + "hover-image": [ + "cpe:2.3:a:hover-image_project:hover-image:*:*:*:*:*:wordpress:*:*" + ], + "hpbtool": [ + "cpe:2.3:a:justsystems:hpb_dashboard:*:*:*:*:*:wordpress:*:*" + ], + "hreflang-tags-by-dcgws": [ + "cpe:2.3:a:dcgws:hreflang_tags_lite:*:*:*:*:*:wordpress:*:*" + ], + "hrm": [ + "cpe:2.3:a:mishubd:wp_human_resource_management:*:*:*:*:*:wordpress:*:*" + ], + "ht-contactform": [ + "cpe:2.3:a:hasthemes:download_contact_form_7_widget_for_elementor_page_builder_\\\u0026_gutenberg_blocks:*:*:*:*:*:wordpress:*:*" + ], + "ht-easy-google-analytics": [ + "cpe:2.3:a:hasthemes:ht_easy_ga4_\\(google_analytics_4\\):*:*:*:*:*:wordpress:*:*" + ], + "ht-event": [ + "cpe:2.3:a:hasthemes:ht_event:*:*:*:*:*:wordpress:*:*" + ], + "ht-instagram": [ + "cpe:2.3:a:hasthemes:ht_feed:*:*:*:*:*:wordpress:*:*" + ], + "ht-mega-for-elementor": [ + "cpe:2.3:a:hasthemes:ht_mega_-_absolute_addons_for_elementor_page_builder:*:*:*:*:*:wordpress:*:*" + ], + "ht-menu-lite": [ + "cpe:2.3:a:hasthemes:ht_menu:*:*:*:*:*:wordpress:*:*" + ], + "ht-portfolio": [ + "cpe:2.3:a:hasthemes:ht_portfolio:*:*:*:*:*:wordpress:*:*" + ], + "ht-slider-for-elementor": [ + "cpe:2.3:a:hasthemes:ht_slider_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "htaccess": [ + "cpe:2.3:a:bestwebsoft:htaccess:*:*:*:*:*:wordpress:*:*" + ], + "html-forms": [ + "cpe:2.3:a:ibericode:html_forms:*:*:*:*:*:wordpress:*:*" + ], + "html5-audio-player": [ + "cpe:2.3:a:bplugins:html5_audio_player:*:*:*:*:*:wordpress:*:*" + ], + "html5-maps": [ + "cpe:2.3:a:fla-shop:html5_maps:*:*:*:*:*:wordpress:*:*" + ], + "html5-mp3-player-with-playlist": [ + "cpe:2.3:a:svnlabs:html5_mp3_player_with_playlist_free:*:*:*:*:*:wordpress:*:*" + ], + "html5-soundcloud-player-with-playlist": [ + "cpe:2.3:a:svnlabs:html5_soundcloud_player_with_playlist_free:*:*:*:*:*:wordpress:*:*" + ], + "html5-video-player": [ + "cpe:2.3:a:bplugins:html5_video_player:*:*:*:*:*:wordpress:*:*" + ], + "http-auth": [ + "cpe:2.3:a:yasglobal:http_auth:*:*:*:*:*:wordpress:*:*" + ], + "http-headers": [ + "cpe:2.3:a:riverside:http_headers:*:*:*:*:*:wordpress:*:*" + ], + "http-https-remover": [ + "cpe:2.3:a:inisev:ssl_mixed_content_fix:*:*:*:*:*:wordpress:*:*" + ], + "hummingbird-performance": [ + "cpe:2.3:a:incsub:hummingbird:*:*:*:*:*:wordpress:*:*" + ], + "hungarian-pickup-points-for-woocommerce": [ + "cpe:2.3:a:visztpeter:package_points_and_shipping_labels_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "hyphenator": [ + "cpe:2.3:a:benedictb\\/maciejgryniuk:hyphenator:*:*:*:*:*:wordpress:*:*" + ], + "i-recommend-this": [ + "cpe:2.3:a:themeist:i_recommend_this:*:*:*:*:*:wordpress:*:*" + ], + "i2-pro-cons": [ + "cpe:2.3:a:i2_pros_\\\u0026_cons_project:i2_pros_\\\u0026_cons:*:*:*:*:*:wordpress:*:*" + ], + "ibs-mappro": [ + "cpe:2.3:a:ibs_mappro_project:ibs_mappro:*:*:*:*:*:wordpress:*:*" + ], + "ibtana-visual-editor": [ + "cpe:2.3:a:vowelweb:ibtana:*:*:*:*:*:wordpress:*:*" + ], + "icegram": [ + "cpe:2.3:a:icegram:icegram_engage:*:*:*:*:*:wordpress:*:*" + ], + "icons-font-loader": [ + "cpe:2.3:a:bplugins:icons_font_loader:*:*:*:*:*:wordpress:*:*" + ], + "icons-for-features": [ + "cpe:2.3:a:woocommerce:icons_for_features:*:*:*:*:*:wordpress:*:*" + ], + "idbbee": [ + "cpe:2.3:a:dbbee:idbbee:*:*:*:*:*:wordpress:*:*" + ], + "ideapush": [ + "cpe:2.3:a:northernbeacheswebsites:ideapush:*:*:*:*:*:wordpress:*:*" + ], + "idx-broker-platinum": [ + "cpe:2.3:a:idxbroker:idx_broker:*:*:*:*:platinum:wordpress:*:*", + "cpe:2.3:a:idxbroker:impress_for_idx_broker:*:*:*:*:platinum:wordpress:*:*" + ], + "if-so": [ + "cpe:2.3:a:if-so:dynamic_content_personalization:*:*:*:*:*:wordpress:*:*" + ], + "ifeature-slider": [ + "cpe:2.3:a:cyberchimps:ifeature_slider:*:*:*:*:*:wordpress:*:*" + ], + "iflychat": [ + "cpe:2.3:a:iflychat:iflychat:*:*:*:*:*:wordpress:*:*" + ], + "ifolders": [ + "cpe:2.3:a:avirtum:ifolders:*:*:*:*:*:wordpress:*:*" + ], + "iframe": [ + "cpe:2.3:a:iframe_project:iframe:*:*:*:*:*:wordpress:*:*" + ], + "iframe-shortcode": [ + "cpe:2.3:a:jacksonwhelan:iframe_shortcode:*:*:*:*:*:wordpress:*:*" + ], + "igniteup": [ + "cpe:2.3:a:getigniteup:igniteup:*:*:*:*:*:wordpress:*:*" + ], + "iksweb": [ + "cpe:2.3:a:iksweb:wordpress_ctapt:*:*:*:*:*:wordpress:*:*" + ], + "image-export": [ + "cpe:2.3:a:image-export_project:image-export:*:*:*:*:*:wordpress:*:*" + ], + "image-gallery-with-slideshow": [ + "cpe:2.3:a:anblik:image-gallery-with-slideshow:*:*:*:*:*:wordpress:*:*" + ], + "image-horizontal-reel-scroll-slideshow": [ + "cpe:2.3:a:gopiplus:image_horizontal_reel_scroll_slideshow:*:*:*:*:*:wordpress:*:*" + ], + "image-hover-effects": [ + "cpe:2.3:a:webdevocean:image_hover_effects:*:*:*:*:*:wordpress:*:*" + ], + "image-hover-effects-addon-for-elementor": [ + "cpe:2.3:a:blocksera:image_hover_effects:*:*:*:*:*:wordpress:*:*" + ], + "image-hover-effects-css3": [ + "cpe:2.3:a:image_hover_effects_css3_project:image_hover_effects_css3:*:*:*:*:*:wordpress:*:*" + ], + "image-hover-effects-ultimate": [ + "cpe:2.3:a:oxilab:image_hover_effects_ultimate:*:*:*:*:*:*:*:*", + "cpe:2.3:a:oxilab:image_hover_effects_ultimate:*:*:*:*:*:wordpress:*:*" + ], + "image-hover-effects-visual-composer-extension": [ + "cpe:2.3:a:webdevocean:image_hover_effects_for_wpbakery_page_builder:*:*:*:*:*:wordpress:*:*" + ], + "image-hover-effects-with-carousel": [ + "cpe:2.3:a:oxilab:image_hover_effects_for_elementor_with_lightbox_and_flipbox:*:*:*:*:*:wordpress:*:*" + ], + "image-map-pro-lite": [ + "cpe:2.3:a:imagemappro:image_map_pro:*:*:*:*:lite:wordpress:*:*" + ], + "image-metadata-cruncher": [ + "cpe:2.3:a:image_metadata_cruncher_project:image_metadata_cruncher:*:*:*:*:*:wordpress:*:*" + ], + "image-over-image-vc-extension": [ + "cpe:2.3:a:image_over_image_for_wpbakery_page_builder_project:image_over_image_for_wpbakery_page_builder:*:*:*:*:*:wordpress:*:*" + ], + "image-protector": [ + "cpe:2.3:a:image_protector_project:image_protector:*:*:*:*:*:wordpress:*:*" + ], + "image-regenerate-select-crop": [ + "cpe:2.3:a:iuliacazan:image_regenerate_\\\u0026_select_crop:*:*:*:*:*:wordpress:*:*" + ], + "image-slider-widget": [ + "cpe:2.3:a:ghozylab:image_slider:*:*:*:*:*:wordpress:*:*" + ], + "image-source-control-isc": [ + "cpe:2.3:a:imagesourcecontrol:image_source_control:*:*:*:*:*:wordpress:*:*" + ], + "image-tag-manager": [ + "cpe:2.3:a:bradleybdalina:image_tag_manager:*:*:*:*:*:*:*:*" + ], + "image-upload-for-bbpress": [ + "cpe:2.3:a:wpzone:inline_image_upload_for_bbpress:*:*:*:*:*:wordpress:*:*" + ], + "image-vertical-reel-scroll-slideshow": [ + "cpe:2.3:a:gopiplus:image_vertical_reel_scroll_slideshow:*:*:*:*:*:wordpress:*:*" + ], + "imageboss": [ + "cpe:2.3:a:imageboss:imageboss:*:*:*:*:*:wordpress:*:*" + ], + "imagelinks-interactive-image-builder-lite": [ + "cpe:2.3:a:avirtum:imagelinks:*:*:*:*:*:wordpress:*:*" + ], + "imagemagick-engine": [ + "cpe:2.3:a:orangelab:imagemagick_engine:*:*:*:*:*:wordpress:*:*" + ], + "imagemapper": [ + "cpe:2.3:a:imagemapper_project:imagemapper:*:*:*:*:*:wordpress:*:*" + ], + "imagements": [ + "cpe:2.3:a:imagements_project:imagements:*:*:*:*:*:wordpress:*:*" + ], + "imagerecycle-pdf-image-compression": [ + "cpe:2.3:a:imagerecycle:imagerecycle_pdf_\\\u0026_image_compression:*:*:*:*:*:wordpress:*:*" + ], + "images-optimize-and-upload-cf7": [ + "cpe:2.3:a:images_optimize_and_upload_cf7_project:images_optimize_and_upload_cf7:*:*:*:*:*:wordpress:*:*" + ], + "images-to-webp": [ + "cpe:2.3:a:imagestowebp_project:images_to_webp:*:*:*:*:*:wordpress:*:*" + ], + "imageseo": [ + "cpe:2.3:a:imageseo:optimize_images_alt_text_\\(alt_tag\\)_\\\u0026_names_for_seo_using_ai:*:*:*:*:*:wordpress:*:*" + ], + "imdb-info-box": [ + "cpe:2.3:a:99webtools:imdb_info_box:*:*:*:*:*:wordpress:*:*" + ], + "imdb-widget": [ + "cpe:2.3:a:imdb-widget_project:imdb-widget:*:*:*:*:*:wordpress:*:*" + ], + "import-legacy-media": [ + "cpe:2.3:a:import_legacy_media_project:import_legacy_media:*:*:*:*:*:wordpress:*:*" + ], + "import-shopify-to-woocommerce": [ + "cpe:2.3:a:villatheme:s2w_-_import_shopify_to_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "import-users-from-csv-with-meta": [ + "cpe:2.3:a:codection:import_and_export_users_and_customers:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:codection:import_users_from_csv_with_meta:*:*:*:*:*:wordpress:*:*" + ], + "import-xml-feed": [ + "cpe:2.3:a:mooveagency:import_xml_and_rss_feeds:*:*:*:*:*:wordpress:*:*" + ], + "improved-include-page": [ + "cpe:2.3:a:improved_include_page_project:improved_include_page:*:*:*:*:*:wordpress:*:*" + ], + "inactive-user-deleter": [ + "cpe:2.3:a:inactive_user_deleter_project:inactive_user_deleter:*:*:*:*:*:wordpress:*:*" + ], + "include-me": [ + "cpe:2.3:a:include_me_project:include_me:*:*:*:*:*:wordpress:*:*" + ], + "incoming-links": [ + "cpe:2.3:a:monitorbacklinks:incoming_links:*:*:*:*:*:wordpress:*:*" + ], + "indeed-job-importer": [ + "cpe:2.3:a:indeed-job-importer_project:indeed-job-importer:*:*:*:*:*:*:*:*" + ], + "indieweb-post-kinds": [ + "cpe:2.3:a:indieweb_post_kinds_project:indieweb_post_kinds:*:*:*:*:*:wordpress:*:*" + ], + "infogram": [ + "cpe:2.3:a:torbjon:infogram:*:*:*:*:*:wordpress:*:*" + ], + "infographic-and-list-builder-ilist": [ + "cpe:2.3:a:quantumcloud:infographic_maker:*:*:*:*:*:wordpress:*:*" + ], + "information-reel": [ + "cpe:2.3:a:gopiplus:information_reel:*:*:*:*:*:wordpress:*:*" + ], + "infusionsoft": [ + "cpe:2.3:a:infusionsoft_gravity_forms_project:infusionsoft_gravity_forms:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:infusionsoft_project:infusionsoft:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:katz:infusionsoft_gravity_forms:*:*:*:*:*:wordpress:*:*" + ], + "inline-google-spreadsheet-viewer": [ + "cpe:2.3:a:inline_google_spreadsheet_viewer_project:inline_google_spreadsheet_viewer:*:*:*:*:*:wordpress:*:*" + ], + "inline-tweet-sharer": [ + "cpe:2.3:a:winwar:inline_tweet_sharer:*:*:*:*:*:wordpress:*:*" + ], + "inlinks": [ + "cpe:2.3:a:inlinks_project:inlinks:*:*:*:*:*:wordpress:*:*" + ], + "innovs-hr-manager": [ + "cpe:2.3:a:theinnovs:innovs_hr:*:*:*:*:*:wordpress:*:*" + ], + "inpost-gallery": [ + "cpe:2.3:a:pluginus:inpost_gallery:*:*:*:*:*:wordpress:*:*" + ], + "insert-estimated-reading-time": [ + "cpe:2.3:a:nigauri:insert_estimated_reading_time:*:*:*:*:*:wordpress:*:*" + ], + "insert-headers-and-footers": [ + "cpe:2.3:a:wpcode:wpcode:*:*:*:*:*:wordpress:*:*" + ], + "insert-or-embed-articulate-content-into-wordpress": [ + "cpe:2.3:a:elearningfreak:insert_or_embed_articulate_content:*:*:*:*:*:wordpress:*:*" + ], + "insert-pages": [ + "cpe:2.3:a:insert_pages_project:insert_pages:*:*:*:*:*:wordpress:*:*" + ], + "insert-php": [ + "cpe:2.3:a:cm-wp:woody_code_snippets:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:webcraftic:woody_ad_snippets:*:*:*:*:*:wordpress:*:*" + ], + "insight-core": [ + "cpe:2.3:a:thememove:insight_core:*:*:*:*:*:wordpress:*:*" + ], + "inspirational-quote-rotator": [ + "cpe:2.3:a:inspirational_quote_rotator_project:inspirational_quote_rotator:*:*:*:*:*:wordpress:*:*" + ], + "insta-gallery": [ + "cpe:2.3:a:quadlayers:wp_social_feed_gallery:*:*:*:*:*:wordpress:*:*" + ], + "instagram-for-wordpress": [ + "cpe:2.3:a:ink361:instagram_for_wordpress:*:*:*:*:*:wordpress:*:*" + ], + "instagram-slider-widget": [ + "cpe:2.3:a:cm-wp:social_slider_widget:*:*:*:*:*:wordpress:*:*" + ], + "instalinker": [ + "cpe:2.3:a:elfsight:instalinker:*:*:*:*:*:wordpress:*:*" + ], + "instant-css": [ + "cpe:2.3:a:dylanblokhuis:instant_css:*:*:*:*:*:wordpress:*:*" + ], + "instant-images": [ + "cpe:2.3:a:connekthq:instant_images_-_one_click_unsplash_uploads:*:*:*:*:*:wordpress:*:*" + ], + "instawp-connect": [ + "cpe:2.3:a:instawp:instawp_connect:*:*:*:*:*:wordpress:*:*" + ], + "integracao-rd-station": [ + "cpe:2.3:a:rdstation:rd_station:*:*:*:*:*:wordpress:*:*" + ], + "integrar-getnet-con-woo": [ + "cpe:2.3:a:getnet_argentina_para_woocommerce_project:getnet_argentina_para_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "integrate-google-drive": [ + "cpe:2.3:a:softlabbd:integrate_google_drive:*:*:*:*:*:wordpress:*:*" + ], + "integration-for-billingo-gravity-forms": [ + "cpe:2.3:a:integration_for_billingo_\\\u0026_gravity_forms_project:integration_for_billingo_\\\u0026_gravity_forms:*:*:*:*:*:wordpress:*:*" + ], + "integration-for-szamlazz-hu-gravity-forms": [ + "cpe:2.3:a:integration_for_szamlazz.hu_\\\u0026_gravity_forms_project:integration_for_szamlazz.hu_\\\u0026_gravity_forms:*:*:*:*:*:wordpress:*:*" + ], + "integration-for-szamlazzhu-woocommerce": [ + "cpe:2.3:a:visztpeter:integration_for_szamlazz.hu_\\\u0026_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "interactive-3d-flipbook-powered-physics-engine": [ + "cpe:2.3:a:3dflipbook:3d_flipbook:*:*:*:*:*:wordpress:*:*" + ], + "interactive-geo-maps": [ + "cpe:2.3:a:interactive_geo_maps_project:interactive_geo_maps:*:*:*:*:*:wordpress:*:*" + ], + "interactive-image-map-builder": [ + "cpe:2.3:a:wpmart:interactive_svg_image_map_builder:*:*:*:*:*:wordpress:*:*" + ], + "interactive-medical-drawing-of-human-body": [ + "cpe:2.3:a:humananatomyillustrations:interactive_medical_drawing_of_human_body:*:*:*:*:*:wordpress:*:*" + ], + "interactive-polish-map": [ + "cpe:2.3:a:interactive_polish_map_project:interactive_polish_map:*:*:*:*:*:wordpress:*:*" + ], + "interactive-world-map": [ + "cpe:2.3:a:fla-shop:interactive_world_map:*:*:*:*:*:wordpress:*:*" + ], + "intercom": [ + "cpe:2.3:a:intercom:intercom:*:*:*:*:*:wordpress:*:*" + ], + "intergeo-maps": [ + "cpe:2.3:a:themeisle:google_maps_plugin_by_intergeo:*:*:*:*:*:wordpress:*:*" + ], + "internal-link-building-plugin": [ + "cpe:2.3:a:internetmarketingninjas:internal_link_building:*:*:*:*:*:wordpress:*:*" + ], + "internal-links": [ + "cpe:2.3:a:internallinkjuicer:internal_link_juicer:*:*:*:*:*:wordpress:*:*" + ], + "inventorypress": [ + "cpe:2.3:a:inventorypress_project:inventorypress:*:*:*:*:*:wordpress:*:*" + ], + "invitation-based-registrations": [ + "cpe:2.3:a:securebit:invitation_based_registrations:*:*:*:*:*:wordpress:*:*" + ], + "invite-anyone": [ + "cpe:2.3:a:invite_anyone_project:invite_anyone:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:teleogistic:invite_anyone:*:*:*:*:*:wordpress:*:*" + ], + "invoicing": [ + "cpe:2.3:a:ayecode:getpaid:*:*:*:*:*:wordpress:*:*" + ], + "ip-address-blocker": [ + "cpe:2.3:a:lionscripts:ip_blocker_lite:*:*:*:*:*:wordpress:*:*" + ], + "ip-blacklist-cloud": [ + "cpe:2.3:a:ip_blacklist_cloud_project:ip_blacklist_cloud:*:*:*:*:*:wordpress:*:*" + ], + "ip2location-country-blocker": [ + "cpe:2.3:a:ip2location:country_blocker:*:*:*:*:*:wordpress:*:*" + ], + "ipages-flipbook": [ + "cpe:2.3:a:avirtum:ipages_flipbook:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:ipages_flipbook_project:ipages_flipbook:*:*:*:*:*:wordpress:*:*" + ], + "ipanorama-360-virtual-tour-builder-lite": [ + "cpe:2.3:a:ipanorama_360_wordpress_virtual_tour_builder_project:ipanorama_360_wordpress_virtual_tour_builder:*:*:*:*:*:wordpress:*:*" + ], + "iq-block-country": [ + "cpe:2.3:a:webence:iq_block_country:*:*:*:*:*:wordpress:*:*" + ], + "iubenda-cookie-law-solution": [ + "cpe:2.3:a:iubenda:iubenda-cookie-law-solution:*:*:*:*:*:wordpress:*:*" + ], + "iwp-client": [ + "cpe:2.3:a:revmakx:infinitewp_client:*:*:*:*:*:wordpress:*:*" + ], + "iws-geo-form-fields": [ + "cpe:2.3:a:iws-geo-form-fields_project:iws-geo-form-fields:*:*:*:*:*:wordpress:*:*" + ], + "jayj-quicktag": [ + "cpe:2.3:a:jayj_quicktag_project:jayj_quicktag:*:*:*:*:*:wordpress:*:*" + ], + "jazz-popups": [ + "cpe:2.3:a:crudlab:jazz_popups:*:*:*:*:*:wordpress:*:*" + ], + "jazzcash-woocommerce-gateway": [ + "cpe:2.3:a:jazzcash:woocommerce_jazzcash_gateway_plugin:*:*:*:*:*:wordpress:*:*" + ], + "jc-importer": [ + "cpe:2.3:a:importwp:import_wp:*:*:*:*:*:wordpress:*:*" + ], + "jch-optimize": [ + "cpe:2.3:a:jch_optimize_project:jch_optimize:*:*:*:*:*:wordpress:*:*" + ], + "jeeng-push-notifications": [ + "cpe:2.3:a:jeeng_push_notifications_project:jeeng_push_notifications:*:*:*:*:*:wordpress:*:*" + ], + "jeg-elementor-kit": [ + "cpe:2.3:a:jegtheme:jeg_elementor_kit:*:*:*:*:*:wordpress:*:*" + ], + "jetformbuilder": [ + "cpe:2.3:a:crocoblock:jetformbuilder:*:*:*:*:*:wordpress:*:*" + ], + "jetwidgets-for-elementor": [ + "cpe:2.3:a:crocoblock:jetwidgets_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "jh-404-logger": [ + "cpe:2.3:a:jh_404_logger_project:jh_404_logger:*:*:*:*:*:wordpress:*:*" + ], + "jiangqie-official-website-mini-program": [ + "cpe:2.3:a:jiangqie:official_website_mini_program:*:*:*:*:*:wordpress:*:*" + ], + "jivochat": [ + "cpe:2.3:a:jivochat:jivochat:*:*:*:*:*:wordpress:*:*" + ], + "job-board": [ + "cpe:2.3:a:bestwebsoft:job_board:*:*:*:*:*:wordpress:*:*" + ], + "job-board-vanilla": [ + "cpe:2.3:a:perceptionsystem:job_board_vanila:*:*:*:*:*:wordpress:*:*" + ], + "job-manager": [ + "cpe:2.3:a:job_manager_project:job_manager:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wp-jobmanager:job_manager:*:*:*:*:*:wordpress:*:*" + ], + "job-manager-career": [ + "cpe:2.3:a:themehigh:job_manager_\\\u0026_career:*:*:*:*:*:wordpress:*:*" + ], + "job-portal": [ + "cpe:2.3:a:job-portal_project:job-portal:*:*:*:*:*:wordpress:*:*" + ], + "job-postings": [ + "cpe:2.3:a:blueglass:jobs_for_wordpress:*:*:*:*:*:wordpress:*:*" + ], + "jobboardwp": [ + "cpe:2.3:a:ultimatemember:jobboardwp:*:*:*:*:*:wordpress:*:*" + ], + "jobwp": [ + "cpe:2.3:a:hmplugin:jobwp:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:hmplugin:wordpress_job_board_and_recruitment_plugin_-_jobwp:*:*:*:*:*:wordpress:*:*" + ], + "joli-table-of-contents": [ + "cpe:2.3:a:wpjoli:joli_table_of_contents:*:*:*:*:*:wordpress:*:*" + ], + "joomsport-sports-league-results-management": [ + "cpe:2.3:a:beardev:joomsport:*:*:*:*:*:wordpress:*:*" + ], + "jp-staticpagex": [ + "cpe:2.3:a:static_page_extended_project:static_page_extended:*:*:*:*:*:wordpress:*:*" + ], + "jquery-accordion-slideshow": [ + "cpe:2.3:a:gopiplus:jquery_accordion_slideshow:*:*:*:*:*:wordpress:*:*" + ], + "jquery-collapse-o-matic": [ + "cpe:2.3:a:twinpictures:collapse-o-matic:*:*:*:*:*:wordpress:*:*" + ], + "jquery-news-ticker": [ + "cpe:2.3:a:gopiplus:jquery_news_ticker:*:*:*:*:*:wordpress:*:*" + ], + "jquery-reply-to-comment": [ + "cpe:2.3:a:jquery-reply-to-comment_project:jquery-reply-to-comment:*:*:*:*:*:wordpress:*:*" + ], + "jquery-tagline-rotator": [ + "cpe:2.3:a:arvtard:jquery_tagline_rotator:*:*:*:*:*:wordpress:*:*" + ], + "jquery-vertical-accordion-menu": [ + "cpe:2.3:a:designchemical:jquery_accordion_menu_widget:*:*:*:*:*:wordpress:*:*" + ], + "js-css-script-optimizer": [ + "cpe:2.3:a:yevhenkotelnytskyi:js_\\\u0026_css_script_optimizer:*:*:*:*:*:wordpress:*:*" + ], + "js-jobs": [ + "cpe:2.3:a:joomsky:js_job_manager:*:*:*:*:*:wordpress:*:*" + ], + "js-support-ticket": [ + "cpe:2.3:a:joomsky:js_help_desk:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wiselyhub:js_help_desk:*:*:*:*:*:wordpress:*:*" + ], + "jsmol2wp": [ + "cpe:2.3:a:jsmol2wp_project:jsmol2wp:*:*:*:*:*:wordpress:*:*" + ], + "json-content-importer": [ + "cpe:2.3:a:json-content-importer:json_content_importer:*:*:*:*:*:wordpress:*:*" + ], + "jtrt-responsive-tables": [ + "cpe:2.3:a:jtrt_responsive_tables_project:jtrt_responsive_tables:*:*:*:*:*:wordpress:*:*" + ], + "judgeme-product-reviews-woocommerce": [ + "cpe:2.3:a:judge:product_reviews_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "juicer": [ + "cpe:2.3:a:saas.group:juicer:*:*:*:*:*:wordpress:*:*" + ], + "jupiterx-core": [ + "cpe:2.3:a:artbees:jupiter_x_core:*:*:*:*:*:wordpress:*:*" + ], + "just-tables": [ + "cpe:2.3:a:hasthemes:justtables:*:*:*:*:*:wordpress:*:*" + ], + "jvm-rich-text-icons": [ + "cpe:2.3:a:jorisvm:jvm_gutenberg_rich_text_icons:*:*:*:*:*:wordpress:*:*" + ], + "kadence-starter-templates": [ + "cpe:2.3:a:kadencewp:starter_templates:*:*:*:*:*:wordpress:*:*" + ], + "kadence-woocommerce-email-designer": [ + "cpe:2.3:a:kadencewp:kadence_woocommerce_email_designer:*:*:*:*:*:wordpress:*:*" + ], + "kali-forms": [ + "cpe:2.3:a:kaliforms:kali_forms:*:*:*:*:*:wordpress:*:*" + ], + "kama-clic-counter": [ + "cpe:2.3:a:wp-kama:kama_click_counter:*:*:*:*:*:wordpress:*:*" + ], + "kanban": [ + "cpe:2.3:a:kanbanwp:kanban_boards_for_wordpress:*:*:*:*:*:wordpress:*:*" + ], + "kangu": [ + "cpe:2.3:a:kangu:kangu:*:*:*:*:*:wordpress:*:*" + ], + "kau-boys-backend-localization": [ + "cpe:2.3:a:kau-boys:backend_localization:*:*:*:*:*:wordpress:*:*" + ], + "kb-support": [ + "cpe:2.3:a:liquidweb:kb_support:*:*:*:*:*:wordpress:*:*" + ], + "keep-backup-daily": [ + "cpe:2.3:a:androidbubbles:keep_backup_daily:*:*:*:*:*:wordpress:*:*" + ], + "kento-post-view-counter": [ + "cpe:2.3:a:kentothemes:kento-post-view-counter:*:*:*:*:*:wordpress:*:*" + ], + "ketchup-restaurant-reservations": [ + "cpe:2.3:a:ketchup_restaurant_reservations_project:ketchup_restaurant_reservations:*:*:*:*:*:wordpress:*:*" + ], + "keyword-meta": [ + "cpe:2.3:a:keyword_meta_project:keyword_meta:*:*:*:*:*:wordpress:*:*" + ], + "kitestudio-core": [ + "cpe:2.3:a:kitestudio:core_plugin_for_kitestudio_themes:*:*:*:*:*:wordpress:*:*" + ], + "kivicare-clinic-management-system": [ + "cpe:2.3:a:iqonic:kivicare:*:*:*:*:*:wordpress:*:*" + ], + "kiwi-logo-carousel": [ + "cpe:2.3:a:kiwi-logo-carousel_project:kiwi-logo-carousel:*:*:*:*:*:wordpress:*:*" + ], + "kjm-admin-notices": [ + "cpe:2.3:a:kajoom:kjm_admin_notices:*:*:*:*:*:wordpress:*:*" + ], + "kk-star-ratings": [ + "cpe:2.3:a:kamalkhan:kk_star_ratings:*:*:*:*:*:wordpress:*:*" + ], + "klaviyo": [ + "cpe:2.3:a:klaviyo:klavio:*:*:*:*:*:wordpress:*:*" + ], + "kodex-posts-likes": [ + "cpe:2.3:a:pierros:kodex_posts_likes:*:*:*:*:*:wordpress:*:*" + ], + "koko-analytics": [ + "cpe:2.3:a:ibericode:koko_analytics:*:*:*:*:*:wordpress:*:*" + ], + "konnichiwa": [ + "cpe:2.3:a:calendarscripts:konnichiwa:*:*:*:*:*:wordpress:*:*" + ], + "korea-sns": [ + "cpe:2.3:a:icansoft:korea_sns:*:*:*:*:*:wordpress:*:*" + ], + "kp-fastest-tawk-to-chat": [ + "cpe:2.3:a:kreativopro:kp_fastest_tawk.to_chat:*:*:*:*:*:wordpress:*:*" + ], + "kraken-image-optimizer": [ + "cpe:2.3:a:kraken:kraken.io_image_optimizer:*:*:*:*:*:wordpress:*:*" + ], + "kunze-law": [ + "cpe:2.3:a:kunze-medien:kunze_law:*:*:*:*:*:wordpress:*:*" + ], + "kwayy-html-sitemap": [ + "cpe:2.3:a:kwayyinfotech:kwayy_html_sitemap:*:*:*:*:*:wordpress:*:*" + ], + "labtools": [ + "cpe:2.3:a:creativityjuice:labtools:*:*:*:*:*:wordpress:*:*" + ], + "lana-downloads-manager": [ + "cpe:2.3:a:lana:lana_downloads_manager:*:*:*:*:*:wordpress:*:*" + ], + "lana-email-logger": [ + "cpe:2.3:a:lanacodes:lana_email_logger:*:*:*:*:*:wordpress:*:*" + ], + "lana-text-to-image": [ + "cpe:2.3:a:lanacodes:lana_text_to_image:*:*:*:*:*:wordpress:*:*" + ], + "landing-pages": [ + "cpe:2.3:a:inboundnow:landing-pages:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:inboundnow:wordpress_landing_pages:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:landing_pages_project:landing_pages:*:*:*:*:*:wordpress:*:*" + ], + "language-bar-flags": [ + "cpe:2.3:a:language_bar_flags_project:language_bar_flags:*:*:*:*:*:wordpress:*:*" + ], + "laposta-signup-basic": [ + "cpe:2.3:a:laposta:laposta_signup_basic:*:*:*:*:*:wordpress:*:*" + ], + "lara-google-analytics": [ + "cpe:2.3:a:lara\\'s_google_analytics_project:lara\\'s_google_analytics:*:*:*:*:*:wordpress:*:*" + ], + "lastudio-element-kit": [ + "cpe:2.3:a:la-studioweb:element_kit_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "latest-tweets-widget": [ + "cpe:2.3:a:latest_tweets_widget_project:latest_tweets_widget:*:*:*:*:*:wordpress:*:*" + ], + "launcher": [ + "cpe:2.3:a:mythemeshop:launcher:*:*:*:*:*:wordpress:*:*" + ], + "launchpad-by-obox": [ + "cpe:2.3:a:obox:launchpad_-_coming_soon_\\\u0026_maintenance_mode_plugin:*:*:*:*:*:wordpress:*:*" + ], + "lava-directory-manager": [ + "cpe:2.3:a:lava-code:lava_directory_manager:*:*:*:*:*:wordpress:*:*" + ], + "laybuy-gateway-for-woocommerce": [ + "cpe:2.3:a:laybuy:laybuy_payment_extension_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "lazy-facebook-comments": [ + "cpe:2.3:a:lazy_social_comments_project:lazy_social_comments:*:*:*:*:*:wordpress:*:*" + ], + "lazy-load-for-videos": [ + "cpe:2.3:a:kevinweber:lazy_load_for_videos:*:*:*:*:*:wordpress:*:*" + ], + "lbstopattack": [ + "cpe:2.3:a:laubrotel:lbstopattack:*:*:*:*:*:wordpress:*:*" + ], + "ldap-ad-staff-employee-directory-search": [ + "cpe:2.3:a:miniorange:staff_\\/_employee_business_directory_for_active_directory:*:*:*:*:*:wordpress:*:*" + ], + "ldap-login-for-intranet-sites": [ + "cpe:2.3:a:miniorange:active_directory_integration_\\/_ldap_integration:*:*:*:*:*:wordpress:*:*" + ], + "ldap-wp-login-integration-with-active-directory": [ + "cpe:2.3:a:ldap_wp_login_\\/_active_directory_integration_project:ldap_wp_login_\\/_active_directory_integration:*:*:*:*:*:wordpress:*:*" + ], + "lead-capturing-call-to-actions-by-vcita": [ + "cpe:2.3:a:vcita:contact_form_and_calls_to_action_by_vcita:*:*:*:*:*:wordpress:*:*" + ], + "lead-form-builder": [ + "cpe:2.3:a:themehunk:contact_form_\\\u0026_lead_form_elementor_builder:*:*:*:*:*:wordpress:*:*" + ], + "lead-generated": [ + "cpe:2.3:a:leadgenerated:lead_generated:*:*:*:*:*:wordpress:*:*" + ], + "leadsquared-suite": [ + "cpe:2.3:a:leadsquared:leadsquared_suite:*:*:*:*:*:wordpress:*:*" + ], + "leadster-marketing-conversacional": [ + "cpe:2.3:a:leadster:leadster:*:*:*:*:*:wordpress:*:*" + ], + "leaflet-map": [ + "cpe:2.3:a:bozdoz:leaflet_map:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:leaflet_map_project:leaflet_map:*:*:*:*:*:wordpress:*:*" + ], + "leaflet-maps-marker": [ + "cpe:2.3:a:mapsmarker:leaflet_maps_marker:*:*:*:*:*:wordpress:*:*" + ], + "league-table-lite": [ + "cpe:2.3:a:daext:league_table:*:*:*:*:*:wordpress:*:*" + ], + "leaky-paywall": [ + "cpe:2.3:a:zeen101:leaky_paywall:*:*:*:*:*:wordpress:*:*" + ], + "learn-manager": [ + "cpe:2.3:a:wplearnmanager:wp_learn_manager:*:*:*:*:*:wordpress:*:*" + ], + "learning-management-system": [ + "cpe:2.3:a:masteriyo:masteriyo:*:*:*:*:*:wordpress:*:*" + ], + "learnpress": [ + "cpe:2.3:a:thimpress:learnpress:*:*:*:*:*:wordpress:*:*" + ], + "leenkme": [ + "cpe:2.3:a:leenk:leenk.me:*:*:*:*:*:wordpress:*:*" + ], + "left-right-image-slideshow-gallery": [ + "cpe:2.3:a:gopiplus:left_right_image_slideshow_gallery:*:*:*:*:*:wordpress:*:*" + ], + "legal-pages": [ + "cpe:2.3:a:wpwax:legal_pages:*:*:*:*:*:wordpress:*:*" + ], + "letterpress": [ + "cpe:2.3:a:themeqx:letterpress:*:*:*:*:*:wordpress:*:*" + ], + "leyka": [ + "cpe:2.3:a:te-st:leyka:*:*:*:*:*:wordpress:*:*" + ], + "lgx-owl-carousel": [ + "cpe:2.3:a:logichunt:owl_carousel:*:*:*:*:*:wordpress:*:*" + ], + "lh-password-changer": [ + "cpe:2.3:a:shawfactor:lh-password-changer:*:*:*:*:*:wordpress:*:*" + ], + "library-viewer": [ + "cpe:2.3:a:pexlechris:library_viewer:*:*:*:*:*:wordpress:*:*" + ], + "libsyn-podcasting": [ + "cpe:2.3:a:libsyn:libsyn_publisher_hub:*:*:*:*:*:wordpress:*:*" + ], + "license-manager-for-woocommerce": [ + "cpe:2.3:a:wpexperts:license_manager_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "lifterlms": [ + "cpe:2.3:a:lifterlms:lifterlms:*:*:*:*:*:wordpress:*:*" + ], + "light-messages": [ + "cpe:2.3:a:light_messages_project:light_messages:*:*:*:*:*:wordpress:*:*" + ], + "lightbox-gallery": [ + "cpe:2.3:a:wpgogo:lightbox-gallery:*:*:*:*:*:wordpress:*:*" + ], + "lightbox-plus": [ + "cpe:2.3:a:23systems:lightbox_plus_colorbox:*:*:*:*:*:wordpress:*:*" + ], + "lightbox-popup": [ + "cpe:2.3:a:wpdevart:download_image_and_video_lightbox\\,_image_popup:*:*:*:*:*:wordpress:*:*" + ], + "lightweight-accordion": [ + "cpe:2.3:a:smartwp:lightweight_accordion:*:*:*:*:*:wordpress:*:*" + ], + "likebtn-like-button": [ + "cpe:2.3:a:likebtn:like_button_rating:*:*:*:*:*:wordpress:*:*" + ], + "limb-gallery": [ + "cpe:2.3:a:limbcode:limb-gallery:*:*:*:*:*:wordpress:*:*" + ], + "limit-attempts": [ + "cpe:2.3:a:bestwebsoft:limit_attempts:*:*:*:*:*:wordpress:*:*" + ], + "limit-login-attempts": [ + "cpe:2.3:a:limit_login_attempts_project:limit_login_attempts:*:*:*:*:*:wordpress:*:*" + ], + "limit-login-attempts-reloaded": [ + "cpe:2.3:a:limitloginattempts:limit_login_attempts_reloaded:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:miniorange:limit_login_attempts:*:*:*:*:*:wordpress:*:*" + ], + "link-juice-keeper": [ + "cpe:2.3:a:link_juice_keeper_project:link_juice_keeper:*:*:*:*:*:wordpress:*:*" + ], + "link-library": [ + "cpe:2.3:a:link_library_project:link_library:*:*:*:*:*:wordpress:*:*" + ], + "link-log": [ + "cpe:2.3:a:perafox:link_log:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:petersplugins:link_log:*:*:*:*:*:wordpress:*:*" + ], + "link-optimizer-lite": [ + "cpe:2.3:a:link_optimizer_lite_project:link_optimizer_lite:*:*:*:*:*:wordpress:*:*" + ], + "linker": [ + "cpe:2.3:a:pojo:linker:*:*:*:*:*:wordpress:*:*" + ], + "linkworth-wp-plugin": [ + "cpe:2.3:a:linkworth:linkworth:*:*:*:*:*:wordpress:*:*" + ], + "liquid-speech-balloon": [ + "cpe:2.3:a:lqd:liquid_speech_balloon:*:*:*:*:*:wordpress:*:*" + ], + "list-all-posts-by-authors-nested-categories-and-titles": [ + "cpe:2.3:a:marzocca:list_all_posts_by_authors_nested_categories_and_titles:*:*:*:*:*:wordpress:*:*" + ], + "list-category-posts": [ + "cpe:2.3:a:fernandobriano:list_category_posts:*:*:*:*:*:wordpress:*:*" + ], + "litespeed-cache": [ + "cpe:2.3:a:litespeedtech:litespeed_cache:*:*:*:*:*:wordpress:*:*" + ], + "live-composer-page-builder": [ + "cpe:2.3:a:blueastral:page_builder\\:_live_composer:*:*:*:*:*:wordpress:*:*" + ], + "live-news-lite": [ + "cpe:2.3:a:daext:live_news:*:*:*:*:*:wordpress:*:*" + ], + "liveforms": [ + "cpe:2.3:a:w3eden:live_forms:*:*:*:*:*:wordpress:*:*" + ], + "localize-my-post": [ + "cpe:2.3:a:localize_my_post_project:localize_my_post:*:*:*:*:*:wordpress:*:*" + ], + "localize-remote-images": [ + "cpe:2.3:a:buildfail:localize_remote_images:*:*:*:*:*:wordpress:*:*" + ], + "location-weather": [ + "cpe:2.3:a:shapedplugin:location_weather:*:*:*:*:*:wordpress:*:*" + ], + "locations": [ + "cpe:2.3:a:goldplugins:locations:*:*:*:*:*:wordpress:*:*" + ], + "locations-and-areas": [ + "cpe:2.3:a:100plugins:locations_and_areas:*:*:*:*:*:wordpress:*:*" + ], + "locatoraid": [ + "cpe:2.3:a:plainware:locatoraid:*:*:*:*:*:wordpress:*:*" + ], + "loco-translate": [ + "cpe:2.3:a:loco_translate_project:loco_translate:*:*:*:*:*:wordpress:*:*" + ], + "login-as-customer-or-user": [ + "cpe:2.3:a:wp-buy:login_as_user_or_customer_\\(user_switching\\):*:*:*:*:*:wordpress:*:*" + ], + "login-block-ips": [ + "cpe:2.3:a:gunkastudios:login_block_ips:*:*:*:*:*:wordpress:*:*" + ], + "login-configurator": [ + "cpe:2.3:a:login_configurator_project:login_configurator:*:*:*:*:*:wordpress:*:*" + ], + "login-form-recaptcha": [ + "cpe:2.3:a:recaptcha_project:recaptcha:*:*:*:*:*:wordpress:*:*" + ], + "login-lockdown": [ + "cpe:2.3:a:webfactoryltd:wp_login_lockdown:*:*:*:*:*:wordpress:*:*" + ], + "login-logout-menu": [ + "cpe:2.3:a:wpbrigade:login_logout_menu:*:*:*:*:*:wordpress:*:*" + ], + "login-or-logout-menu-item": [ + "cpe:2.3:a:login_or_logout_menu_item_project:login_or_logout_menu_item:*:*:*:*:*:wordpress:*:*" + ], + "login-screen-manager": [ + "cpe:2.3:a:nazmulhossainnihal:login_screen_manager:*:*:*:*:*:wordpress:*:*" + ], + "login-sidebar-widget": [ + "cpe:2.3:a:login_widget_with_shortcode_project:login_widget_with_shortcode:*:*:*:*:*:wordpress:*:*" + ], + "login-with-phone-number": [ + "cpe:2.3:a:idehweb:login_with_phone_number:*:*:*:*:*:wordpress:*:*" + ], + "loginizer": [ + "cpe:2.3:a:loginizer:loginizer:*:*:*:*:*:wordpress:*:*" + ], + "loginpress": [ + "cpe:2.3:a:wpbrigade:loginpress:*:*:*:*:*:wordpress:*:*" + ], + "logo-carousel-free": [ + "cpe:2.3:a:shapedplugin:logo_carousel:*:*:*:*:*:wordpress:*:*" + ], + "logo-scheduler-great-for-holidays-events-and-more": [ + "cpe:2.3:a:allmywebneeds:logo_scheduler:*:*:*:*:*:wordpress:*:*" + ], + "logo-showcase-with-slick-slider": [ + "cpe:2.3:a:infornweb:logo_showcase_with_slick_slider:*:*:*:*:*:wordpress:*:*" + ], + "logo-slider": [ + "cpe:2.3:a:logo_slider_project:logo_slider:*:*:*:*:*:wordpress:*:*" + ], + "logo-slider-wp": [ + "cpe:2.3:a:logichunt:logo_slider:*:*:*:*:*:wordpress:*:*" + ], + "logwpmail": [ + "cpe:2.3:a:premierethemes:log_wp_mail:*:*:*:*:*:wordpress:*:*" + ], + "lws-cleaner": [ + "cpe:2.3:a:lws:lws_cleaner:*:*:*:*:*:wordpress:*:*" + ], + "lws-hide-login": [ + "cpe:2.3:a:lws:lws_hide_login:*:*:*:*:*:wordpress:*:*" + ], + "lws-tools": [ + "cpe:2.3:a:lws:lws_tools:*:*:*:*:*:wordpress:*:*" + ], + "m-chart": [ + "cpe:2.3:a:m_chart_project:m_chart:*:*:*:*:*:wordpress:*:*" + ], + "m-vslider": [ + "cpe:2.3:a:nimble3:m-vslider:*:*:*:*:*:wordpress:*:*" + ], + "m-wp-popup": [ + "cpe:2.3:a:custom_popup_builder_project:custom_popup_builder:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:popup_\\|_custom_popup_builder_project:popup_\\|_custom_popup_builder:*:*:*:*:*:wordpress:*:*" + ], + "mage-eventpress": [ + "cpe:2.3:a:mage-people:event_manager_and_tickets_selling_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "magee-shortcodes": [ + "cpe:2.3:a:hoosoft:magee_shortcodes:*:*:*:*:*:wordpress:*:*" + ], + "magic-action-box": [ + "cpe:2.3:a:pogidude:magic_action_box:*:*:*:*:*:wordpress:*:*" + ], + "magic-post-thumbnail": [ + "cpe:2.3:a:magic-post-thumbnail:magic_post_thumbnail:*:*:*:*:*:wordpress:*:*" + ], + "mail-control": [ + "cpe:2.3:a:instareza:mail_control:*:*:*:*:*:wordpress:*:*" + ], + "mail-integration-365": [ + "cpe:2.3:a:wpo365:mail_integration_for_office_365_\\/_outlook:*:*:*:*:*:wordpress:*:*" + ], + "mail-queue": [ + "cpe:2.3:a:webdesignmunich:mail_queue:*:*:*:*:*:wordpress:*:*" + ], + "mail-subscribe-list": [ + "cpe:2.3:a:webfwd:mail_subscribe_list:*:*:*:*:*:wordpress:*:*" + ], + "mailarchiver": [ + "cpe:2.3:a:perfopsone:mailarchiver:*:*:*:*:*:wordpress:*:*" + ], + "mailchimp-for-woocommerce": [ + "cpe:2.3:a:mailchimp:mailchimp_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "mailchimp-for-wp": [ + "cpe:2.3:a:ibericode:mailchimp:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:mailchimp_for_wordpress_project:mailchimp_for_wordpress:*:*:*:*:*:wordpress:*:*" + ], + "mailchimp-forms-by-mailmunch": [ + "cpe:2.3:a:mailmunch:mailchimp_forms:*:*:*:*:*:wordpress:*:*" + ], + "mailchimp-subscribe-sm": [ + "cpe:2.3:a:pluginops:mailchimp_subscribe_form:*:*:*:*:*:wordpress:*:*" + ], + "mailcwp": [ + "cpe:2.3:a:mailcwp_project:mailcwp:*:*:*:*:*:wordpress:*:*" + ], + "mailin": [ + "cpe:2.3:a:sendinblue:newsletter\\,_smtp\\,_email_marketing_and_subscribe:*:*:*:*:*:wordpress:*:*" + ], + "mailmunch": [ + "cpe:2.3:a:mailmunch:mailmunch:*:*:*:*:*:wordpress:*:*" + ], + "mailoptin": [ + "cpe:2.3:a:mailoptin:mailoptin:*:*:*:*:*:wordpress:*:*" + ], + "mailpoet": [ + "cpe:2.3:a:mailpoet:mailpoet:*:*:*:*:*:wordpress:*:*" + ], + "mailtree-log-mail": [ + "cpe:2.3:a:oacstudio:mailtree_log_mail:*:*:*:*:*:wordpress:*:*" + ], + "maintenance": [ + "cpe:2.3:a:webfactoryltd:maintenance:*:*:*:*:*:wordpress:*:*" + ], + "mainwp": [ + "cpe:2.3:a:mainwp:mainwp_dashboard:*:*:*:*:*:wordpress:*:*" + ], + "mainwp-child": [ + "cpe:2.3:a:mainwp:mainwp_child:*:*:*:*:*:wordpress:*:*" + ], + "mainwp-child-reports": [ + "cpe:2.3:a:mainwp:mainwp_child_reports:*:*:*:*:*:wordpress:*:*" + ], + "make-paths-relative": [ + "cpe:2.3:a:yasglobal:make_paths_relative:*:*:*:*:*:wordpress:*:*" + ], + "makestories-helper": [ + "cpe:2.3:a:makestories:makestories_\\(for_google_web_stories\\):*:*:*:*:*:wordpress:*:*" + ], + "malinky-ajax-pagination": [ + "cpe:2.3:a:malinky:malinky-ajax-pagination:*:*:*:*:*:wordpress:*:*" + ], + "manage-notification-emails": [ + "cpe:2.3:a:freeamigos:manage_notification_e-mails:*:*:*:*:*:wordpress:*:*" + ], + "manage-shipyaari-shipping": [ + "cpe:2.3:a:shipyaari:shipping_management:*:*:*:*:*:wordpress:*:*" + ], + "mangboard": [ + "cpe:2.3:a:mangboard:mang_board:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:mangboard:mangboard_wp:*:*:*:*:basic:wordpress:*:*" + ], + "mantenimiento-web": [ + "cpe:2.3:a:webartesanal:mantenimiento_web:*:*:*:*:*:wordpress:*:*" + ], + "manual-image-crop": [ + "cpe:2.3:a:manual_image_crop_project:manual_image_crop:*:*:*:*:*:wordpress:*:*" + ], + "mapping-multiple-urls-redirect-same-page": [ + "cpe:2.3:a:mapping_multiple_urls_redirect_same_page_project:mapping_multiple_urls_redirect_same_page:*:*:*:*:*:wordpress:*:*" + ], + "mappress-google-maps-for-wordpress": [ + "cpe:2.3:a:mappresspro:mappress:*:*:*:*:free:wordpress:*:*", + "cpe:2.3:a:mappresspro:mappress:*:*:*:*:pro:wordpress:*:*", + "cpe:2.3:a:mappresspro:mappress_maps_for_wordpress:*:*:*:*:*:wordpress:*:*" + ], + "mapster-wp-maps": [ + "cpe:2.3:a:mapster:mapster_wp_maps:*:*:*:*:*:wordpress:*:*" + ], + "mapsvg-lite-interactive-vector-maps": [ + "cpe:2.3:a:mapsvg:mapsvg_lite:*:*:*:*:*:wordpress:*:*" + ], + "mapwiz": [ + "cpe:2.3:a:conceptbeans:mapwiz:*:*:*:*:*:wordpress:*:*" + ], + "mark-posts": [ + "cpe:2.3:a:mark_posts_project:mark_posts:*:*:*:*:*:wordpress:*:*" + ], + "mark-user-as-spammer": [ + "cpe:2.3:a:mark_user_as_spammer_project:mark_user_as_spammer:*:*:*:*:*:wordpress:*:*" + ], + "markdown-on-save-improved": [ + "cpe:2.3:a:markdown_on_save_improved_project:markdown_on_save_improved:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:markdown_on_saved_improved_project:markdown_on_saved_improved:*:*:*:*:*:wordpress:*:*" + ], + "market-exporter": [ + "cpe:2.3:a:vanyukov:market_exporter:*:*:*:*:*:wordpress:*:*" + ], + "marketo-forms-and-tracking": [ + "cpe:2.3:a:hutchhouse:marketo_forms_and_tracking:*:*:*:*:*:wordpress:*:*" + ], + "marmoset-viewer": [ + "cpe:2.3:a:marmoset:marmoset_viewer:*:*:*:*:*:wordpress:*:*" + ], + "martins-link-network": [ + "cpe:2.3:a:martinstools:free_\\\u0026_easy_link_building:*:*:*:*:*:wordpress:*:*" + ], + "mashsharer": [ + "cpe:2.3:a:social_media_share_buttons_project:social_media_share_buttons:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpchill:mashshare:*:*:*:*:*:wordpress:*:*" + ], + "mass-pagesposts-creator": [ + "cpe:2.3:a:dotstore:mass_pages\\/posts_creator:*:*:*:*:*:wordpress:*:*" + ], + "master-addons": [ + "cpe:2.3:a:master-addons:master_addons:*:*:*:*:*:wordpress:*:*" + ], + "master-slider": [ + "cpe:2.3:a:averta:master_slider:*:*:*:*:*:wordpress:*:*" + ], + "masterstudy-lms-learning-management-system": [ + "cpe:2.3:a:stylemixthemes:masterstudy_lms:*:*:*:*:*:wordpress:*:*" + ], + "material-design-for-contact-form-7": [ + "cpe:2.3:a:material_design_for_contact_form_7_project:material_design_for_contact_form_7:*:*:*:*:*:wordpress:*:*" + ], + "material-design-icons-for-elementor": [ + "cpe:2.3:a:material_design_icons_for_page_builders_project:material_design_icons_for_page_builders:*:*:*:*:*:wordpress:*:*" + ], + "matrix-pre-loader": [ + "cpe:2.3:a:nkb-bd:preloader_matrix:*:*:*:*:*:wordpress:*:*" + ], + "maxbuttons": [ + "cpe:2.3:a:maxfoundry:maxbuttons:*:*:*:*:*:wordpress:*:*" + ], + "maz-loader": [ + "cpe:2.3:a:feataholic:maz_loader:*:*:*:*:*:wordpress:*:*" + ], + "mdc-youtube-downloader": [ + "cpe:2.3:a:mdc_youtube_downloader_project:mdc_youtube_downloader:*:*:*:*:*:wordpress:*:*" + ], + "media-downloader": [ + "cpe:2.3:a:media_downloader_project:media_downloader:*:*:*:*:*:wordpress:*:*" + ], + "media-file-manager": [ + "cpe:2.3:a:media_file_manager_project:media_file_manager:*:*:*:*:*:wordpress:*:*" + ], + "media-file-organizer": [ + "cpe:2.3:a:media_file_organizer_project:media_file_organizer:*:*:*:*:*:wordpress:*:*" + ], + "media-file-renamer": [ + "cpe:2.3:a:meowapps:media_file_renamer_-_auto_\\\u0026_manual_rename:*:*:*:*:*:wordpress:*:*" + ], + "media-from-ftp": [ + "cpe:2.3:a:media_from_ftp_project:media_from_ftp:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:riverforest-wp:media_from_ftp:*:*:*:*:*:wordpress:*:*" + ], + "media-library-assistant": [ + "cpe:2.3:a:davidlingren:media_library_assistant:*:*:*:*:*:wordpress:*:*" + ], + "media-library-plus": [ + "cpe:2.3:a:maxfoundry:media_library_folders:*:*:*:*:*:wordpress:*:*" + ], + "media-list": [ + "cpe:2.3:a:drelton:medialist:*:*:*:*:*:wordpress:*:*" + ], + "media-usage": [ + "cpe:2.3:a:meowapps:media_usage:*:*:*:*:*:wordpress:*:*" + ], + "mediaburst-ecommerce-sms-notifications": [ + "cpe:2.3:a:mediaburst:wp_e-commerce:*:*:*:*:*:wordpress:*:*" + ], + "mediaburst-email-to-sms": [ + "cpe:2.3:a:mediaburst:clockwork_sms_notfications:*:*:*:*:*:wordpress:*:*" + ], + "mediamatic": [ + "cpe:2.3:a:frenify:mediamatic:*:*:*:*:*:wordpress:*:*" + ], + "mediavine-control-panel": [ + "cpe:2.3:a:mediavine:mediavine_control_panel:*:*:*:*:*:wordpress:*:*" + ], + "meeting-scheduler-by-vcita": [ + "cpe:2.3:a:vcita:online_booking_\\\u0026_scheduling_calendar_for_wordpress:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:vcita:online_booking_\\\u0026_scheduling_calendar_for_wordpress_by_vcita:*:*:*:*:*:wordpress:*:*" + ], + "mega-addons-for-visual-composer": [ + "cpe:2.3:a:topdigitaltrends:mega_addons_for_wpbakery_page_builder:*:*:*:*:*:wordpress:*:*" + ], + "megamenu": [ + "cpe:2.3:a:megamenu:max_mega_menu:*:*:*:*:*:wordpress:*:*" + ], + "meks-audio-player": [ + "cpe:2.3:a:mekshq:meks_audio_player:*:*:*:*:*:wordpress:*:*" + ], + "meks-easy-instagram-widget": [ + "cpe:2.3:a:mekshq:meks_easy_photo_feed_widget:*:*:*:*:*:wordpress:*:*" + ], + "meks-flexible-shortcodes": [ + "cpe:2.3:a:mekshq:meks_flexible_shortcodes:*:*:*:*:*:wordpress:*:*" + ], + "meks-smart-social-widget": [ + "cpe:2.3:a:mekshq:meks_smart_social_widget:*:*:*:*:*:wordpress:*:*" + ], + "melapress-login-security": [ + "cpe:2.3:a:melapress:melapress_login_security:*:*:*:*:*:wordpress:*:*" + ], + "member-hero": [ + "cpe:2.3:a:memberhero:member_hero:*:*:*:*:*:wordpress:*:*" + ], + "memberlite-shortcodes": [ + "cpe:2.3:a:strangerstudios:memberlite_shortcodes:*:*:*:*:*:wordpress:*:*" + ], + "members-import": [ + "cpe:2.3:a:youngtechleads:members_import:*:*:*:*:*:wordpress:*:*" + ], + "membership-simplified-for-oap-members-only": [ + "cpe:2.3:a:membership_simplified_project:membership_simplified:*:*:*:*:*:wordpress:*:*" + ], + "memphis-documents-library": [ + "cpe:2.3:a:memphis_documents_library_project:memphis_documents_library:*:*:*:*:*:wordpress:*:*" + ], + "mendeleyplugin": [ + "cpe:2.3:a:kochm:mendeley_plugin:*:*:*:*:*:wordpress:*:*" + ], + "menu-image": [ + "cpe:2.3:a:freshlightlab:menu_image\\,_icons_made_easy:*:*:*:*:*:wordpress:*:*" + ], + "menu-items-visibility-control": [ + "cpe:2.3:a:menu_item_visibility_control_project:menu_item_visibility_control:*:*:*:*:*:wordpress:*:*" + ], + "menu-ordering-reservations": [ + "cpe:2.3:a:oracle:restaurant_menu_-_food_ordering_system_-_table_reservation:*:*:*:*:*:wordpress:*:*" + ], + "menu-shortcode": [ + "cpe:2.3:a:menu_shortcode_project:menu_shortcode:*:*:*:*:*:wordpress:*:*" + ], + "menu-swapper": [ + "cpe:2.3:a:menu_swapper_project:menu_swapper:*:*:*:*:*:wordpress:*:*" + ], + "menubar": [ + "cpe:2.3:a:dontdream:menubar:*:*:*:*:*:wordpress:*:*" + ], + "meow-gallery": [ + "cpe:2.3:a:meowapps:meow_gallery:*:*:*:*:*:wordpress:*:*" + ], + "mesmerize-companion": [ + "cpe:2.3:a:extendthemes:mesmerize_companion:*:*:*:*:*:wordpress:*:*" + ], + "message-ticker": [ + "cpe:2.3:a:gopiplus:message_ticker:*:*:*:*:*:wordpress:*:*" + ], + "meteor-slides": [ + "cpe:2.3:a:meteor_slides_project:meteor_slides:*:*:*:*:*:wordpress:*:*" + ], + "metform": [ + "cpe:2.3:a:wpmet:metform_elementor_contact_form_builder:*:*:*:*:*:wordpress:*:*" + ], + "metricool": [ + "cpe:2.3:a:metricool:metricool:*:*:*:*:*:wordpress:*:*" + ], + "metronet-profile-picture": [ + "cpe:2.3:a:cozmoslabs:user_profile_picture:*:*:*:*:*:wordpress:*:*" + ], + "metronet-tag-manager": [ + "cpe:2.3:a:mediaron:metronet_tag_manager:*:*:*:*:*:wordpress:*:*" + ], + "mf-gig-calendar": [ + "cpe:2.3:a:mf_gig_calendar_project:mf_gig_calendar:*:*:*:*:*:wordpress:*:*" + ], + "microblog-poster": [ + "cpe:2.3:a:efficientscripts:microblog_poster:*:*:*:*:*:wordpress:*:*" + ], + "microcopy": [ + "cpe:2.3:a:activemedia:microcopy:*:*:*:*:*:wordpress:*:*" + ], + "microsoft-advertising-universal-event-tracking-uet": [ + "cpe:2.3:a:microsoft:microsoft_advertising_universal_event_tracking:*:*:*:*:*:wordpress:*:*" + ], + "microsoft-clarity": [ + "cpe:2.3:a:microsoft:clarity:*:*:*:*:*:wordpress:*:*" + ], + "mihdan-index-now": [ + "cpe:2.3:a:kobzarev:index_now:*:*:*:*:*:wordpress:*:*" + ], + "mini-mail-dashboard-widget": [ + "cpe:2.3:a:mini_mail_dashboard_widget_project:mini_mail_dashboard_widget:*:*:*:*:*:wordpress:*:*" + ], + "minimal-coming-soon-maintenance-mode": [ + "cpe:2.3:a:webfactoryltd:minimal_coming_soon_\\\u0026_maintenance_mode:*:*:*:*:*:wordpress:*:*" + ], + "miniorange-2-factor-authentication": [ + "cpe:2.3:a:miniorange:google_authenticator:*:*:*:*:*:wordpress:*:*" + ], + "miniorange-login-openid": [ + "cpe:2.3:a:miniorange:wordpress_social_login_and_register_\\(discord\\,_google\\,_twitter\\,_linkedin\\):*:*:*:*:*:wordpress:*:*" + ], + "miniorange-login-with-eve-online-google-facebook": [ + "cpe:2.3:a:miniorange:oauth_single_sign_on:*:*:*:*:*:wordpress:*:*" + ], + "miniorange-oauth-20-server": [ + "cpe:2.3:a:miniorange:wp_oauth_server:*:*:*:*:*:wordpress:*:*" + ], + "miniorange-saml-20-single-sign-on": [ + "cpe:2.3:a:miniorange:saml_sp_single_sign_on:*:*:*:*:*:wordpress:*:*" + ], + "miniorange-wp-as-saml-idp": [ + "cpe:2.3:a:miniorange:login_using_wordpress_users:*:*:*:*:*:wordpress:*:*" + ], + "ml-slider": [ + "cpe:2.3:a:metaslider:slider\\,_gallery\\,_and_carousel:*:*:*:*:*:wordpress:*:*" + ], + "mmm-file-list": [ + "cpe:2.3:a:mediamanifesto:mmm_simple_file_list:*:*:*:*:*:wordpress:*:*" + ], + "mobile-address-bar-changer": [ + "cpe:2.3:a:anshullabs:mobile_address_bar_changer:*:*:*:*:*:wordpress:*:*" + ], + "mobile-app-builder-by-wappress": [ + "cpe:2.3:a:mobile-app-builder-by-wappress_project:mobile-app-builder-by-wappress:*:*:*:*:*:wordpress:*:*" + ], + "mobile-banner": [ + "cpe:2.3:a:robinphillips:mobile_banner:*:*:*:*:*:wordpress:*:*" + ], + "mobile-browser-color-select": [ + "cpe:2.3:a:script:mobile_browser_color_select:*:*:*:*:*:wordpress:*:*" + ], + "mobile-events-manager": [ + "cpe:2.3:a:mobile_events_manager_project:mobile_events_manager:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:mobileeventsmanager:mobile_events_manager:*:*:*:*:*:wordpress:*:*" + ], + "mobile-login-woocommerce": [ + "cpe:2.3:a:xootix:otp_login_woocommerce_\\\u0026_gravity_forms:*:*:*:*:*:wordpress:*:*" + ], + "modal-dialog": [ + "cpe:2.3:a:modal_dialog_project:modal_dialog:*:*:*:*:*:wordpress:*:*" + ], + "modal-window": [ + "cpe:2.3:a:wow-company:modal_window:*:*:*:*:*:wordpress:*:*" + ], + "modern-events-calendar-lite": [ + "cpe:2.3:a:webnus:modern_events_calendar_lite:*:*:*:*:*:wordpress:*:*" + ], + "modern-footnotes": [ + "cpe:2.3:a:prismtechstudios:modern_footnotes:*:*:*:*:*:wordpress:*:*" + ], + "modula-best-grid-gallery": [ + "cpe:2.3:a:machothemes:modula_image_gallery:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpchill:customizable_wordpress_gallery_plugin_-_modula_image_gallery:*:*:*:*:*:wordpress:*:*" + ], + "molie-instructure-canvas-linking-tool": [ + "cpe:2.3:a:molie_instructure_canvas_linking_tool_project:molie_instructure_canvas_linking_tool:*:*:*:*:*:wordpress:*:*" + ], + "mollie-forms": [ + "cpe:2.3:a:wobbie:mollie_forms:*:*:*:*:*:wordpress:*:*" + ], + "molongui-authorship": [ + "cpe:2.3:a:amitzy:molongui_authorship:*:*:*:*:*:wordpress:*:*" + ], + "monetize": [ + "cpe:2.3:a:monetize_project:monetize:*:*:*:*:*:wordpress:*:*" + ], + "montonio-for-woocommerce": [ + "cpe:2.3:a:montonio:montonio_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "moolamojo": [ + "cpe:2.3:a:kibokolabs:moolamojo:*:*:*:*:*:wordpress:*:*" + ], + "moova-for-woocommerce": [ + "cpe:2.3:a:moova:moova_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "moreads-se": [ + "cpe:2.3:a:lamp-solutions:moreads_se:*:*:*:*:*:wordpress:*:*" + ], + "morpheus-slider": [ + "cpe:2.3:a:webpsilon:responsive_3d_slider:*:*:*:*:*:wordpress:*:*" + ], + "mortgage-calculators-wp": [ + "cpe:2.3:a:lenderd:mortgage_calculators_wp:*:*:*:*:*:wordpress:*:*" + ], + "most-and-least-read-posts-widget": [ + "cpe:2.3:a:whiletrue:most_and_least_read_posts_widget:*:*:*:*:*:wordpress:*:*" + ], + "most-popular-posts-widget-lite": [ + "cpe:2.3:a:smartfan:most_popular_posts_widget:*:*:*:*:*:wordpress:*:*" + ], + "motopress-hotel-booking-lite": [ + "cpe:2.3:a:motopress:hotel_booking_lite:*:*:*:*:*:wordpress:*:*" + ], + "motopress-slider-lite": [ + "cpe:2.3:a:motopress:motopress-slider-lite:*:*:*:*:*:wordpress:*:*" + ], + "motor-racing-league": [ + "cpe:2.3:a:motor_racing_league_project:motor_racing_league:*:*:*:*:*:wordpress:*:*" + ], + "motors-car-dealership-classified-listings": [ + "cpe:2.3:a:stylemixthemes:motors_-_car_dealer\\,_classifieds_\\\u0026_listing:*:*:*:*:*:wordpress:*:*" + ], + "mousewheel-smooth-scroll": [ + "cpe:2.3:a:mousewheel_smooth_scroll_project:mousewheel_smooth_scroll:*:*:*:*:*:wordpress:*:*" + ], + "move-addons": [ + "cpe:2.3:a:moveaddons:move_addons_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "movies": [ + "cpe:2.3:a:movies_project:movies:*:*:*:*:*:wordpress:*:*" + ], + "mp-restaurant-menu": [ + "cpe:2.3:a:motopress:restaurant_menu:*:*:*:*:*:wordpress:*:*" + ], + "mp-timetable": [ + "cpe:2.3:a:motopress:timetable_and_event_schedule:*:*:*:*:*:wordpress:*:*" + ], + "mp3-jplayer": [ + "cpe:2.3:a:mp3-jplayer_project:mp3-jplayer:*:*:*:*:*:wordpress:*:*" + ], + "mp3-music-player-by-sonaar": [ + "cpe:2.3:a:sonaar:mp3_audio_player_for_music\\,_radio_\\\u0026_podcast:*:*:*:*:*:wordpress:*:*" + ], + "mpl-publisher": [ + "cpe:2.3:a:mpl-publisher_project:mpl-publisher:*:*:*:*:*:wordpress:*:*" + ], + "mpoperationlogs": [ + "cpe:2.3:a:mrpeng:mpoperationlogs:*:*:*:*:*:wordpress:*:*" + ], + "mq-woocommerce-products-price-bulk-edit": [ + "cpe:2.3:a:mq-woocommerce-products-price-bulk-edit_project:mq-woocommerce-products-price-bulk-edit:*:*:*:*:*:wordpress:*:*" + ], + "ms-reviews": [ + "cpe:2.3:a:ms-reviews_project:ms-reviews:*:*:*:*:*:wordpress:*:*" + ], + "mshop-mysite": [ + "cpe:2.3:a:codemshop:mshop_my_site:*:*:*:*:*:wordpress:*:*" + ], + "mstore-api": [ + "cpe:2.3:a:inspireui:mstore_api:*:*:*:*:*:wordpress:*:*" + ], + "mtouch-quiz": [ + "cpe:2.3:a:mtouch_quiz_project:mtouch_quiz:*:*:*:*:*:wordpress:*:*" + ], + "mts-url-shortener": [ + "cpe:2.3:a:mythemeshop:url_shortener:*:*:*:*:*:wordpress:*:*" + ], + "multi-column-tag-map": [ + "cpe:2.3:a:multi-column_tag_map_project:multi-column_tag_map:*:*:*:*:*:wordpress:*:*" + ], + "multi-feed-reader": [ + "cpe:2.3:a:multi_feed_reader_project:multi_feed_reader:*:*:*:*:*:wordpress:*:*" + ], + "multi-page-toolkit": [ + "cpe:2.3:a:multi-page_toolkit_project:multi-page_toolkit:*:*:*:*:*:wordpress:*:*" + ], + "multi-rating": [ + "cpe:2.3:a:danielpowney:multi_rating:*:*:*:*:*:wordpress:*:*" + ], + "multi-step-form": [ + "cpe:2.3:a:mondula:multi_step_form:*:*:*:*:*:wordpress:*:*" + ], + "multicons": [ + "cpe:2.3:a:doc4design:multicons:*:*:*:*:*:wordpress:*:*" + ], + "multilanguage": [ + "cpe:2.3:a:bestwebsoft:multilanguage:*:*:*:*:*:wordpress:*:*" + ], + "multiparcels-shipping-for-woocommerce": [ + "cpe:2.3:a:multiparcels:multiparcels_shipping_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "multiplayer-plugin": [ + "cpe:2.3:a:multiplayer-plugin_project:multiplayer-plugin:*:*:*:*:*:wordpress:*:*" + ], + "multiple-pages-generator-by-porthas": [ + "cpe:2.3:a:themeisle:multiple_page_generator:*:*:*:*:*:wordpress:*:*" + ], + "multiple-post-passwords": [ + "cpe:2.3:a:andreasmuench:multiple_post_passwords:*:*:*:*:*:wordpress:*:*" + ], + "multiple-roles": [ + "cpe:2.3:a:multiple_roles_project:multiple_roles:*:*:*:*:*:wordpress:*:*" + ], + "multisafepay": [ + "cpe:2.3:a:multisafepay:multisafepay_plugin_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "multisite-post-duplicator": [ + "cpe:2.3:a:wpmaz:multisite_post_duplicator:*:*:*:*:*:wordpress:*:*" + ], + "music-store": [ + "cpe:2.3:a:codepeople:music_store:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:musicstore:music_store:*:*:*:*:*:wordpress:*:*" + ], + "mw-wp-form": [ + "cpe:2.3:a:web-soudan:mw_wp_form:*:*:*:*:*:wordpress:*:*" + ], + "mwp-countdown": [ + "cpe:2.3:a:wow-company:wow_countdowns:*:*:*:*:*:wordpress:*:*" + ], + "mwp-forms": [ + "cpe:2.3:a:wow-company:wow_forms:*:*:*:*:*:wordpress:*:*" + ], + "mwp-herd-effect": [ + "cpe:2.3:a:wow-company:herd_effects:*:*:*:*:*:wordpress:*:*" + ], + "mwp-skype": [ + "cpe:2.3:a:wow-company:wow_skype_buttons:*:*:*:*:*:wordpress:*:*" + ], + "mx-time-zone-clocks": [ + "cpe:2.3:a:mx_time_zone_clocks_project:mx_time_zone_clocks:*:*:*:*:*:wordpress:*:*" + ], + "my-calendar": [ + "cpe:2.3:a:joedolson:my_calendar:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:my_calendar_project:my_calendar:*:*:*:*:*:wordpress:*:*" + ], + "my-content-management": [ + "cpe:2.3:a:joedolson:my_content_management:*:*:*:*:*:wordpress:*:*" + ], + "my-tickets": [ + "cpe:2.3:a:my_tickets_project:my_tickets:*:*:*:*:*:wordpress:*:*" + ], + "my-wish-list": [ + "cpe:2.3:a:nlb-creationst:my_wish_list:*:*:*:*:*:wordpress:*:*" + ], + "my-wp-health-check": [ + "cpe:2.3:a:sitealert:sitealert:*:*:*:*:*:wordpress:*:*" + ], + "my-wp-translate": [ + "cpe:2.3:a:mythemeshop:my_wp_translate:*:*:*:*:*:wordpress:*:*" + ], + "my-wpdb": [ + "cpe:2.3:a:my_wpdb_project:my_wpdb:*:*:*:*:*:*:*:*" + ], + "myagileprivacy": [ + "cpe:2.3:a:myagileprivacy:my_agile_privacy:*:*:*:*:*:wordpress:*:*" + ], + "mybb-cross-poster": [ + "cpe:2.3:a:mybb_cross-poster_project:mybb_cross-poster:*:*:*:*:*:wordpress:*:*" + ], + "mybooktable": [ + "cpe:2.3:a:stormhillmedia:mybook_table_bookstore:*:*:*:*:*:wordpress:*:*" + ], + "mycred": [ + "cpe:2.3:a:mycred:mycred:*:*:*:*:*:wordpress:*:*" + ], + "mycryptocheckout": [ + "cpe:2.3:a:plainviewplugins:mycryptocheckout:*:*:*:*:*:wordpress:*:*" + ], + "mycurator": [ + "cpe:2.3:a:mycurator_content_curation_project:mycurator_content_curation:*:*:*:*:*:wordpress:*:*" + ], + "mypixs": [ + "cpe:2.3:a:mypixs_project:mypixs:*:*:*:*:*:wordpress:*:*" + ], + "mystickyelements": [ + "cpe:2.3:a:premio:mystickyelements:*:*:*:*:*:wordpress:*:*" + ], + "mystickymenu": [ + "cpe:2.3:a:premio:my_sticky_bar:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:premio:mystickymenu:*:*:*:*:*:wordpress:*:*" + ], + "n-media-woocommerce-checkout-fields": [ + "cpe:2.3:a:najeebmedia:woocommerce_checkout_field_manager:*:*:*:*:*:wordpress:*:*" + ], + "namaste-lms": [ + "cpe:2.3:a:kibokolabs:namaste\\!_lms:*:*:*:*:*:wordpress:*:*" + ], + "name-directory": [ + "cpe:2.3:a:name_directory_project:name_directory:*:*:*:*:*:wordpress:*:*" + ], + "navz-photo-gallery": [ + "cpe:2.3:a:navz:acf_photo_gallery_field:*:*:*:*:*:wordpress:*:*" + ], + "nd-booking": [ + "cpe:2.3:a:booking_project:booking:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:nicdark:hotel_booking:*:*:*:*:*:wordpress:*:*" + ], + "nd-donations": [ + "cpe:2.3:a:donations_project:donations:*:*:*:*:*:wordpress:*:*" + ], + "nd-learning": [ + "cpe:2.3:a:learning_courses_project:learning_courses:*:*:*:*:*:wordpress:*:*" + ], + "nd-projects": [ + "cpe:2.3:a:nicdark:cost_calculator:*:*:*:*:*:wordpress:*:*" + ], + "nd-restaurant-reservations": [ + "cpe:2.3:a:restaurant_reservations_project:restaurant_reservations:*:*:*:*:*:wordpress:*:*" + ], + "nd-shortcodes": [ + "cpe:2.3:a:components_for_wp_bakery_page_builder_project:components_for_wp_bakery_page_builder:*:*:*:*:*:*:*:*", + "cpe:2.3:a:nicdark:nd_shortcodes:*:*:*:*:*:wordpress:*:*" + ], + "nd-travel": [ + "cpe:2.3:a:travel_management_project:travel_management_:*:*:*:*:*:wordpress:*:*" + ], + "nelio-ab-testing": [ + "cpe:2.3:a:neliosoftware:nelio_ab_testing:*:*:*:*:*:wordpress:*:*" + ], + "neon-text": [ + "cpe:2.3:a:eralion:neon_text:*:*:*:*:*:wordpress:*:*" + ], + "neshan-maps": [ + "cpe:2.3:a:neshan:neshan_maps:*:*:*:*:*:wordpress:*:*" + ], + "netgsm": [ + "cpe:2.3:a:netgsm:netgsm:*:*:*:*:*:wordpress:*:*" + ], + "netreviews": [ + "cpe:2.3:a:skeepers:verified_reviews_\\(avis_verifies\\):*:*:*:*:*:wordpress:*:*" + ], + "neuvoo-jobroll": [ + "cpe:2.3:a:neuvoo:neuvoo-jobroll:*:*:*:*:*:wordpress:*:*" + ], + "new-adman": [ + "cpe:2.3:a:new_adman_project:new_adman:*:*:*:*:*:wordpress:*:*" + ], + "new-album-gallery": [ + "cpe:2.3:a:awplife:album_gallery:*:*:*:*:*:wordpress:*:*" + ], + "new-contact-form-widget": [ + "cpe:2.3:a:awplife:contact_form_widget:*:*:*:*:*:wordpress:*:*" + ], + "new-grid-gallery": [ + "cpe:2.3:a:awplife:grid_gallery:*:*:*:*:*:wordpress:*:*" + ], + "new-image-gallery": [ + "cpe:2.3:a:awplife:image_gallery:*:*:*:*:*:wordpress:*:*" + ], + "new-user-approve": [ + "cpe:2.3:a:wpexperts:new_user_approve:*:*:*:*:*:wordpress:*:*" + ], + "new-user-email-set-up": [ + "cpe:2.3:a:new_user_email_set_up_project:new_user_email_set_up:*:*:*:*:*:wordpress:*:*" + ], + "news-announcement-scroll": [ + "cpe:2.3:a:storeapps:news_announcement_scroll:*:*:*:*:*:wordpress:*:*" + ], + "newsletter": [ + "cpe:2.3:a:thenewsletterplugin:newsletter:*:*:*:*:*:wordpress:*:*" + ], + "newsletter-bulk-email": [ + "cpe:2.3:a:happybox:newsletter_\\\u0026_bulk_email_sender:*:*:*:*:*:wordpress:*:*" + ], + "newsletter-by-supsystic": [ + "cpe:2.3:a:supsystic:newsletter_by_supsystic:*:*:*:*:*:wordpress:*:*" + ], + "newsletter-optin-box": [ + "cpe:2.3:a:noptin:noptin:*:*:*:*:*:wordpress:*:*" + ], + "newsletters-lite": [ + "cpe:2.3:a:tribulant:newsletters:*:*:*:*:*:wordpress:*:*" + ], + "newsplugin": [ + "cpe:2.3:a:ipdgroup:newsplugin:*:*:*:*:*:wordpress:*:*" + ], + "newstatpress": [ + "cpe:2.3:a:newstatpress_project:newstatpress:*:*:*:*:*:wordpress:*:*" + ], + "nex-forms-express-wp-form-builder": [ + "cpe:2.3:a:basixonline:nex-forms:*:*:*:*:*:*:*:*", + "cpe:2.3:a:basixonline:nex-forms:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:nex-forms_-_ultimate_form_builder_project:nex-forms_-_ultimate_form_builder:*:*:*:*:*:wordpress:*:*" + ], + "next-page": [ + "cpe:2.3:a:stephanieleary:next_page:*:*:*:*:*:wordpress:*:*" + ], + "nextend-facebook-connect": [ + "cpe:2.3:a:nextendweb:facebook_connect:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:nextendweb:nextend_facebook_connect:*:*:*:*:*:wordpress:*:*" + ], + "nextend-twitter-connect": [ + "cpe:2.3:a:nextendweb:nextend_twitter_connect:*:*:*:*:*:wordpress:*:*" + ], + "nexter-extension": [ + "cpe:2.3:a:posimyth:nexter_extension:*:*:*:*:*:wordpress:*:*" + ], + "nextgen-gallery": [ + "cpe:2.3:a:imagely:nextgen_gallery:*:*:*:*:*:wordpress:*:*" + ], + "ni-purchase-orderpo-for-woocommerce": [ + "cpe:2.3:a:naziinfotech:ni_purchase_order\\(po\\)_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "ni-woocommerce-custom-order-status": [ + "cpe:2.3:a:ni_woocommerce_custom_order_status_project:ni_woocommerce_custom_order_status:*:*:*:*:*:wordpress:*:*" + ], + "nice-paypal-button-lite": [ + "cpe:2.3:a:trinitronic:nice_paypal_button_lite:*:*:*:*:*:wordpress:*:*" + ], + "nifty-coming-soon-and-under-construction-page": [ + "cpe:2.3:a:wpconcern:coming_soon_\\\u0026_maintenance_mode_page:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpconcern:nifty_coming_soon_\\\u0026_maintenance_mode_page:*:*:*:*:*:wordpress:*:*" + ], + "ninja-forms": [ + "cpe:2.3:a:ninjaforms:contact_form:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:ninjaforms:ninja_forms:*:*:*:*:*:wordpress:*:*" + ], + "ninja-job-board": [ + "cpe:2.3:a:wpmanageninja:ninja_job_board:*:*:*:*:*:wordpress:*:*" + ], + "ninja-tables": [ + "cpe:2.3:a:wpmanageninja:ninja_tables:*:*:*:*:*:wordpress:*:*" + ], + "nirweb-support": [ + "cpe:2.3:a:nirweb:nirweb_support:*:*:*:*:*:wordpress:*:*" + ], + "nitropack": [ + "cpe:2.3:a:nitropack:nitropack:*:*:*:*:*:wordpress:*:*" + ], + "nktagcloud": [ + "cpe:2.3:a:better_tag_cloud_project:better_tag_cloud:*:*:*:*:*:wordpress:*:*" + ], + "nmedia-user-file-uploader": [ + "cpe:2.3:a:najeebmedia:frontend_file_manager_plugin:*:*:*:*:*:wordpress:*:*" + ], + "no-future-posts": [ + "cpe:2.3:a:no_future_posts_project:no_future_posts:*:*:*:*:*:wordpress:*:*" + ], + "nofollow": [ + "cpe:2.3:a:ultimate_nofollow_project:ultimate_nofollow:*:*:*:*:*:wordpress:*:*" + ], + "nofollow-links": [ + "cpe:2.3:a:nofollow_links_project:nofollow_links:*:*:*:*:*:wordpress:*:*" + ], + "nokia-mapsplaces": [ + "cpe:2.3:a:nokia_maps_\\\u0026_places_project:nokia_maps_\\\u0026_places:*:*:*:*:*:wordpress:*:*" + ], + "nooz": [ + "cpe:2.3:a:nooz_project:nooz:*:*:*:*:*:wordpress:*:*" + ], + "note-press": [ + "cpe:2.3:a:datainterlock:note_press:*:*:*:*:*:wordpress:*:*" + ], + "notices": [ + "cpe:2.3:a:notices_project:notices:*:*:*:*:*:wordpress:*:*" + ], + "notification": [ + "cpe:2.3:a:bracketspace:notification:*:*:*:*:*:wordpress:*:*" + ], + "notificationx": [ + "cpe:2.3:a:wpdeveloper:notificationx:*:*:*:*:*:wordpress:*:*" + ], + "novelist": [ + "cpe:2.3:a:nosegraze:novelist:*:*:*:*:*:wordpress:*:*" + ], + "novo-map": [ + "cpe:2.3:a:novo-media:novo-map\\:your_wp_posts_on_custom_google_maps:*:*:*:*:*:wordpress:*:*" + ], + "ns-coupon-to-become-customer": [ + "cpe:2.3:a:nsthemes:ns_coupon_to_become_customer:*:*:*:*:*:wordpress:*:*" + ], + "ns-facebook-pixel-for-wp": [ + "cpe:2.3:a:nsthemes:advanced_social_pixel:*:*:*:*:*:wordpress:*:*" + ], + "ns-woocommerce-watermark": [ + "cpe:2.3:a:nsthemes:ns_watermark_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "oauth-client": [ + "cpe:2.3:a:miniorange:oauth_2.0_client_for_sso:*:*:*:*:*:wordpress:*:*" + ], + "oauth-client-for-user-authentication": [ + "cpe:2.3:a:oauth_client_single_sign_on_project:oauth_client_single_sign_on:*:*:*:*:*:wordpress:*:*" + ], + "oauth-twitter-feed-for-developers": [ + "cpe:2.3:a:stormconsultancy:oauth_twitter_feed_for_developers:*:*:*:*:*:wordpress:*:*" + ], + "oauth2-provider": [ + "cpe:2.3:a:dash10:oauth_server:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wp-oauth:wp_oauth_server:*:*:*:*:*:wordpress:*:*" + ], + "oauth2-server": [ + "cpe:2.3:a:codexshaper:wp_oauth2_server:*:*:*:*:*:wordpress:*:*" + ], + "ocean-extra": [ + "cpe:2.3:a:oceanwp:ocean_extra:*:*:*:*:*:wordpress:*:*" + ], + "official-facebook-pixel": [ + "cpe:2.3:a:facebook:facebook:*:*:*:*:*:wordpress:*:*" + ], + "official-mailerlite-sign-up-forms": [ + "cpe:2.3:a:mailerlite:mailerlite_signup_forms:*:*:*:*:*:wordpress:*:*" + ], + "official-sendle-shipping-method": [ + "cpe:2.3:a:joovii:sendle_shipping:*:*:*:*:*:wordpress:*:*" + ], + "og-tags": [ + "cpe:2.3:a:og_tags_project:og_tags:*:*:*:*:*:wordpress:*:*" + ], + "oi-yamaps": [ + "cpe:2.3:a:oi_yandex.maps_for_wordpress_project:oi_yandex.maps_for_wordpress:*:*:*:*:*:wordpress:*:*" + ], + "olevmedia-shortcodes": [ + "cpe:2.3:a:olevmedia:olevmedia_shortcodes:*:*:*:*:*:wordpress:*:*" + ], + "olimometer": [ + "cpe:2.3:a:olimometer_project:olimometer:*:*:*:*:*:wordpress:*:*" + ], + "olive-one-click-demo-import": [ + "cpe:2.3:a:olivethemes:olive_one_click_demo_import:*:*:*:*:*:wordpress:*:*" + ], + "omnisend-connect": [ + "cpe:2.3:a:omnisend:email_marketing_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "onclick-show-popup": [ + "cpe:2.3:a:gopiplus:onclick_show_popup:*:*:*:*:*:wordpress:*:*" + ], + "one-click-demo-import": [ + "cpe:2.3:a:ocdi:one_click_demo_import:*:*:*:*:*:wordpress:*:*" + ], + "one-click-plugin-updater": [ + "cpe:2.3:a:one_click_plugin_updater_project:one_click_plugin_updater:*:*:*:*:*:wordpress:*:*" + ], + "one-click-ssl": [ + "cpe:2.3:a:tribulant:one_click_ssl:*:*:*:*:*:wordpress:*:*" + ], + "one-page-express-companion": [ + "cpe:2.3:a:horea_radu:one_page_express_companion:*:*:*:*:*:wordpress:*:*" + ], + "one-user-avatar": [ + "cpe:2.3:a:onedesigns:one_user_avatar:*:*:*:*:*:wordpress:*:*" + ], + "oneclick-whatsapp-order": [ + "cpe:2.3:a:onlinestorekit:oneclick_chat_to_order:*:*:*:*:*:wordpress:*:*" + ], + "onelogin-saml-sso": [ + "cpe:2.3:a:onelogin:onelogin_saml_sso:*:*:*:*:*:wordpress:*:*" + ], + "onesignal-free-web-push-notifications": [ + "cpe:2.3:a:onesignal:onesignal-free-web-push-notifications:*:*:*:*:*:wordpress:*:*" + ], + "online-accessibility": [ + "cpe:2.3:a:adaplugin:accessibility_suite_by_online_ada:*:*:*:*:*:wordpress:*:*" + ], + "online-lesson-booking-system": [ + "cpe:2.3:a:sukimalab:online_lesson_booking:*:*:*:*:*:wordpress:*:*" + ], + "onwebchat": [ + "cpe:2.3:a:onwebchat:live_chat_-_live_support:*:*:*:*:*:wordpress:*:*" + ], + "ooohboi-steroids-for-elementor": [ + "cpe:2.3:a:ooohboi_steroids_for_elementor_project:ooohboi_steroids_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "oopspam-anti-spam": [ + "cpe:2.3:a:oopspam:oopspam_anti-spam:*:*:*:*:*:wordpress:*:*" + ], + "opal-estate": [ + "cpe:2.3:a:wpopal:opal_estate:*:*:*:*:*:wordpress:*:*" + ], + "opcache": [ + "cpe:2.3:a:extendwings:opcache_dashboard:*:*:*:*:*:wordpress:*:*" + ], + "open-external-links-in-a-new-window": [ + "cpe:2.3:a:webfactoryltd:external_links_in_new_window_\\/_new_tab:*:*:*:*:*:wordpress:*:*" + ], + "open-graph-metabox": [ + "cpe:2.3:a:underdock:open_graph_metabox:*:*:*:*:*:wordpress:*:*" + ], + "open-rdw-kenteken-voertuiginformatie": [ + "cpe:2.3:a:tussendoor:open_rdw_kenteken_voertuiginformatie:*:*:*:*:*:wordpress:*:*" + ], + "open-user-map": [ + "cpe:2.3:a:100plugins:open_user_map:*:*:*:*:*:wordpress:*:*" + ], + "opengraph": [ + "cpe:2.3:a:willnorris:open_graph:*:*:*:*:*:wordpress:*:*" + ], + "opening-hours": [ + "cpe:2.3:a:designextreme:we\\'re_open\\!:*:*:*:*:*:wordpress:*:*" + ], + "ops-robots-txt": [ + "cpe:2.3:a:ops-robots-txt_project:ops-robots-txt:*:*:*:*:*:wordpress:*:*" + ], + "optima-express": [ + "cpe:2.3:a:ihomefinder:optima_express_\\+_marketboost_idx:*:*:*:*:*:wordpress:*:*" + ], + "optimole-wp": [ + "cpe:2.3:a:vertistudio:image_optimization_\\\u0026_lazy_load_by_optimole:*:*:*:*:*:wordpress:*:*" + ], + "optin-forms": [ + "cpe:2.3:a:fancythemes:optin_forms:*:*:*:*:*:wordpress:*:*" + ], + "optinly": [ + "cpe:2.3:a:optinly:optinly:*:*:*:*:*:wordpress:*:*" + ], + "optinmonster": [ + "cpe:2.3:a:optinmonster:optinmonster:*:*:*:*:*:wordpress:*:*" + ], + "option-tree": [ + "cpe:2.3:a:optiontree_project:optiontree:*:*:*:*:*:wordpress:*:*" + ], + "options-for-twenty-seventeen": [ + "cpe:2.3:a:webd:options_for_twenty_seventeen:*:*:*:*:*:wordpress:*:*" + ], + "orbisius-child-theme-creator": [ + "cpe:2.3:a:orbisius:child_theme_creator:*:*:*:*:*:wordpress:*:*" + ], + "order-auto-complete-for-woocommerce": [ + "cpe:2.3:a:order_auto_complete_for_woocommerce_project:order_auto_complete_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "order-delivery-date-for-woocommerce": [ + "cpe:2.3:a:tychesoftwares:order_delivery_date_for_woocommerce:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:tychesoftwares:order_delivery_date_for_wp_e-commerce:*:*:*:*:*:wordpress:*:*" + ], + "order-import-export-for-woocommerce": [ + "cpe:2.3:a:webtoffee:order_export_\\\u0026_order_import_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "order-tracking": [ + "cpe:2.3:a:etoilewebdesign:order_tracking:*:*:*:*:pro:wordpress:*:*" + ], + "organization-chart": [ + "cpe:2.3:a:wpdevart:organization_chart:*:*:*:*:*:wordpress:*:*" + ], + "organizer": [ + "cpe:2.3:a:organizer_project:organizer:*:*:*:*:*:wordpress:*:*" + ], + "osd-subscribe": [ + "cpe:2.3:a:outsidesource:osd_subscribe:*:*:*:*:*:wordpress:*:*" + ], + "osm": [ + "cpe:2.3:a:hyumika:openstreetmap:*:*:*:*:*:wordpress:*:*" + ], + "osmapper": [ + "cpe:2.3:a:b4after:osmapper:*:*:*:*:*:wordpress:*:*" + ], + "our-team-enhanced": [ + "cpe:2.3:a:smartcat:our_team_showcase:*:*:*:*:*:wordpress:*:*" + ], + "outbound-link-manager": [ + "cpe:2.3:a:sparro:outbound_link_manager:*:*:*:*:*:wordpress:*:*" + ], + "ovic-import-demo": [ + "cpe:2.3:a:ovic_importer_project:ovic_importer:*:*:*:*:*:wordpress:*:*" + ], + "ovic-vc-addon": [ + "cpe:2.3:a:kutethemes:ovic_responsive_wpbakery:*:*:*:*:*:wordpress:*:*" + ], + "owl-carousel": [ + "cpe:2.3:a:pierre-jehan:owl_carousel:*:*:*:*:*:wordpress:*:*" + ], + "owm-weather": [ + "cpe:2.3:a:ujsoftware:owm_weather:*:*:*:*:*:wordpress:*:*" + ], + "page-and-post-restriction": [ + "cpe:2.3:a:miniorange:page_restriction:*:*:*:*:*:wordpress:*:*" + ], + "page-builder-add": [ + "cpe:2.3:a:pluginops:landing_page_builder:*:*:*:*:*:wordpress:*:*" + ], + "page-builder-by-azexo": [ + "cpe:2.3:a:azexo:page_builder_with_image_map_by_azexo:*:*:*:*:*:wordpress:*:*" + ], + "page-generator": [ + "cpe:2.3:a:wpzinc:page_generator:*:*:*:*:*:wordpress:*:*" + ], + "page-layout-builder": [ + "cpe:2.3:a:page-layout-builder_project:page-layout-builder:*:*:*:*:*:wordpress:*:*" + ], + "page-list": [ + "cpe:2.3:a:page-list_project:page-list:*:*:*:*:*:wordpress:*:*" + ], + "page-scroll-to-id": [ + "cpe:2.3:a:page_scroll_to_id_project:page_scroll_to_id:*:*:*:*:*:wordpress:*:*" + ], + "page-views-count": [ + "cpe:2.3:a:a3rev:page_view_count:*:*:*:*:*:wordpress:*:*" + ], + "pagebar": [ + "cpe:2.3:a:pagebar_project:pagebar:*:*:*:*:*:wordpress:*:*" + ], + "pagelayer": [ + "cpe:2.3:a:pagelayer:pagelayer:*:*:*:*:*:wordpress:*:*" + ], + "pagepost-content-shortcode": [ + "cpe:2.3:a:page\\/post_content_shortcode_project:page\\/post_content_shortcode:*:*:*:*:*:wordpress:*:*" + ], + "pagination": [ + "cpe:2.3:a:bestwebsoft:pagination:*:*:*:*:*:wordpress:*:*" + ], + "paid-member-subscriptions": [ + "cpe:2.3:a:cozmoslabs:membership_\\\u0026_content_restriction_-_paid_member_subscriptions:*:*:*:*:*:wordpress:*:*" + ], + "paid-membership": [ + "cpe:2.3:a:videowhisper:micropayments:*:*:*:*:*:wordpress:*:*" + ], + "paid-memberships-pro": [ + "cpe:2.3:a:strangerstudios:paid_memberships_pro:*:*:*:*:*:wordpress:*:*" + ], + "parallax-image": [ + "cpe:2.3:a:howardehrenberg:parallax_image:*:*:*:*:*:wordpress:*:*" + ], + "parallax-slider-block": [ + "cpe:2.3:a:wpdeveloper:parallax_slider_block:*:*:*:*:*:wordpress:*:*" + ], + "pardakht-delkhah": [ + "cpe:2.3:a:wp-master:pardakht-delkhah:*:*:*:*:*:wordpress:*:*" + ], + "parsi-font": [ + "cpe:2.3:a:parsi-font_project:parsi-font:*:*:*:*:*:wordpress:*:*" + ], + "participants-database": [ + "cpe:2.3:a:xnau:participants_database:*:*:*:*:*:wordpress:*:*" + ], + "password-protect-page": [ + "cpe:2.3:a:passwordprotectwp:password_protect_wordpress:*:*:*:*:*:wordpress:*:*" + ], + "password-protected": [ + "cpe:2.3:a:wpexperts:password_protected:*:*:*:*:*:wordpress:*:*" + ], + "patreon-connect": [ + "cpe:2.3:a:patreon:patreon_wordpress:*:*:*:*:*:wordpress:*:*" + ], + "patron-button-and-widgets-by-codebard": [ + "cpe:2.3:a:codebard:codebard\\'s_patron_button_and_widgets_for_patreon:*:*:*:*:*:wordpress:*:*" + ], + "paygreen-woocommerce": [ + "cpe:2.3:a:paygreen:paygreen_-_ancienne:*:*:*:*:*:wordpress:*:*" + ], + "payment-form-for-paypal-pro": [ + "cpe:2.3:a:codepeople:payment_form_for_paypal_pro:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:ithemes:paypal_pro:*:*:*:*:*:wordpress:*:*" + ], + "payment-forms-for-paystack": [ + "cpe:2.3:a:paystack:payment_forms_for_paystack:*:*:*:*:*:wordpress:*:*" + ], + "payment-gateway-stripe-and-woocommerce-integration": [ + "cpe:2.3:a:webtoffee:stripe_payment_plugin_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "paypal-donations": [ + "cpe:2.3:a:tipsandtricks-hq:donations_via_paypal:*:*:*:*:*:wordpress:*:*" + ], + "paypal-payment-button-by-vcita": [ + "cpe:2.3:a:vcita:online_payments_-_get_paid_with_paypal\\,_square_\\\u0026_stripe:*:*:*:*:*:wordpress:*:*" + ], + "paytium": [ + "cpe:2.3:a:paytium:paytium:*:*:*:*:*:wordpress:*:*" + ], + "paytm-payments": [ + "cpe:2.3:a:paytm:payment_gateway:*:*:*:*:*:wordpress:*:*" + ], + "paytr-taksit-tablosu-woocommerce": [ + "cpe:2.3:a:paytr:paytr_taksit_tablosu_-_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "pdf-block": [ + "cpe:2.3:a:henryholtgeerts:pdf_block:*:*:*:*:*:wordpress:*:*" + ], + "pdf-embedder": [ + "cpe:2.3:a:wp-pdf:pdf_embedder:*:*:*:*:*:wordpress:*:*" + ], + "pdf-generator-for-wp": [ + "cpe:2.3:a:wpswings:pdf_generator_for_wordpress:*:*:*:*:*:wordpress:*:*" + ], + "pdf-light-viewer": [ + "cpe:2.3:a:teamlead:pdf-light-viewer:*:*:*:*:*:wordpress:*:*" + ], + "pdf-poster": [ + "cpe:2.3:a:bplugins:pdf_poster:*:*:*:*:*:wordpress:*:*" + ], + "pdf-print": [ + "cpe:2.3:a:bestwebsoft:pdf_\\\u0026_print:*:*:*:*:*:wordpress:*:*" + ], + "pdf-viewer-block": [ + "cpe:2.3:a:gutenberg_pdf_viewer_block_project:gutenberg_pdf_viewer_block:*:*:*:*:*:wordpress:*:*" + ], + "pdf24-posts-to-pdf": [ + "cpe:2.3:a:pdf24_articles_to_pdf_project:pdf24_articles_to_pdf:*:*:*:*:*:wordpress:*:*" + ], + "pdfjs-viewer-shortcode": [ + "cpe:2.3:a:pdf.js_viewer_project:pdf.js_viewer:*:*:*:*:*:wordpress:*:*" + ], + "pdq-csv": [ + "cpe:2.3:a:ransomchristofferson:pdq_csv:*:*:*:*:*:wordpress:*:*" + ], + "peepso-core": [ + "cpe:2.3:a:peepso:peepso:*:*:*:*:*:wordpress:*:*" + ], + "pepro-cf7-database": [ + "cpe:2.3:a:peprodev:peprodev_cf7_database:*:*:*:*:*:wordpress:*:*" + ], + "per-page-add-to": [ + "cpe:2.3:a:evona:per_page_add_to_head:*:*:*:*:*:wordpress:*:*" + ], + "perelink": [ + "cpe:2.3:a:perelink_pro_project:perelink_pro:*:*:*:*:*:wordpress:*:*" + ], + "perfect-woocommerce-brands": [ + "cpe:2.3:a:quadlayers:perfect_brands_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "performance-lab": [ + "cpe:2.3:a:wordpress:performance_lab:*:*:*:*:*:wordpress:*:*" + ], + "permalink-manager": [ + "cpe:2.3:a:permalink_manager_lite_project:permalink_manager_lite:*:*:*:*:*:wordpress:*:*" + ], + "permalinks-customizer": [ + "cpe:2.3:a:yasglobal:permalinks_customizer:*:*:*:*:*:wordpress:*:*" + ], + "persian-woocommerce": [ + "cpe:2.3:a:woocommerce:persian-woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "persian-woocommerce-sms": [ + "cpe:2.3:a:woocommerce:persian_woocommerce_sms:*:*:*:*:*:wordpress:*:*" + ], + "personalize-woocommerce-cart-page": [ + "cpe:2.3:a:najeebmedia:personalized_woocommerce_cart_page:*:*:*:*:*:wordpress:*:*" + ], + "peters-collaboration-e-mails": [ + "cpe:2.3:a:peter\\'s_collaboration_e-mails_project:peter\\'s_collaboration_e-mails:*:*:*:*:*:wordpress:*:*" + ], + "peters-custom-anti-spam-image": [ + "cpe:2.3:a:peterkeung:peter\\'s_custom_anti-spam:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:peterkeung:peters_custom_anti-spam:*:*:*:*:*:wordpress:*:*" + ], + "peters-login-redirect": [ + "cpe:2.3:a:profilepress:loginwp:*:*:*:*:*:wordpress:*:*" + ], + "petfinder-listings": [ + "cpe:2.3:a:unboxinteractive:petfinder-listings:*:*:*:*:*:wordpress:*:*" + ], + "phastpress": [ + "cpe:2.3:a:kiboit:phastpress:*:*:*:*:*:wordpress:*:*" + ], + "phoenix-media-rename": [ + "cpe:2.3:a:phoenix_media_rename_project:phoenix_media_rename:*:*:*:*:*:wordpress:*:*" + ], + "phone-orders-for-woocommerce": [ + "cpe:2.3:a:algolplus:phone_orders_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "phonepe-payment-solutions": [ + "cpe:2.3:a:phonepe:phonepe:*:*:*:*:*:wordpress:*:*" + ], + "phonetrack-meu-site-manager": [ + "cpe:2.3:a:phonetrack:phonetrack_meu_site_manager:*:*:*:*:*:wordpress:*:*" + ], + "photo-contest": [ + "cpe:2.3:a:flippercode:photo_gallery_-_image_gallery:*:*:*:*:*:wordpress:*:*" + ], + "photo-gallery": [ + "cpe:2.3:a:10web:photo_gallery:*:*:*:*:*:wordpress:*:*" + ], + "photoblocks-grid-gallery": [ + "cpe:2.3:a:greentreelabs:gallery_photoblocks:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpchill:gallery_photoblocks:*:*:*:*:*:wordpress:*:*" + ], + "photospace": [ + "cpe:2.3:a:photospace_gallery_project:photospace_gallery:*:*:*:*:*:wordpress:*:*" + ], + "photospace-responsive": [ + "cpe:2.3:a:deanoakley:photospace_responsive_gallery:*:*:*:*:*:wordpress:*:*" + ], + "photoswipe-masonry": [ + "cpe:2.3:a:thriveweb:photoswipe_masonry_gallery:*:*:*:*:*:wordpress:*:*" + ], + "photoxhibit": [ + "cpe:2.3:a:photoxhibit_project:photoxhibit:*:*:*:*:*:wordpress:*:*" + ], + "php-compatibility-checker": [ + "cpe:2.3:a:wpengine:php_compatibility_checker:*:*:*:*:*:wordpress:*:*" + ], + "php-everywhere": [ + "cpe:2.3:a:php_everywhere_project:php_everywhere:*:*:*:*:*:wordpress:*:*" + ], + "php-execution-plugin": [ + "cpe:2.3:a:php_execution_project:php_execution:*:*:*:*:*:wordpress:*:*" + ], + "php-to-page": [ + "cpe:2.3:a:php_to_page_project:php_to_page:*:*:*:*:*:wordpress:*:*" + ], + "phpfreechat": [ + "cpe:2.3:a:frumph:phpfreechat:*:*:*:*:*:wordpress:*:*" + ], + "pi-woocommerce-order-date-time-and-type": [ + "cpe:2.3:a:piwebsolution:pi-woocommerce-order-date-time-and-type:*:*:*:*:*:wordpress:*:*" + ], + "picture-gallery": [ + "cpe:2.3:a:videowhisper:picture_gallery:*:*:*:*:*:wordpress:*:*" + ], + "pie-forms-for-wp": [ + "cpe:2.3:a:pieforms:drag_\\\u0026_drop_builder:*:*:*:*:*:wordpress:*:*" + ], + "pie-register": [ + "cpe:2.3:a:genetechsolutions:pie_register:*:*:*:*:*:wordpress:*:*" + ], + "pinterest-rss-widget": [ + "cpe:2.3:a:bkmacdaddy:pinterest_rss_widget:*:*:*:*:*:wordpress:*:*" + ], + "piotnetforms": [ + "cpe:2.3:a:piotnet:piotnet_forms:*:*:*:*:*:wordpress:*:*" + ], + "pixabay-images": [ + "cpe:2.3:a:pixabay_images_project:pixabay_images:*:*:*:*:*:wordpress:*:*" + ], + "pixelyoursite": [ + "cpe:2.3:a:pixelyoursite:pixelyoursite:*:*:*:*:*:wordpress:*:*" + ], + "pixtypes": [ + "cpe:2.3:a:pixelgrade:pixtypes:*:*:*:*:*:wordpress:*:*" + ], + "plainview-activity-monitor": [ + "cpe:2.3:a:plainview_activity_monitor_project:plainview_activity_monitor:*:*:*:*:*:wordpress:*:*" + ], + "plainview-protect-passwords": [ + "cpe:2.3:a:plainviewplugins:plainview_protect_passwords:*:*:*:*:*:wordpress:*:*" + ], + "planso-forms": [ + "cpe:2.3:a:planso:planso_forms:*:*:*:*:*:wordpress:*:*" + ], + "plausible-analytics": [ + "cpe:2.3:a:plausible:plausible_analytics:*:*:*:*:*:wordpress:*:*" + ], + "player": [ + "cpe:2.3:a:web-dorado:spidervplayer:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:web-dorado:web-dorado_spider_video_player:*:*:*:*:*:wordpress:*:*" + ], + "plugin-logic": [ + "cpe:2.3:a:plugin_logic_project:plugin_logic:*:*:*:*:*:wordpress:*:*" + ], + "plugin-organizer": [ + "cpe:2.3:a:plugin-organizer_project:plugin-organizer:*:*:*:*:*:wordpress:*:*" + ], + "plugins-list": [ + "cpe:2.3:a:artiss:plugins_list:*:*:*:*:*:wordpress:*:*" + ], + "plugmatter-optin-feature-box-lite": [ + "cpe:2.3:a:sizmic:plugmatter_optin_feature_box:*:*:*:*:*:wordpress:*:*" + ], + "plugmatter-pricing-table": [ + "cpe:2.3:a:sizmic:plugmatter_pricing_table:*:*:*:*:lite:wordpress:*:*" + ], + "plugnedit": [ + "cpe:2.3:a:simplysymphony:plugnedit:*:*:*:*:*:wordpress:*:*" + ], + "podcast-channels": [ + "cpe:2.3:a:podcast_channels_project:podcast_channels:*:*:*:*:*:wordpress:*:*" + ], + "podcast-importer-secondline": [ + "cpe:2.3:a:secondline:podcast_importer_secondline:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:secondlinethemes:podcast_importer_secondline:*:*:*:*:*:wordpress:*:*" + ], + "podcast-subscribe-buttons": [ + "cpe:2.3:a:secondlinethemes:podcast_subscribe_buttons:*:*:*:*:*:wordpress:*:*" + ], + "podlove-podcasting-plugin-for-wordpress": [ + "cpe:2.3:a:podlove:podlove_podcast_publisher:*:*:*:*:*:*:*:*", + "cpe:2.3:a:podlove:podlove_podcast_publisher:*:*:*:*:*:wordpress:*:*" + ], + "podlove-subscribe-button": [ + "cpe:2.3:a:podlove:podlove_subscribe_button:*:*:*:*:*:wordpress:*:*" + ], + "pods": [ + "cpe:2.3:a:podsfoundation:pods:*:*:*:*:*:wordpress:*:*" + ], + "poeditor": [ + "cpe:2.3:a:poeditor:poeditor:*:*:*:*:*:wordpress:*:*" + ], + "poll-maker": [ + "cpe:2.3:a:ays-pro:poll_maker:*:*:*:*:*:wordpress:*:*" + ], + "poll-wp": [ + "cpe:2.3:a:total-soft:responsive_poll:*:*:*:*:*:wordpress:*:*" + ], + "polldaddy": [ + "cpe:2.3:a:automattic:crowdsignal_dashboard:*:*:*:*:*:wordpress:*:*" + ], + "polls-widget": [ + "cpe:2.3:a:wpdevart:poll\\,_survey\\,_questionnaire_and_voting_system:*:*:*:*:*:wordpress:*:*" + ], + "polo-video-gallery": [ + "cpe:2.3:a:bplugins:polo_video_gallery:*:*:*:*:*:wordpress:*:*" + ], + "pootle-button": [ + "cpe:2.3:a:pootlepress:pootle_button:*:*:*:*:*:wordpress:*:*" + ], + "pop-up": [ + "cpe:2.3:a:chop-chop:pop-up_chop_chop:*:*:*:*:*:wordpress:*:*" + ], + "pop-up-pop-up": [ + "cpe:2.3:a:mypopups:pop-up:*:*:*:*:*:wordpress:*:*" + ], + "popcashnet-code-integration-tool": [ + "cpe:2.3:a:popcash:popcash.net_code_integration_tool:*:*:*:*:*:wordpress:*:*" + ], + "poptin": [ + "cpe:2.3:a:poptin:popups:*:*:*:*:*:wordpress:*:*" + ], + "popup-anything-on-click": [ + "cpe:2.3:a:essentialplugin:popup_anything:*:*:*:*:*:wordpress:*:*" + ], + "popup-box": [ + "cpe:2.3:a:wow-company:popup_box:*:*:*:*:*:wordpress:*:*" + ], + "popup-builder": [ + "cpe:2.3:a:sygnoos:popup_builder:*:*:*:*:*:wordpress:*:*" + ], + "popup-by-supsystic": [ + "cpe:2.3:a:supsystic:popup:*:*:*:*:*:wordpress:*:*" + ], + "popup-contact-form": [ + "cpe:2.3:a:gopiplus:popup_contact_form:*:*:*:*:*:wordpress:*:*" + ], + "popup-maker": [ + "cpe:2.3:a:code-atlantic:popup_maker:*:*:*:*:*:wordpress:*:*" + ], + "popup-manager": [ + "cpe:2.3:a:popup_manager_project:popup_manager:*:*:*:*:*:wordpress:*:*" + ], + "popup-zyrex": [ + "cpe:2.3:a:zyrex:popup:*:*:*:*:*:wordpress:*:*" + ], + "popups": [ + "cpe:2.3:a:timersys:popups:*:*:*:*:*:wordpress:*:*" + ], + "portable-phpmyadmin": [ + "cpe:2.3:a:getbutterfly:portable-phpmyadmin:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:portable_phpmyadmin_project:portable_phpmyadmin:*:*:*:*:*:wordpress:*:*" + ], + "portfolio": [ + "cpe:2.3:a:bestwebsoft:portfolio:*:*:*:*:*:wordpress:*:*" + ], + "portfolio-by-lisa-westlund": [ + "cpe:2.3:a:portfolio_project:portfolio:*:*:*:*:*:wordpress:*:*" + ], + "portfolio-elementor": [ + "cpe:2.3:a:pwrplugins:powerfolio:*:*:*:*:*:wordpress:*:*" + ], + "portfolio-gallery": [ + "cpe:2.3:a:huge-it:portfolio_gallery:*:*:*:*:*:wordpress:*:*" + ], + "portfolio-responsive-gallery": [ + "cpe:2.3:a:ays-pro:portfolio_responsive_gallery:*:*:*:*:*:wordpress:*:*" + ], + "portfolio-slideshow": [ + "cpe:2.3:a:portfolio_slideshow_project:portfolio_slideshow:*:*:*:*:*:wordpress:*:*" + ], + "portfolio-wp": [ + "cpe:2.3:a:wpsofts:portfolio_gallery\\,_product_catalog_-_grid_kit_portfolio:*:*:*:*:*:wordpress:*:*" + ], + "portugal-ctt-tracking-woocommerce": [ + "cpe:2.3:a:webdados:portugal_ctt_tracking_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "post-and-page-builder": [ + "cpe:2.3:a:boldgrid:post_and_page_builder_by_boldgrid_-_visual_drag_and_drop_editor:*:*:*:*:*:wordpress:*:*" + ], + "post-connector": [ + "cpe:2.3:a:never5:post_connector:*:*:*:*:*:wordpress:*:*" + ], + "post-content-xmlrpc": [ + "cpe:2.3:a:post_content_xmlrpc_project:post_content_xmlrpc:*:*:*:*:*:wordpress:*:*" + ], + "post-duplicator": [ + "cpe:2.3:a:metaphorcreations:post_duplicator:*:*:*:*:*:wordpress:*:*" + ], + "post-expirator": [ + "cpe:2.3:a:publishpress:post_expirator:*:*:*:*:*:wordpress:*:*" + ], + "post-grid": [ + "cpe:2.3:a:pickplugins:post_grid:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:pickplugins:post_grid_combo:*:*:*:*:*:wordpress:*:*" + ], + "post-grid-carousel-ultimate": [ + "cpe:2.3:a:wpwax:post_grid\\,_slider_\\\u0026_carousel_ultimate:*:*:*:*:*:wordpress:*:*" + ], + "post-highlights": [ + "cpe:2.3:a:post_highlights_projects:post_highlights:*:*:*:*:*:wordpress:*:*" + ], + "post-index": [ + "cpe:2.3:a:post_index_project:post_index:*:*:*:*:*:wordpress:*:*" + ], + "post-list-designer": [ + "cpe:2.3:a:infornweb:posts_list_designer_by_category:*:*:*:*:*:wordpress:*:*" + ], + "post-meta-data-manager": [ + "cpe:2.3:a:wpexpertplugins:post_meta_data_manager:*:*:*:*:*:wordpress:*:*" + ], + "post-pay-counter": [ + "cpe:2.3:a:post_pay_counter_project:post_pay_counter:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:thecrowned:post_pay_counter:*:*:*:*:*:wordpress:*:*" + ], + "post-slider-carousel": [ + "cpe:2.3:a:i13websolution:post_sliders_\\\u0026_post_grids:*:*:*:*:*:wordpress:*:*" + ], + "post-smtp": [ + "cpe:2.3:a:wpexperts:post_smtp:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpexperts:post_smtp_mailer:*:*:*:*:*:wordpress:*:*" + ], + "post-snippets": [ + "cpe:2.3:a:postsnippets:post_snippets:*:*:*:*:*:wordpress:*:*" + ], + "post-state-tags": [ + "cpe:2.3:a:brandbrilliance:post_state_tags:*:*:*:*:*:wordpress:*:*" + ], + "post-status-notifier-lite": [ + "cpe:2.3:a:ifeelweb:post_status_notifier_lite:*:*:*:*:*:wordpress:*:*" + ], + "post-timeline": [ + "cpe:2.3:a:agilelogix:post_timeline:*:*:*:*:*:wordpress:*:*" + ], + "post-title-counter": [ + "cpe:2.3:a:wpleet:post_title_counter:*:*:*:*:*:wordpress:*:*" + ], + "post-to-csv": [ + "cpe:2.3:a:bestwebsoft:post_to_csv:*:*:*:*:*:wordpress:*:*" + ], + "post-type-x": [ + "cpe:2.3:a:implecode:product_catalog_simple:*:*:*:*:*:wordpress:*:*" + ], + "post-views-counter": [ + "cpe:2.3:a:dfactory:post_views_counter:*:*:*:*:*:wordpress:*:*" + ], + "post-views-stats": [ + "cpe:2.3:a:cybernetikz:post_views_stats:*:*:*:*:*:wordpress:*:*" + ], + "postaffiliatepro": [ + "cpe:2.3:a:qualityunit:post_affiliate_pro:*:*:*:*:*:wordpress:*:*" + ], + "postie": [ + "cpe:2.3:a:postieplugin:postie:*:*:*:*:*:wordpress:*:*" + ], + "postmagthemes-demo-import": [ + "cpe:2.3:a:postmagthemes:postmagthemes_demo_import:*:*:*:*:*:wordpress:*:*" + ], + "postman-smtp": [ + "cpe:2.3:a:postman-smtp_project:postman-smtp:*:*:*:*:*:wordpress:*:*" + ], + "postmatic": [ + "cpe:2.3:a:gopostmatic:replyable:*:*:*:*:*:wordpress:*:*" + ], + "posts-in-page": [ + "cpe:2.3:a:ivycat:posts_in_page:*:*:*:*:*:wordpress:*:*" + ], + "posttabs": [ + "cpe:2.3:a:posttabs_project:posttabs:*:*:*:*:*:wordpress:*:*" + ], + "powerpack-addon-for-beaver-builder": [ + "cpe:2.3:a:wpbeaveraddons:powerpack_lite_for_beaver_builder:*:*:*:*:*:wordpress:*:*" + ], + "powerpack-lite-for-elementor": [ + "cpe:2.3:a:ideabox:powerpack_addons_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "powerpress": [ + "cpe:2.3:a:blubrry:powerpress:*:*:*:*:*:wordpress:*:*" + ], + "pre-orders-for-woocommerce": [ + "cpe:2.3:a:brightplugins:pre-orders_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "pre-party-browser-hints": [ + "cpe:2.3:a:samperrow:party_resource_hints:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:samperrow:pre_party_resource_hints:*:*:*:*:*:wordpress:*:*" + ], + "premium-addons-for-elementor": [ + "cpe:2.3:a:leap13:premium_addons_for_elementor:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:leap13:premium_addons_for_elementor:*:*:*:*:pro:wordpress:*:*" + ], + "premmerce": [ + "cpe:2.3:a:premmerce:premmerce:*:*:*:*:*:wordpress:*:*" + ], + "premmerce-redirect-manager": [ + "cpe:2.3:a:premmerce:redirect_manager:*:*:*:*:*:wordpress:*:*" + ], + "prepost-seo": [ + "cpe:2.3:a:enzipe:prepost_seo:*:*:*:*:*:wordpress:*:*" + ], + "pressference-exporter": [ + "cpe:2.3:a:pressference:pressference_exporter:*:*:*:*:*:wordpress:*:*" + ], + "pressforward": [ + "cpe:2.3:a:pressforward:pressforward:*:*:*:*:*:wordpress:*:*" + ], + "preview-link-generator": [ + "cpe:2.3:a:hasthemes:preview_link_generator:*:*:*:*:*:wordpress:*:*" + ], + "pricetable": [ + "cpe:2.3:a:price_table_project:price_table:*:*:*:*:*:wordpress:*:*" + ], + "pricing-deals-for-woocommerce": [ + "cpe:2.3:a:varktech:pricing_deals_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "pricing-table": [ + "cpe:2.3:a:w3eden:pricing_table:*:*:*:*:*:wordpress:*:*" + ], + "pricing-table-by-supsystic": [ + "cpe:2.3:a:supsystic:pricing_table_by_supsystic:*:*:*:*:*:wordpress:*:*" + ], + "pricing-tables-for-wpbakery-page-builder": [ + "cpe:2.3:a:pricing_tables_for_wpbakery_page_builder_project:pricing_tables_for_wpbakery_page_builder:*:*:*:*:*:wordpress:*:*" + ], + "prime-mover": [ + "cpe:2.3:a:codexonics:prime_mover:*:*:*:*:*:wordpress:*:*" + ], + "print-invoices-packing-slip-labels-for-woocommerce": [ + "cpe:2.3:a:webtoffee:woocommerce_pdf_invoices\\,_packing_slips\\,_delivery_notes_and_shipping_labels:*:*:*:*:*:wordpress:*:*" + ], + "print-my-blog": [ + "cpe:2.3:a:print_my_blog_project:print_my_blog:*:*:*:*:*:wordpress:*:*" + ], + "print-o-matic": [ + "cpe:2.3:a:print-o-matic_project:print-o-matic:*:*:*:*:*:wordpress:*:*" + ], + "printfriendly": [ + "cpe:2.3:a:printfriendly:print\\,_pdf\\,_email_by_printfriendly:*:*:*:*:*:wordpress:*:*" + ], + "prismatic": [ + "cpe:2.3:a:plugin-planet:prismatic:*:*:*:*:*:wordpress:*:*" + ], + "private-content": [ + "cpe:2.3:a:lcweb:privatecontent:*:*:*:*:*:wordpress:*:*" + ], + "private-google-calendars": [ + "cpe:2.3:a:michielvaneerd:private_google_calendars:*:*:*:*:*:wordpress:*:*" + ], + "private-messages-for-wordpress": [ + "cpe:2.3:a:private_messages_project:private_messages:*:*:*:*:*:wordpress:*:*" + ], + "private-only": [ + "cpe:2.3:a:private_only_project:private_only:*:*:*:*:*:wordpress:*:*" + ], + "pro-mime-types": [ + "cpe:2.3:a:cyberwire:pro_mime_types:*:*:*:*:*:wordpress:*:*" + ], + "process-steps-template-designer": [ + "cpe:2.3:a:coolplugins:process_steps_template_designer:*:*:*:*:*:wordpress:*:*" + ], + "product-carousel-slider-for-woocommerce": [ + "cpe:2.3:a:aazztech:woocommerce_product_carousel_slider:*:*:*:*:*:wordpress:*:*" + ], + "product-catalog-feed": [ + "cpe:2.3:a:pixelyoursite:product_catalog_feed:*:*:*:*:*:wordpress:*:*" + ], + "product-category-tree": [ + "cpe:2.3:a:awesometogi:product-category-tree:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:awesometogi:product_category_tree:*:*:*:*:*:wordpress:*:*" + ], + "product-designer": [ + "cpe:2.3:a:pickplugins:product_designer:*:*:*:*:*:wordpress:*:*" + ], + "product-expiry-for-woocommerce": [ + "cpe:2.3:a:webcodingplace:product_expiry_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "product-gtin-ean-upc-isbn-for-woocommerce": [ + "cpe:2.3:a:product_gtin_\\(ean\\,_upc\\,_isbn\\)_for_woocommerce_project:product_gtin_\\(ean\\,_upc\\,_isbn\\)_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "product-import-export-for-woo": [ + "cpe:2.3:a:webtoffee:product_import_export_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "product-reviews-import-export-for-woocommerce": [ + "cpe:2.3:a:webtoffee:product_reviews_import_export_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "product-visibility-by-country-for-woocommerce": [ + "cpe:2.3:a:wpwham:product_visibility_by_country_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "profile-builder": [ + "cpe:2.3:a:cozmoslabs:profile_builder:*:*:*:*:*:wordpress:*:*" + ], + "profile-extra-fields": [ + "cpe:2.3:a:bestwebsoft:profile_extra:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:bestwebsoft:profile_extra_fields:*:*:*:*:*:wordpress:*:*" + ], + "profilegrid-user-profiles-groups-and-communities": [ + "cpe:2.3:a:metagauss:profilegrid:*:*:*:*:*:wordpress:*:*" + ], + "profit-products-tables-for-woocommerce": [ + "cpe:2.3:a:pluginus:woot:*:*:*:*:*:wordpress:*:*" + ], + "progress-bar": [ + "cpe:2.3:a:progress_bar_project:progress_bar:*:*:*:*:*:wordpress:*:*" + ], + "progressive-license": [ + "cpe:2.3:a:crowdfavorite:progressive_license:*:*:*:*:*:wordpress:*:*" + ], + "project-source-code-download": [ + "cpe:2.3:a:project-source-code-download_project:project-source-code-download:*:*:*:*:*:wordpress:*:*" + ], + "project-status": [ + "cpe:2.3:a:3.7designs:project_status:*:*:*:*:*:wordpress:*:*" + ], + "promobar": [ + "cpe:2.3:a:bestwebsoft:promobar:*:*:*:*:*:wordpress:*:*" + ], + "promotion-slider": [ + "cpe:2.3:a:promotion_slider_project:promotion_slider:*:*:*:*:*:wordpress:*:*" + ], + "proofreading": [ + "cpe:2.3:a:scribit:proofreading:*:*:*:*:*:wordpress:*:*" + ], + "propertyhive": [ + "cpe:2.3:a:wp-property-hive:propertyhive:*:*:*:*:*:wordpress:*:*" + ], + "ps-phpcaptcha": [ + "cpe:2.3:a:ps_phpcaptcha_wp_project:ps_phpcaptcha_wp:*:*:*:*:*:wordpress:*:*" + ], + "ptypeconverter": [ + "cpe:2.3:a:briandgoad:ptypeconverter:*:*:*:*:*:wordpress:*:*" + ], + "publish-post-email-notification": [ + "cpe:2.3:a:i13websolution:wordpress_publish_post_email_notification:*:*:*:*:*:wordpress:*:*" + ], + "publish-to-schedule": [ + "cpe:2.3:a:publish_to_schedule_project:publish_to_schedule:*:*:*:*:*:wordpress:*:*" + ], + "pubsubhubbub": [ + "cpe:2.3:a:pubsubhubbub:websub:*:*:*:*:*:wordpress:*:*" + ], + "purple-xmls-google-product-feed-for-woocommerce": [ + "cpe:2.3:a:dpl:product_feed_on_woocommerce_for_google\\,_awin\\,_shareasale\\,_bing\\,_and_more:*:*:*:*:*:wordpress:*:*" + ], + "push-notification-by-feedify": [ + "cpe:2.3:a:feedify:web_push_notifications:*:*:*:*:*:wordpress:*:*" + ], + "push-notifications-for-wp": [ + "cpe:2.3:a:delitestudio:push_notifications_for_wordpress:*:*:*:*:lite:wordpress:*:*" + ], + "pwa-for-wp": [ + "cpe:2.3:a:magazine3:pwa_for_wp_\\\u0026_amp:*:*:*:*:*:wordpress:*:*" + ], + "pz-linkcard": [ + "cpe:2.3:a:popozure:pz-linkcard:*:*:*:*:*:wordpress:*:*" + ], + "q2w3-post-order": [ + "cpe:2.3:a:q2w3:q2w3_post_order:*:*:*:*:*:wordpress:*:*" + ], + "qi-addons-for-elementor": [ + "cpe:2.3:a:qodeinteractive:qi_addons_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "qi-blocks": [ + "cpe:2.3:a:qodeinteractive:qi_blocks:*:*:*:*:*:wordpress:*:*" + ], + "qode-essential-addons": [ + "cpe:2.3:a:qodeinteractive:qode_essential_addons:*:*:*:*:*:wordpress:*:*" + ], + "qr-code-tag": [ + "cpe:2.3:a:spreendigital:qr_code_tag:*:*:*:*:*:wordpress:*:*" + ], + "qr-redirector": [ + "cpe:2.3:a:qr_redirector_project:qr_redirector:*:*:*:*:*:wordpress:*:*" + ], + "qr-twitter-widget": [ + "cpe:2.3:a:qrokes:qr_twitter_widget:*:*:*:*:*:wordpress:*:*" + ], + "qtranslate-slug": [ + "cpe:2.3:a:qtranslate_slug_project:qtranslate_slug:*:*:*:*:*:wordpress:*:*" + ], + "qtranslate-x": [ + "cpe:2.3:a:qtranslate_x_project:qtranslate_x:*:*:*:*:*:wordpress:*:*" + ], + "qubely": [ + "cpe:2.3:a:themeum:qubely:*:*:*:*:*:wordpress:*:*" + ], + "querlo-chatbots": [ + "cpe:2.3:a:querlo:chatbot:*:*:*:*:*:wordpress:*:*" + ], + "quick-chat": [ + "cpe:2.3:a:quick_chat_project:quick_chat:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:techytalk:quick_chat:*:*:*:*:*:wordpress:*:*" + ], + "quick-contact-form": [ + "cpe:2.3:a:fullworksplugins:quick_contact_form:*:*:*:*:*:wordpress:*:*" + ], + "quick-edit-template-link": [ + "cpe:2.3:a:template_debugger_project:template_debugger:*:*:*:*:*:wordpress:*:*" + ], + "quick-event-manager": [ + "cpe:2.3:a:fullworksplugins:quick_event_manager:*:*:*:*:*:wordpress:*:*" + ], + "quick-interest-slider": [ + "cpe:2.3:a:quick-plugins:loan_repayment_calculator_and_application_form:*:*:*:*:*:wordpress:*:*" + ], + "quick-pagepost-redirect-plugin": [ + "cpe:2.3:a:anadnet:quick_page\\/post_redirect_plugin:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:quick_page\\/post_redirect_project:quick_page\\/post_redirect:*:*:*:*:*:wordpress:*:*" + ], + "quick-paypal-payments": [ + "cpe:2.3:a:fullworksplugins:quick_paypal_payments:*:*:*:*:*:wordpress:*:*" + ], + "quick-restaurant-menu": [ + "cpe:2.3:a:thingsforrestaurants:quick_restaurant_reservations:*:*:*:*:*:wordpress:*:*" + ], + "quick-restaurant-reservations": [ + "cpe:2.3:a:thingsforrestaurants:quick_restaurant_reservations:*:*:*:*:*:wordpress:*:*" + ], + "quick-subscribe": [ + "cpe:2.3:a:quick_subscribe_project:quick_subscribe:*:*:*:*:*:wordpress:*:*" + ], + "quickswish": [ + "cpe:2.3:a:hasthemes:quickswish:*:*:*:*:*:wordpress:*:*" + ], + "quiz-expert": [ + "cpe:2.3:a:wepupil:quiz_expert_-_easy_quiz_maker\\,_exam_and_test_manager:*:*:*:*:*:wordpress:*:*" + ], + "quiz-maker": [ + "cpe:2.3:a:ays-pro:quiz_maker:*:*:*:*:*:wordpress:*:*" + ], + "quiz-master-next": [ + "cpe:2.3:a:expresstech:quiz_and_survey_master:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:quizandsurveymaster:quiz_and_survey_master:*:*:*:*:*:wordpress:*:*" + ], + "quiz-tool-lite": [ + "cpe:2.3:a:quiz_tool_lite_project:quiz_tool_lite:*:*:*:*:*:wordpress:*:*" + ], + "quizlord": [ + "cpe:2.3:a:vms-studio:quizlord:*:*:*:*:*:wordpress:*:*" + ], + "quotes-and-tips": [ + "cpe:2.3:a:bestwebsoft:quotes_and_tips:*:*:*:*:*:wordpress:*:*" + ], + "quotes-collection": [ + "cpe:2.3:a:quotes_collection_project:quotes_collection:*:*:*:*:*:wordpress:*:*" + ], + "quotes-llama": [ + "cpe:2.3:a:quotes_llama_project:quotes_llama:*:*:*:*:*:wordpress:*:*" + ], + "quttera-web-malware-scanner": [ + "cpe:2.3:a:quttera:quttera_web_malware_scanner:*:*:*:*:*:wordpress:*:*" + ], + "qwiz-online-quizzes-and-flashcards": [ + "cpe:2.3:a:qwizcards_project:qwizcards:*:*:*:*:*:wordpress:*:*" + ], + "qyrr-code": [ + "cpe:2.3:a:patrickposner:qyrr:*:*:*:*:*:wordpress:*:*" + ], + "radio-buttons-for-taxonomies": [ + "cpe:2.3:a:radio_buttons_for_taxonomies_project:radio_buttons_for_taxonomies:*:*:*:*:*:wordpress:*:*" + ], + "radio-forge": [ + "cpe:2.3:a:radioforge:radio_forge_muses_player_with_skins:*:*:*:*:*:wordpress:*:*" + ], + "rafflepress": [ + "cpe:2.3:a:seedprod:rafflepress:*:*:*:*:*:wordpress:*:*" + ], + "random-banner": [ + "cpe:2.3:a:buffercode:random_banner:*:*:*:*:*:wordpress:*:*" + ], + "randomize": [ + "cpe:2.3:a:javik:randomize:*:*:*:*:*:wordpress:*:*" + ], + "randomtext": [ + "cpe:2.3:a:random_text_project:random_text:*:*:*:*:*:wordpress:*:*" + ], + "rara-one-click-demo-import": [ + "cpe:2.3:a:rarathemes:rara_one_click_demo_import:*:*:*:*:*:wordpress:*:*" + ], + "rate-my-post": [ + "cpe:2.3:a:blazzdev:rate_my_post:*:*:*:*:*:wordpress:*:*" + ], + "rate-star-review": [ + "cpe:2.3:a:videowhisper:rate_star_review:*:*:*:*:*:wordpress:*:*" + ], + "rating-bws": [ + "cpe:2.3:a:bestwebsoft:rating:*:*:*:*:*:wordpress:*:*" + ], + "rating-widget": [ + "cpe:2.3:a:rating-widget:ratingwidget:*:*:*:*:*:wordpress:*:*" + ], + "ravpage": [ + "cpe:2.3:a:ravpage_project:ravpage:*:*:*:*:*:wordpress:*:*" + ], + "raygun4wp": [ + "cpe:2.3:a:raygun:raygun4wp:*:*:*:*:*:wordpress:*:*" + ], + "rays-grid": [ + "cpe:2.3:a:rays_grid_project:rays_grid:*:*:*:*:*:wordpress:*:*" + ], + "rb-internal-links": [ + "cpe:2.3:a:rb_internal_links_project:rb_internal_links:*:*:*:*:*:wordpress:*:*" + ], + "rduplicator": [ + "cpe:2.3:a:wpspeedx:rduplicator:*:*:*:*:*:wordpress:*:*" + ], + "re-attacher": [ + "cpe:2.3:a:bestwebsoft:re-attacher:*:*:*:*:*:wordpress:*:*" + ], + "react-webcam": [ + "cpe:2.3:a:react_webcam_project:react_webcam:*:*:*:*:*:wordpress:*:*" + ], + "read-and-understood": [ + "cpe:2.3:a:read_and_understood_project:read_and_understood:*:*:*:*:*:wordpress:*:*" + ], + "read-more-without-refresh": [ + "cpe:2.3:a:8web:read_more_without_refresh:*:*:*:*:*:wordpress:*:*" + ], + "real-cookie-banner": [ + "cpe:2.3:a:devowl:wordpress_real_cookie_banner:*:*:*:*:*:wordpress:*:*" + ], + "real-estate-manager": [ + "cpe:2.3:a:webcodingplace:real_estate_manager:*:*:*:*:*:wordpress:*:*" + ], + "real-kit": [ + "cpe:2.3:a:real.kit_project:real.kit:*:*:*:*:*:wordpress:*:*" + ], + "real-media-library-lite": [ + "cpe:2.3:a:devowl:wordpress_real_media_library:*:*:*:*:*:wordpress:*:*" + ], + "real-time-auto-find-and-replace": [ + "cpe:2.3:a:codesolz:better_find_and_replace:*:*:*:*:*:wordpress:*:*" + ], + "real-time-find-and-replace": [ + "cpe:2.3:a:infolific:real-time_find_and_replace:*:*:*:*:*:wordpress:*:*" + ], + "real3d-flipbook-lite": [ + "cpe:2.3:a:creativeinteractivemedia:real3d_flipbook:*:*:*:*:*:wordpress:*:*" + ], + "realia": [ + "cpe:2.3:a:pragmaticmates:realia:*:*:*:*:*:wordpress:*:*" + ], + "really-simple-google-tag-manager": [ + "cpe:2.3:a:hasthemes:really_simple_google_tag_manager:*:*:*:*:*:wordpress:*:*" + ], + "realty": [ + "cpe:2.3:a:bestwebsoft:realty:*:*:*:*:*:wordpress:*:*" + ], + "realty-workstation": [ + "cpe:2.3:a:realty_workstation:realty_workstation:*:*:*:*:*:wordpress:*:*" + ], + "rearrange-woocommerce-products": [ + "cpe:2.3:a:rearrange_woocommerce_products_project:rearrange_woocommerce_products:*:*:*:*:*:wordpress:*:*" + ], + "recall-products": [ + "cpe:2.3:a:recall-products_project:recall-products:*:*:*:*:*:wordpress:*:*" + ], + "recent-backups": [ + "cpe:2.3:a:recent-backups_project:recent-backups:*:*:*:*:*:wordpress:*:*" + ], + "recent-posts-slider": [ + "cpe:2.3:a:recent_posts_slider_project:recent_posts_slider:*:*:*:*:*:wordpress:*:*" + ], + "recently-viewed-products": [ + "cpe:2.3:a:rajarora795:recently_viewed_products:*:*:*:*:*:wordpress:*:*" + ], + "recipe-card-blocks-by-wpzoom": [ + "cpe:2.3:a:wpzoom:recipe_card_blocks_for_gutenberg_\\\u0026_elementor:*:*:*:*:*:wordpress:*:*" + ], + "reciply": [ + "cpe:2.3:a:reciply_project:reciply:*:*:*:*:*:wordpress:*:*" + ], + "redi-restaurant-reservation": [ + "cpe:2.3:a:catzsoft:redi_restaurant_reservation:*:*:*:*:*:wordpress:*:*" + ], + "redirect-404-error-page-to-homepage-or-custom-page": [ + "cpe:2.3:a:fullworks:redirect_404_error_page_to_homepage_or_custom_page_with_logs:*:*:*:*:*:wordpress:*:*" + ], + "redirect-404-to-parent": [ + "cpe:2.3:a:mooveagency:redirect_404_to_parent:*:*:*:*:*:wordpress:*:*" + ], + "redirect-redirection": [ + "cpe:2.3:a:inisev:redirection:*:*:*:*:*:wordpress:*:*" + ], + "redirection": [ + "cpe:2.3:a:redirection:redirection:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:redirection_project:redirection:*:*:*:*:*:wordpress:*:*" + ], + "redux-framework": [ + "cpe:2.3:a:redux:gutenberg_template_library_\\\u0026_redux_framework:*:*:*:*:*:wordpress:*:*" + ], + "refer-a-friend-widget-for-wp": [ + "cpe:2.3:a:invitebox:invitebox:*:*:*:*:*:wordpress:*:*" + ], + "reflex-gallery": [ + "cpe:2.3:a:reflex_gallery_project:reflex_gallery:*:*:*:*:*:wordpress:*:*" + ], + "regenerate-thumbnails": [ + "cpe:2.3:a:regenerate_thumbnails_project:regenerate_thumbnails:*:*:*:*:*:wordpress:*:*" + ], + "registrations-for-the-events-calendar": [ + "cpe:2.3:a:roundupwp:registrations_for_the_events_calendar:*:*:*:*:*:wordpress:*:*" + ], + "related-posts-for-wp": [ + "cpe:2.3:a:never5:related_posts:*:*:*:*:*:wordpress:*:*" + ], + "related-youtube-videos": [ + "cpe:2.3:a:meomundo:related_youtube_videos:*:*:*:*:*:wordpress:*:*" + ], + "relevanssi": [ + "cpe:2.3:a:relevanssi:relevanssi:*:*:*:*:*:wordpress:*:*" + ], + "relevant": [ + "cpe:2.3:a:bestwebsoft:relevant:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:bestwebsoft:relevant_-_related_posts:*:*:*:*:*:wordpress:*:*" + ], + "remove-footer-credit": [ + "cpe:2.3:a:wpchill:remove_footer_credit:*:*:*:*:*:wordpress:*:*" + ], + "remove-schema": [ + "cpe:2.3:a:websitescanner:remove_schema:*:*:*:*:*:wordpress:*:*" + ], + "removehide-author-date-category-like-entry-meta": [ + "cpe:2.3:a:remove\\/hide_author\\,_date\\,_category_like_entry-meta_project:remove\\/hide_author\\,_date\\,_category_like_entry-meta:*:*:*:*:*:wordpress:*:*" + ], + "rename-media-files": [ + "cpe:2.3:a:milandinic:rename_media_files:*:*:*:*:*:wordpress:*:*" + ], + "rename-wp-login": [ + "cpe:2.3:a:rename_wp-login_project:rename_wp-login:*:*:*:*:*:wordpress:*:*" + ], + "rencontre": [ + "cpe:2.3:a:boiteasite:download_rencontre_-_dating_site:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:boiteasite:rencontre:*:*:*:*:*:wordpress:*:*" + ], + "rentpress": [ + "cpe:2.3:a:30lines:rentpress:*:*:*:*:*:wordpress:*:*" + ], + "republish-old-posts": [ + "cpe:2.3:a:mariosalexandrou:republish_old_posts:*:*:*:*:*:wordpress:*:*" + ], + "request-a-quote": [ + "cpe:2.3:a:emarketdesign:request_a_quote:*:*:*:*:*:wordpress:*:*" + ], + "resads": [ + "cpe:2.3:a:web-mv:resads:*:*:*:*:*:wordpress:*:*" + ], + "rescue-shortcodes": [ + "cpe:2.3:a:rescuethemes:rescue_shortcodes:*:*:*:*:*:wordpress:*:*" + ], + "resend-welcome-email": [ + "cpe:2.3:a:resend_welcome_email_project:resend_welcome_email:*:*:*:*:*:wordpress:*:*" + ], + "reservation-studio-widget": [ + "cpe:2.3:a:pvmg:reservation.studio:*:*:*:*:*:wordpress:*:*" + ], + "resize-at-upload-plus": [ + "cpe:2.3:a:resize_at_upload_plus_project:resize_at_upload_plus:*:*:*:*:*:wordpress:*:*" + ], + "resmushit-image-optimizer": [ + "cpe:2.3:a:resmush.it:resmush.it_image_optimizer:*:*:*:*:*:wordpress:*:*" + ], + "responsive-add-ons": [ + "cpe:2.3:a:cyberchimps:gutenberg_\\\u0026_elementor_templates_importer_for_responsive:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:cyberchimps:responsive_addons:*:*:*:*:*:wordpress:*:*" + ], + "responsive-column-widgets": [ + "cpe:2.3:a:michaeluno:responsive_column_widgets:*:*:*:*:*:wordpress:*:*" + ], + "responsive-coming-soon": [ + "cpe:2.3:a:wpshopmart:coming_soon_page_\\\u0026_maintenance_mode:*:*:*:*:*:wordpress:*:*" + ], + "responsive-coming-soon-page": [ + "cpe:2.3:a:responsive_coming_soon_page_project:responsive_coming_soon_page:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:weblizar:responsive_coming_soon_\\\u0026_maintenance_mode:*:*:*:*:*:wordpress:*:*" + ], + "responsive-css-editor": [ + "cpe:2.3:a:wpwox:responsive_css_editor:*:*:*:*:*:wordpress:*:*" + ], + "responsive-gallery-grid": [ + "cpe:2.3:a:bdwm:responsive_gallery_grid:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:responsive_gallery_grid_project:responsive_gallery_grid:*:*:*:*:*:wordpress:*:*" + ], + "responsive-header-image-slider": [ + "cpe:2.3:a:wponlinesupport:wp_responsive_header_image_slider:*:*:*:*:*:wordpress:*:*" + ], + "responsive-horizontal-vertical-and-accordion-tabs": [ + "cpe:2.3:a:i13websolution:wp_responsive_tabs:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:i13websolution:wp_responsive_tabs_horizontal_vertical_and_accordion_tabs:*:*:*:*:*:wordpress:*:*" + ], + "responsive-lightbox": [ + "cpe:2.3:a:dfactory:responsive_lightbox:*:*:*:*:*:wordpress:*:*" + ], + "responsive-lightbox2": [ + "cpe:2.3:a:noorsplugin:responsive_lightbox2:*:*:*:*:*:wordpress:*:*" + ], + "responsive-menu": [ + "cpe:2.3:a:expresstech:responsive_menu:*:*:*:*:*:wordpress:*:*" + ], + "responsive-tabs": [ + "cpe:2.3:a:wpdarko:responsive_tabs:*:*:*:*:*:wordpress:*:*" + ], + "responsive-vector-maps": [ + "cpe:2.3:a:thinkupthemes:responsive_vector_maps:*:*:*:*:*:wordpress:*:*" + ], + "restaurant-pickup-delivery-dine-in": [ + "cpe:2.3:a:byconsole:pickup_\\|_delivery_\\|_dine-in_date_time:*:*:*:*:*:wordpress:*:*" + ], + "restaurant-reservations": [ + "cpe:2.3:a:fivestarplugins:five_star_restaurant_reservations:*:*:*:*:*:wordpress:*:*" + ], + "restrict-content": [ + "cpe:2.3:a:liquidweb:restrict_content:*:*:*:*:*:wordpress:*:*" + ], + "restrict-usernames-emails-characters": [ + "cpe:2.3:a:benaceur-php:restrict_usernames_emails_characters:*:*:*:*:*:wordpress:*:*" + ], + "restricted-content": [ + "cpe:2.3:a:tickera:restrict:*:*:*:*:*:wordpress:*:*" + ], + "restricted-site-access": [ + "cpe:2.3:a:10up:restricted_site_access:*:*:*:*:*:wordpress:*:*" + ], + "resume-builder": [ + "cpe:2.3:a:resumebuilder:resume_builder:*:*:*:*:*:wordpress:*:*" + ], + "reusable-blocks-extended": [ + "cpe:2.3:a:jeanbaptisteaudras:reusable_blocks_extended:*:*:*:*:*:wordpress:*:*" + ], + "review-buddypress-groups": [ + "cpe:2.3:a:wbcomdesigns:buddypress_group_reviews:*:*:*:*:*:wordpress:*:*" + ], + "review-schema": [ + "cpe:2.3:a:radiustheme:review_schema:*:*:*:*:*:wordpress:*:*" + ], + "reviews-plus": [ + "cpe:2.3:a:implecode:reviews_plus:*:*:*:*:*:wordpress:*:*" + ], + "reviewx": [ + "cpe:2.3:a:wpdeveloper:reviewx:*:*:*:*:*:wordpress:*:*" + ], + "rezgo": [ + "cpe:2.3:a:rezgo:rezgo_online_booking:*:*:*:*:*:wordpress:*:*" + ], + "rich-counter": [ + "cpe:2.3:a:saschart:rich_counter:*:*:*:*:*:wordpress:*:*" + ], + "rich-event-timeline": [ + "cpe:2.3:a:rich-web:event_timeline:*:*:*:*:*:wordpress:*:*" + ], + "rich-reviews": [ + "cpe:2.3:a:starfish:rich_review:*:*:*:*:*:wordpress:*:*" + ], + "rich-table-of-content": [ + "cpe:2.3:a:croover:rich_table_of_contents:*:*:*:*:*:wordpress:*:*" + ], + "rife-elementor-extensions": [ + "cpe:2.3:a:apollo13themes:rife_elementor_extensions_\\\u0026_templates:*:*:*:*:*:wordpress:*:*" + ], + "rimons-twitter-widget": [ + "cpe:2.3:a:rimons_twitter_widget_project:rimons_twitter_widget:*:*:*:*:*:wordpress:*:*" + ], + "rise-blocks": [ + "cpe:2.3:a:eaglevisionit:rise_blocks:*:*:*:*:*:wordpress:*:*" + ], + "rk-responsive-contact-form": [ + "cpe:2.3:a:rkdownload:rk-responsive-contact-form:*:*:*:*:*:wordpress:*:*" + ], + "robo-gallery": [ + "cpe:2.3:a:robogallery:robo_gallery:*:*:*:*:*:wordpress:*:*" + ], + "rock-convert": [ + "cpe:2.3:a:rockcontent:rock_convert:*:*:*:*:*:wordpress:*:*" + ], + "rocket-font": [ + "cpe:2.3:a:qwerty23:rocket_font:*:*:*:*:*:wordpress:*:*" + ], + "rocket-maintenance-mode": [ + "cpe:2.3:a:wpexperts:rocket_maintenance_mode_\\\u0026_coming_soon_page:*:*:*:*:*:wordpress:*:*" + ], + "role-scoper": [ + "cpe:2.3:a:role_scoper_project:role_scoper:*:*:*:*:*:wordpress:*:*" + ], + "roomcloud": [ + "cpe:2.3:a:roomcloud:roomcloud:*:*:*:*:*:wordpress:*:*" + ], + "rough-chart": [ + "cpe:2.3:a:rough_chart_project:rough_chart:*:*:*:*:*:wordpress:*:*" + ], + "royal-elementor-addons": [ + "cpe:2.3:a:royal-elementor-addons:royal_elementor_addons:*:*:*:*:*:wordpress:*:*" + ], + "rsfirewall": [ + "cpe:2.3:a:rsjoomla:rsfirewall\\!:*:*:*:*:*:wordpress:*:*" + ], + "rss-feed-widget": [ + "cpe:2.3:a:rss_feed_widget_project:rss_feed_widget:*:*:*:*:*:wordpress:*:*" + ], + "rss-for-yandex-turbo": [ + "cpe:2.3:a:wpuslugi:rss_for_yandex_turbo:*:*:*:*:*:wordpress:*:*" + ], + "rsvp": [ + "cpe:2.3:a:swimordiesoftware:rsvp:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpchill:rsvp_and_event_management:*:*:*:*:*:wordpress:*:*" + ], + "rsvpmaker": [ + "cpe:2.3:a:carrcommunications:rsvpmaker:*:*:*:*:*:wordpress:*:*" + ], + "rsvpmaker-excel": [ + "cpe:2.3:a:carrcommunications:rsvpmaker_excel:*:*:*:*:*:wordpress:*:*" + ], + "rt-easy-builder-advanced-addons-for-elementor": [ + "cpe:2.3:a:risethemes:rt_easy_builder:*:*:*:*:*:wordpress:*:*" + ], + "rt-prettyphoto": [ + "cpe:2.3:a:royaltechbd:royal_prettyphoto:*:*:*:*:*:wordpress:*:*" + ], + "ruby-help-desk": [ + "cpe:2.3:a:wpruby:ruby_help_desk:*:*:*:*:*:wordpress:*:*" + ], + "rucy": [ + "cpe:2.3:a:rucy_project:rucy:*:*:*:*:*:wordpress:*:*" + ], + "rustolat": [ + "cpe:2.3:a:rus-to-lat_project:rus-to-lat:*:*:*:*:*:wordpress:*:*" + ], + "ruven-toolkit": [ + "cpe:2.3:a:ruven-toolkit_project:ruven-toolkit:*:*:*:*:*:wordpress:*:*" + ], + "s3bubble-amazon-s3-audio-streaming": [ + "cpe:2.3:a:s3bubble:s3bubble-amazon-s3-audio-streaming:*:*:*:*:*:wordpress:*:*" + ], + "s3bubble-amazon-s3-html-5-video-with-adverts": [ + "cpe:2.3:a:s3bubble:s3bubble-amazon-s3-html-5-video-with-adverts:*:*:*:*:*:wordpress:*:*" + ], + "saan-world-clock": [ + "cpe:2.3:a:saan:world_clock:*:*:*:*:*:wordpress:*:*" + ], + "safe-editor": [ + "cpe:2.3:a:kodebyraaet:safe_editor:*:*:*:*:*:wordpress:*:*" + ], + "safe-svg": [ + "cpe:2.3:a:10up:safe_svg:*:*:*:*:*:wordpress:*:*" + ], + "sagepay-server-gateway-for-woocommerce": [ + "cpe:2.3:a:patsatech:sagepay_server_gateway_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "salat-times": [ + "cpe:2.3:a:salat_times_project:salat_times:*:*:*:*:*:wordpress:*:*" + ], + "salesmanago": [ + "cpe:2.3:a:salesmanago:salesmanago:*:*:*:*:*:wordpress:*:*" + ], + "salon-booking-system": [ + "cpe:2.3:a:salonbookingsystem:salon_booking_system:*:*:*:*:*:wordpress:*:*" + ], + "sassy-social-share": [ + "cpe:2.3:a:heateor:sassy_social_share:*:*:*:*:*:wordpress:*:*" + ], + "save-as-pdf-by-pdfcrowd": [ + "cpe:2.3:a:pdfcrowd:save_as_pdf:*:*:*:*:*:wordpress:*:*" + ], + "save-grab": [ + "cpe:2.3:a:neobie:grab_\\\u0026_save:*:*:*:*:*:wordpress:*:*" + ], + "sayfa-sayac": [ + "cpe:2.3:a:dmry:sayfa_sayac:*:*:*:*:*:wordpress:*:*" + ], + "sb-child-list": [ + "cpe:2.3:a:sean-barton:sb_child_list:*:*:*:*:*:wordpress:*:*" + ], + "sb-elementor-contact-form-db": [ + "cpe:2.3:a:sean-barton:elementor_contact_form_db:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:webacetechs:contact_form_db_-_elementor:*:*:*:*:*:wordpress:*:*" + ], + "schedule-posts-calendar": [ + "cpe:2.3:a:toolstack:schedule_posts_calendar:*:*:*:*:*:wordpress:*:*" + ], + "scheduled-announcements-widget": [ + "cpe:2.3:a:nlb-creations:scheduled_announcements_widget:*:*:*:*:*:wordpress:*:*" + ], + "schedulicity-online-appointment-booking": [ + "cpe:2.3:a:schedulicity:schedulicity:*:*:*:*:*:wordpress:*:*" + ], + "school-management-system": [ + "cpe:2.3:a:weblizar:school_management_-_education_\\\u0026_learning_management:*:*:*:*:*:wordpress:*:*" + ], + "schreikasten": [ + "cpe:2.3:a:schreikasten_project:schreikasten:*:*:*:*:*:wordpress:*:*" + ], + "scoutnet-kalender": [ + "cpe:2.3:a:scoutnet:kalender:*:*:*:*:*:wordpress:*:*" + ], + "scribble-maps": [ + "cpe:2.3:a:scribblemaps:scribble_maps:*:*:*:*:*:wordpress:*:*" + ], + "scriptless-social-sharing": [ + "cpe:2.3:a:robincornett:scriptless_social_sharing:*:*:*:*:*:wordpress:*:*" + ], + "scroll-post-excerpt": [ + "cpe:2.3:a:gopiplus:scroll_post_excerpt:*:*:*:*:*:wordpress:*:*" + ], + "se-html5-album-audio-player": [ + "cpe:2.3:a:se_html5_album_audio_player_project:se_html5_album_audio_player:*:*:*:*:*:wordpress:*:*" + ], + "seamless-donations": [ + "cpe:2.3:a:seamless_donations_project:seamless_donations:*:*:*:*:*:wordpress:*:*" + ], + "search-analytics": [ + "cpe:2.3:a:cornelraiu:wp_search_analytics:*:*:*:*:*:wordpress:*:*" + ], + "search-everything": [ + "cpe:2.3:a:search_everything_project:search_everything:*:*:*:*:*:wordpress:*:*" + ], + "search-exclude": [ + "cpe:2.3:a:search_exclude_project:search_exclude:*:*:*:*:*:wordpress:*:*" + ], + "search-filter": [ + "cpe:2.3:a:codeamp:search_\\\u0026_filter:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:search_\\\u0026_filter_project:search_\\\u0026_filter:*:*:*:*:*:wordpress:*:*" + ], + "search-meter": [ + "cpe:2.3:a:search_meter_project:search_meter:*:*:*:*:*:wordpress:*:*" + ], + "searchiq": [ + "cpe:2.3:a:searchiq:searchiq:*:*:*:*:*:wordpress:*:*" + ], + "searchterms-tagging-2": [ + "cpe:2.3:a:seo_searchterms_tagging_2_project:seo_searchterms_tagging_2:*:*:*:*:*:wordpress:*:*" + ], + "searchwp-live-ajax-search": [ + "cpe:2.3:a:searchwp:searchwp_live_ajax_search:*:*:*:*:*:wordpress:*:*" + ], + "secondary-title": [ + "cpe:2.3:a:secondary_title_project:secondary_title:*:*:*:*:*:wordpress:*:*" + ], + "secure-copy-content-protection": [ + "cpe:2.3:a:ays-pro:secure_copy_content_protection_and_content_locking:*:*:*:*:*:wordpress:*:*" + ], + "secure-file-manager": [ + "cpe:2.3:a:themexa:secure_file_manager:*:*:*:*:*:wordpress:*:*" + ], + "secure-files": [ + "cpe:2.3:a:wp-plugins:secure_files:*:*:*:*:*:wordpress:*:*" + ], + "securemoz-security-audit": [ + "cpe:2.3:a:securemoz:security_audit:*:*:*:*:*:wordpress:*:*" + ], + "securimage-wp-fixed": [ + "cpe:2.3:a:securimage-wp-fixed_project:securimage-wp-fixed:*:*:*:*:*:wordpress:*:*" + ], + "security-malware-firewall": [ + "cpe:2.3:a:cleantalk:security_\\\u0026_malware_scan:*:*:*:*:*:wordpress:*:*" + ], + "seed-social": [ + "cpe:2.3:a:seedwebs:seed_social:*:*:*:*:*:wordpress:*:*" + ], + "select-all-categories-and-taxonomies-change-checkbox-to-radio-buttons": [ + "cpe:2.3:a:mooveagency:select_all_categories_and_taxonomies\\,_change_checkbox_to_radio_buttons:*:*:*:*:*:wordpress:*:*" + ], + "sell-downloads": [ + "cpe:2.3:a:codepeople:sell_downloads:*:*:*:*:*:wordpress:*:*" + ], + "sell-media": [ + "cpe:2.3:a:graphpaperpress:sell_media:*:*:*:*:*:wordpress:*:*" + ], + "send-users-email": [ + "cpe:2.3:a:sumanbhattarai:send_users_email:*:*:*:*:*:wordpress:*:*" + ], + "sender": [ + "cpe:2.3:a:bestwebsoft:sender:*:*:*:*:*:wordpress:*:*" + ], + "sendgrid-email-delivery-simplified": [ + "cpe:2.3:a:sendgrid:sendgrid:*:*:*:*:*:wordpress:*:*" + ], + "sendit": [ + "cpe:2.3:a:sendit_project:sendit:*:*:*:*:*:wordpress:*:*" + ], + "sendpress": [ + "cpe:2.3:a:pressified:sendpress:*:*:*:*:*:wordpress:*:*" + ], + "sendpulse-web-push": [ + "cpe:2.3:a:sendpulse:free_web_push:*:*:*:*:*:wordpress:*:*" + ], + "sensei-lms": [ + "cpe:2.3:a:automattic:sensei_lms:*:*:*:*:*:wordpress:*:*" + ], + "seo-301-meta": [ + "cpe:2.3:a:seo-301-meta_project:seo-301-meta:*:*:*:*:*:wordpress:*:*" + ], + "seo-backlinks": [ + "cpe:2.3:a:seo_backlinks_project:seo_backlinks:*:*:*:*:*:wordpress:*:*" + ], + "seo-booster": [ + "cpe:2.3:a:cleverplugins:seo_booster:*:*:*:*:*:wordpress:*:*" + ], + "seo-by-10web": [ + "cpe:2.3:a:10web:seo:*:*:*:*:*:wordpress:*:*" + ], + "seo-by-rank-math": [ + "cpe:2.3:a:rankmath:seo:*:*:*:*:free:wordpress:*:*" + ], + "seo-redirection": [ + "cpe:2.3:a:clogica:seo_redirection:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:clogica:seo_redirection_plugin:*:*:*:*:*:wordpress:*:*" + ], + "seo-slider": [ + "cpe:2.3:a:seothemes:seo_slider:*:*:*:*:*:wordpress:*:*" + ], + "seos-contact-form": [ + "cpe:2.3:a:seosthemes:seos_contact_form:*:*:*:*:*:wordpress:*:*" + ], + "seraphinite-accelerator": [ + "cpe:2.3:a:seraphinitesolutions:seraphinite_accelerator:*:*:*:*:*:wordpress:*:*" + ], + "seraphinite-post-docx-source": [ + "cpe:2.3:a:s-sols:seraphinite_post_.docx_source:*:*:*:*:*:wordpress:*:*" + ], + "serial-codes-generator-and-validator": [ + "cpe:2.3:a:nikolov:serial_codes_generator_and_validator_with_woocommerce_support:*:*:*:*:*:wordpress:*:*" + ], + "seriously-simple-podcasting": [ + "cpe:2.3:a:castos:seriously_simple_podcasting:*:*:*:*:*:wordpress:*:*" + ], + "seriously-simple-stats": [ + "cpe:2.3:a:castos:seriously_simple_stats:*:*:*:*:*:wordpress:*:*" + ], + "sermon-browser": [ + "cpe:2.3:a:sermon_browser_project:sermon_browser:*:*:*:*:*:wordpress:*:*" + ], + "sermone-online-sermons-management": [ + "cpe:2.3:a:bearthemes:sermon\\'e_-_sermons_online:*:*:*:*:*:wordpress:*:*" + ], + "server-status-by-hostnameip": [ + "cpe:2.3:a:xpertsol:server_status_by_hostname\\/ip:*:*:*:*:*:wordpress:*:*" + ], + "service-area-postcode-checker": [ + "cpe:2.3:a:plustime:service_area_postcode_checker:*:*:*:*:*:wordpress:*:*" + ], + "seur": [ + "cpe:2.3:a:seur_oficial_project:seur_oficial:*:*:*:*:*:wordpress:*:*" + ], + "sexy-contact-form": [ + "cpe:2.3:a:creative-solutions:creative_contact_form:*:*:*:*:*:wordpress:*:*" + ], + "sfwd-lms": [ + "cpe:2.3:a:learndash:learndash:*:*:*:*:*:wordpress:*:*" + ], + "sg-security": [ + "cpe:2.3:a:siteground:security_optimizer:*:*:*:*:*:wordpress:*:*" + ], + "shapepress-dsgvo": [ + "cpe:2.3:a:legalweb:wp_dsgvo_tools:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:shapepress:wp_dsgvo_tools:*:*:*:*:*:wordpress:*:*" + ], + "share-on-diaspora": [ + "cpe:2.3:a:share_on_diaspora_project:share_on_diaspora:*:*:*:*:*:wordpress:*:*" + ], + "share-this-image": [ + "cpe:2.3:a:share_this_image_project:share_this_image:*:*:*:*:*:wordpress:*:*" + ], + "shareaholic": [ + "cpe:2.3:a:shareaholic:shareaholic:*:*:*:*:*:wordpress:*:*" + ], + "sharebar": [ + "cpe:2.3:a:sharebar_project:sharebar:*:*:*:*:*:wordpress:*:*" + ], + "shared-files": [ + "cpe:2.3:a:tammersoft:shared_files:*:*:*:*:*:wordpress:*:*" + ], + "sheets-to-wp-table-live-sync": [ + "cpe:2.3:a:wppool:sheets_to_wp_table_live_sync:*:*:*:*:*:wordpress:*:*" + ], + "shibboleth": [ + "cpe:2.3:a:shibboleth_project:shibboleth:*:*:*:*:*:wordpress:*:*" + ], + "shiftcontroller": [ + "cpe:2.3:a:plainware:shiftcontroller:*:*:*:*:*:wordpress:*:*" + ], + "shiftnav-responsive-mobile-menu": [ + "cpe:2.3:a:sevenspark:shiftnav:*:*:*:*:*:wordpress:*:*" + ], + "shiny-buttons": [ + "cpe:2.3:a:wpeden:shiny_buttons:*:*:*:*:*:wordpress:*:*" + ], + "shopello": [ + "cpe:2.3:a:shopello_api_project:shopello_api:*:*:*:*:*:wordpress:*:*" + ], + "shopengine": [ + "cpe:2.3:a:wpmet:shopengine:*:*:*:*:*:wordpress:*:*" + ], + "shopp": [ + "cpe:2.3:a:ingenesis:shopp:*:*:*:*:*:wordpress:*:*" + ], + "shopping-pages": [ + "cpe:2.3:a:cmscommander:wp_shopping_pages:*:*:*:*:*:wordpress:*:*" + ], + "shortcode-addons": [ + "cpe:2.3:a:oxilab:shortcode_addons:*:*:*:*:*:wordpress:*:*" + ], + "shortcode-factory": [ + "cpe:2.3:a:wpmadeasy:shortcode_factory:*:*:*:*:*:wordpress:*:*" + ], + "shortcode-gallery-for-matterport-showcase": [ + "cpe:2.3:a:mpembed:wp_matterport_shortcode:*:*:*:*:*:wordpress:*:*" + ], + "shortcode-imdb": [ + "cpe:2.3:a:kemalyazici:shortcode_imdb:*:*:*:*:*:wordpress:*:*" + ], + "shortcode-menu": [ + "cpe:2.3:a:shortcode_menu_project:shortcod_menu:*:*:*:*:*:wordpress:*:*" + ], + "shortcode-to-display-post-and-user-data": [ + "cpe:2.3:a:vegacorp:display_custom_fields_in_the_frontend_-_post_and_user_profile_fields:*:*:*:*:*:wordpress:*:*" + ], + "shortcodes-finder": [ + "cpe:2.3:a:scribit:shortcodes_finder:*:*:*:*:*:wordpress:*:*" + ], + "shortcodes-ui": [ + "cpe:2.3:a:bainternet:shortcodes_ui:*:*:*:*:*:wordpress:*:*" + ], + "shortcodes-ultimate": [ + "cpe:2.3:a:getshortcodes:shortcodes_ultimate:*:*:*:*:*:wordpress:*:*" + ], + "shortcut-macros": [ + "cpe:2.3:a:shortcut_macros_project:shortcut_macros:*:*:*:*:*:wordpress:*:*" + ], + "shorten-url": [ + "cpe:2.3:a:kaizencoders:short_url:*:*:*:*:*:wordpress:*:*" + ], + "shortpixel-adaptive-images": [ + "cpe:2.3:a:shortpixel:shortpixel_adaptive_images:*:*:*:*:*:wordpress:*:*" + ], + "show-all-comments-in-one-page": [ + "cpe:2.3:a:appjetty:show_all_comments:*:*:*:*:*:wordpress:*:*" + ], + "show-posts": [ + "cpe:2.3:a:weavertheme:weaver_show_posts:*:*:*:*:*:wordpress:*:*" + ], + "si-contact-form": [ + "cpe:2.3:a:fast_secure_contact_form_project:fast_secure_contact_form:*:*:*:*:*:wordpress:*:*" + ], + "side-cart-woocommerce": [ + "cpe:2.3:a:xootix:side_cart_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "side-menu": [ + "cpe:2.3:a:wow-estore:side_menu:*:*:*:*:*:wordpress:*:*" + ], + "side-menu-lite": [ + "cpe:2.3:a:wow-company:side_menu_lite:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wow-estore:side_menu:*:*:*:*:lite:wordpress:*:*" + ], + "sidebar-adder": [ + "cpe:2.3:a:add_sidebar_project:add_sidebar:*:*:*:*:*:wordpress:*:*" + ], + "sidebar-manager": [ + "cpe:2.3:a:brainstormforce:lightweight_sidebar_manager:*:*:*:*:*:wordpress:*:*" + ], + "sideblog": [ + "cpe:2.3:a:sideblog_project:sideblog:*:*:*:*:*:wordpress:*:*" + ], + "sign-up-sheets": [ + "cpe:2.3:a:fetchdesigns:sign-up_sheets:*:*:*:*:*:wordpress:*:*" + ], + "similar-posts": [ + "cpe:2.3:a:shareaholic:similar_posts:*:*:*:*:*:wordpress:*:*" + ], + "simple-301-redirects-addon-bulk-uploader": [ + "cpe:2.3:a:webcraftic:simple_301_redirects-addon-bulk_uploader:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:webcraftic:simple_301_redirects:*:*:*:*:*:wordpress:*:*" + ], + "simple-add-pages-or-posts": [ + "cpe:2.3:a:mijnpress:simple_add_pages_or_posts:*:*:*:*:*:wordpress:*:*" + ], + "simple-ads-manager": [ + "cpe:2.3:a:simple_ads_manager_project:simple_ads_manager:*:*:*:*:*:wordpress:*:*" + ], + "simple-ajax-chat": [ + "cpe:2.3:a:plugin-planet:simple_ajax_chat:*:*:*:*:*:wordpress:*:*" + ], + "simple-author-box": [ + "cpe:2.3:a:webfactoryltd:simple_author_box:*:*:*:*:*:wordpress:*:*" + ], + "simple-banner": [ + "cpe:2.3:a:simple_banner_project:simple_banner:*:*:*:*:*:wordpress:*:*" + ], + "simple-basic-contact-form": [ + "cpe:2.3:a:megnicholas:clean_and_simple_contact_form:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpkube:simple_basic_contact_form:*:*:*:*:*:wordpress:*:*" + ], + "simple-behace-portfolio": [ + "cpe:2.3:a:simple-behace-portfolio_project:simple-behace-portfolio:*:*:*:*:*:wordpress:*:*" + ], + "simple-bitcoin-faucets": [ + "cpe:2.3:a:simple_bitcoin_faucets_project:simple_bitcoin_faucets:*:*:*:*:*:wordpress:*:*" + ], + "simple-cloudflare-turnstile": [ + "cpe:2.3:a:replywp:simple_cloudfare_turnstile:*:*:*:*:*:wordpress:*:*" + ], + "simple-cod-fee-for-woocommerce": [ + "cpe:2.3:a:83pixel:simple_cod_fees_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "simple-custom-author-profiles": [ + "cpe:2.3:a:usbmemorydirect:simple_custom_author_profiles:*:*:*:*:*:wordpress:*:*" + ], + "simple-custom-website-data": [ + "cpe:2.3:a:custom_website_data_project:custom_website_data:*:*:*:*:*:wordpress:*:*" + ], + "simple-download-button-shortcode": [ + "cpe:2.3:a:halulu:simple-download-button-shortcode:*:*:*:*:*:wordpress:*:*" + ], + "simple-download-counter": [ + "cpe:2.3:a:plugin-planet:simple_download_counter:*:*:*:*:*:wordpress:*:*" + ], + "simple-download-monitor": [ + "cpe:2.3:a:tipsandtricks-hq:simple_download_monitor:*:*:*:*:*:wordpress:*:*" + ], + "simple-e-commerce-shopping-cart": [ + "cpe:2.3:a:simple-e-commerce-shopping-cart_project:simple-e-commerce-shopping-cart:*:*:*:*:*:wordpress:*:*" + ], + "simple-event-planner": [ + "cpe:2.3:a:press_tigers:simple_event_planner:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:presstigers:simple_event_planner:*:*:*:*:*:wordpress:*:*" + ], + "simple-events-calendar": [ + "cpe:2.3:a:simple_events_calendar_project:simple_events_calendar:*:*:*:*:*:wordpress:*:*" + ], + "simple-facebook-plugin": [ + "cpe:2.3:a:illia:simple_like_page:*:*:*:*:*:*:*:*" + ], + "simple-fields": [ + "cpe:2.3:a:simple_fields_project:simple_fields:*:*:*:*:*:wordpress:*:*" + ], + "simple-file-list": [ + "cpe:2.3:a:simplefilelist:simple-file-list:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:simplefilelist:simple_file_list:*:*:*:*:*:wordpress:*:*" + ], + "simple-history": [ + "cpe:2.3:a:simple_history_project:simple_history:*:*:*:*:*:wordpress:*:*" + ], + "simple-icons": [ + "cpe:2.3:a:thememason:popular_brand_icons_-_simple_icons:*:*:*:*:*:wordpress:*:*" + ], + "simple-iframe": [ + "cpe:2.3:a:simple_iframe_project:simple_iframe:*:*:*:*:*:wordpress:*:*" + ], + "simple-image-manipulator": [ + "cpe:2.3:a:simple-image-manipulator_project:simple-image-manipulator:*:*:*:*:*:wordpress:*:*" + ], + "simple-ip-ban": [ + "cpe:2.3:a:ip_ban_project:ip_ban:*:*:*:*:*:wordpress:*:*" + ], + "simple-job-board": [ + "cpe:2.3:a:presstigers:simple_board_job:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:presstigers:simple_job_board:*:*:*:*:*:wordpress:*:*" + ], + "simple-jwt-login": [ + "cpe:2.3:a:simple_jwt_login_project:simple_jwt_login:*:*:*:*:*:wordpress:*:*" + ], + "simple-link-directory": [ + "cpe:2.3:a:quantumcloud:simple_link_directory:*:*:*:*:*:wordpress:*:*" + ], + "simple-login-log": [ + "cpe:2.3:a:simplerealtytheme:simple_login_log:*:*:*:*:*:wordpress:*:*" + ], + "simple-long-form": [ + "cpe:2.3:a:ohmybox:simple_long_form:*:*:*:*:*:wordpress:*:*" + ], + "simple-mail-address-encoder": [ + "cpe:2.3:a:simple_mail_address_encoder_project:simple_mail_address_encoder:*:*:*:*:*:wordpress:*:*" + ], + "simple-matted-thumbnails": [ + "cpe:2.3:a:devondev:simple_matted_thumbnails:*:*:*:*:*:wordpress:*:*" + ], + "simple-membership": [ + "cpe:2.3:a:simple-membership-plugin:simple_membership:*:*:*:*:*:wordpress:*:*" + ], + "simple-membership-wp-user-import": [ + "cpe:2.3:a:simple-membership-plugin:simple_membership_wp_user_import:*:*:*:*:*:wordpress:*:*" + ], + "simple-mobile-url-redirect": [ + "cpe:2.3:a:ozette:simple_mobile_url_redirect:*:*:*:*:*:wordpress:*:*" + ], + "simple-page-access-restriction": [ + "cpe:2.3:a:pluginsandsnippets:simple_page_access_restriction:*:*:*:*:*:wordpress:*:*" + ], + "simple-page-transition": [ + "cpe:2.3:a:simple_page_transition_project:simple_page_transition:*:*:*:*:*:wordpress:*:*" + ], + "simple-pdf-viewer": [ + "cpe:2.3:a:simple_pdf_viewer_project:simple_pdf_viewer:*:*:*:*:*:wordpress:*:*" + ], + "simple-photo-gallery": [ + "cpe:2.3:a:tipsandtricks-hq:simple_photo_gallery:*:*:*:*:*:wordpress:*:*" + ], + "simple-popup": [ + "cpe:2.3:a:simple_popup_project:simple_popup:*:*:-:*:-:wordpress:*:*" + ], + "simple-popup-newsletter": [ + "cpe:2.3:a:keszites:simple_popup_newsletter:*:*:*:*:*:wordpress:*:*" + ], + "simple-portfolio-gallery": [ + "cpe:2.3:a:simple_portfolio_gallery_project:simple_portfolio_gallery:*:*:*:*:*:wordpress:*:*" + ], + "simple-post": [ + "cpe:2.3:a:nickmomrik:simple_post:*:*:*:*:*:wordpress:*:*" + ], + "simple-posts-ticker": [ + "cpe:2.3:a:sayandatta:simple_posts_ticker:*:*:*:*:*:wordpress:*:*" + ], + "simple-quotation": [ + "cpe:2.3:a:sedlex:simple_quotation:*:*:*:*:*:wordpress:*:*" + ], + "simple-real-estate-pack-4": [ + "cpe:2.3:a:simple_real_estate_pack_project:simple_real_estate_pack:*:*:*:*:*:wordpress:*:*" + ], + "simple-share-buttons-adder": [ + "cpe:2.3:a:sharethis:simple_share_buttons_adder:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:simplesharebuttons:simple_share_buttons_adder:*:*:*:*:*:wordpress:*:*" + ], + "simple-site-verify": [ + "cpe:2.3:a:idoweb:simple_site_verify:*:*:*:*:*:wordpress:*:*" + ], + "simple-slug-translate": [ + "cpe:2.3:a:simple_slug_translate_project:simple_slug_translate:*:*:*:*:*:wordpress:*:*" + ], + "simple-social-buttons": [ + "cpe:2.3:a:wpbrigade:simple_social_buttons:*:*:*:*:*:wordpress:*:*" + ], + "simple-sortsearch": [ + "cpe:2.3:a:yukimichi:simple_sort\\\u0026search:*:*:*:*:*:wordpress:*:*" + ], + "simple-staff-list": [ + "cpe:2.3:a:simple_staff_list_project:simple_staff_list:*:*:*:*:*:wordpress:*:*" + ], + "simple-sticky-footer": [ + "cpe:2.3:a:simple_sticky_footer_project:simple_sticky_footer:*:*:*:*:*:wordpress:*:*" + ], + "simple-student-result": [ + "cpe:2.3:a:saadamin:simple_student_result:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:student_result_or_employee_database_project:student_result_or_employee_database:*:*:*:*:*:wordpress:*:*" + ], + "simple-support-ticket-system": [ + "cpe:2.3:a:support_ticket_system_project:support_ticket_system:*:*:*:*:*:wordpress:*:*" + ], + "simple-table-manager": [ + "cpe:2.3:a:topcode:simple_table_manager:*:*:*:*:*:wordpress:*:*" + ], + "simple-tags": [ + "cpe:2.3:a:taxopress:taxopress:*:*:*:*:*:wordpress:*:*" + ], + "simple-testimonials-showcase": [ + "cpe:2.3:a:presstigers:simple_testimonials_showcase:*:*:*:*:*:wordpress:*:*" + ], + "simple-theme-options": [ + "cpe:2.3:a:chrsinteractive:simple_tracking:*:*:*:*:*:wordpress:*:*" + ], + "simple-tweet": [ + "cpe:2.3:a:wokamoto:simple_tweet:*:*:*:*:*:wordpress:*:*" + ], + "simple-urls": [ + "cpe:2.3:a:getlasso:simple_urls:*:*:*:*:*:wordpress:*:*" + ], + "simple-video-embedder": [ + "cpe:2.3:a:simple_video_embedder_project:simple_video_embedder:*:*:*:*:*:wordpress:*:*" + ], + "simple-yearly-archive": [ + "cpe:2.3:a:simple_yearly_archive_project:simple_yearly_archive:*:*:*:*:*:wordpress:*:*" + ], + "simple-youtube-responsive": [ + "cpe:2.3:a:simple_youtube_responsive_project:simple_youtube_responsive:*:*:*:*:*:wordpress:*:*" + ], + "simplemodal-contact-form-smcf": [ + "cpe:2.3:a:simplemodal_contact_form_project:simplemodal_contact_form:*:*:*:*:*:wordpress:*:*" + ], + "simplepress": [ + "cpe:2.3:a:simple-press:simple\\:press:*:*:*:*:*:wordpress:*:*" + ], + "simplesamlphp-authentication": [ + "cpe:2.3:a:simplesamlphp_authentication_project:simplesamlphp_authentication:*:*:*:*:*:wordpress:*:*" + ], + "simplified-content": [ + "cpe:2.3:a:oxil:simplified-content:*:*:*:*:*:wordpress:*:*" + ], + "simply-excerpts": [ + "cpe:2.3:a:shooflysolutions:simply_excerpts:*:*:*:*:*:wordpress:*:*" + ], + "simply-exclude": [ + "cpe:2.3:a:codehooligans:simply_exclude:*:*:*:*:*:wordpress:*:*" + ], + "simply-gallery-block": [ + "cpe:2.3:a:simplygallery:simply_gallery_blocks_with_lightbox:*:*:*:*:*:wordpress:*:*" + ], + "simply-schedule-appointments": [ + "cpe:2.3:a:nsqua:simply_schedule_appointments:*:*:*:*:*:wordpress:*:*" + ], + "sina-extension-for-elementor": [ + "cpe:2.3:a:shaosina:sina_extension_for_elementor:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:sinaextra:sina_extension_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "single-post-exporter": [ + "cpe:2.3:a:single_post_exporter_project:single_post_exporter:*:*:*:*:*:wordpress:*:*" + ], + "single-sign-on-client": [ + "cpe:2.3:a:simple_sign_on_project:simple_sign_on:*:*:*:*:*:wordpress:*:*" + ], + "sirv": [ + "cpe:2.3:a:sirv:sirv:*:*:*:*:*:wordpress:*:*" + ], + "site-editor": [ + "cpe:2.3:a:siteeditor:site_editor:*:*:*:*:*:wordpress:*:*" + ], + "site-offline": [ + "cpe:2.3:a:freehtmldesigns:site_offline:*:*:*:*:*:wordpress:*:*" + ], + "site-reviews": [ + "cpe:2.3:a:geminilabs:site_reviews:*:*:*:*:*:wordpress:*:*" + ], + "sitebuilder-dynamic-components": [ + "cpe:2.3:a:sitebuilder_dynamic_components_project:sitebuilder_dynamic_components:*:*:*:*:*:wordpress:*:*" + ], + "sitekit": [ + "cpe:2.3:a:sitekit_project:sitekit:*:*:*:*:*:wordpress:*:*" + ], + "sitemap": [ + "cpe:2.3:a:sitemap_project:sitemap:*:*:*:*:*:wordpress:*:*" + ], + "sitemap-by-click5": [ + "cpe:2.3:a:click5interactive:sitemap_by_click5:*:*:*:*:*:wordpress:*:*" + ], + "sitemap-index": [ + "cpe:2.3:a:sitemap_index_project:sitemap_index:*:*:*:*:*:wordpress:*:*" + ], + "siteorigin-panels": [ + "cpe:2.3:a:siteorigin:page_builder:*:*:*:*:*:wordpress:*:*" + ], + "sitepress-multilingual-cms": [ + "cpe:2.3:a:onthegosystems:sitepress-multilingual-cms:*:*:*:*:*:wordpress:*:*" + ], + "sitesupercharger": [ + "cpe:2.3:a:marketingheroes:sitesupercharger:*:*:*:*:*:wordpress:*:*" + ], + "sitewide-notice-wp": [ + "cpe:2.3:a:yoohooplugins:sitewide_notice_wp:*:*:*:*:*:wordpress:*:*" + ], + "skaut-bazar": [ + "cpe:2.3:a:skaut-bazar_project:skaut-bazar:*:*:*:*:*:wordpress:*:*" + ], + "sliced-invoices": [ + "cpe:2.3:a:slicedinvoices:sliced_invoices:*:*:*:*:*:wordpress:*:*" + ], + "slick-contact-forms": [ + "cpe:2.3:a:leechesnutt:slick_contact_forms:*:*:*:*:*:wordpress:*:*" + ], + "slick-popup": [ + "cpe:2.3:a:omaksolutions:slick-popup:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:omaksolutions:slick_popup:*:*:*:*:*:wordpress:*:*" + ], + "slick-social-share-buttons": [ + "cpe:2.3:a:leechesnutt:slick_social_share_buttons:*:*:*:*:*:wordpress:*:*" + ], + "slickquiz": [ + "cpe:2.3:a:slickquiz_project:slickquiz:*:*:*:*:*:wordpress:*:*" + ], + "slickr-flickr": [ + "cpe:2.3:a:diywebmastery:slickr_flickr:*:*:*:*:*:wordpress:*:*" + ], + "slide-anything": [ + "cpe:2.3:a:simonpedge:slide_anything:*:*:*:*:*:wordpress:*:*" + ], + "slidedeck2": [ + "cpe:2.3:a:hbwsl:slidedeck_2:*:*:*:*:lite:wordpress:*:*" + ], + "slider-hero": [ + "cpe:2.3:a:quantumcloud:slider_hero:*:*:*:*:*:wordpress:*:*" + ], + "slider-range-htapps": [ + "cpe:2.3:a:ht_slider_range_for_amazon_affiliates_project:ht_slider_range_for_amazon_affiliates:*:*:*:*:*:wordpress:*:*" + ], + "slider-responsive-slideshow": [ + "cpe:2.3:a:awplife:slider_responsive_slideshow:*:*:*:*:*:wordpress:*:*" + ], + "slider-slideshow": [ + "cpe:2.3:a:web-settler:layer_slider:*:*:*:*:*:wordpress:*:*" + ], + "slider-wd": [ + "cpe:2.3:a:10web:slider:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:10web:sliderby10web:*:*:*:*:*:wordpress:*:*" + ], + "slideshow-ck": [ + "cpe:2.3:a:ceikay:slideshow_ck:*:*:*:*:*:wordpress:*:*" + ], + "slideshow-gallery": [ + "cpe:2.3:a:tribulant:slideshow_gallery:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:tribulant:tibulant_slideshow_gallery:*:*:*:*:*:wordpress:*:*" + ], + "slideshow-jquery-image-gallery": [ + "cpe:2.3:a:slideshow_project:slideshow:*:*:*:*:*:wordpress:*:*" + ], + "slideshow-se": [ + "cpe:2.3:a:slideshow_se_project:slideshow_se:*:*:*:*:*:wordpress:*:*" + ], + "smart-app-banner": [ + "cpe:2.3:a:wandlesoftware:smart_app_banner:*:*:*:*:*:wordpress:*:*" + ], + "smart-cookie-kit": [ + "cpe:2.3:a:nicolamodugno:smart_cookie_kit:*:*:*:*:*:wordpress:*:*" + ], + "smart-donations": [ + "cpe:2.3:a:rednao:donations_made_easy_-_smart_donations:*:*:*:*:*:wordpress:*:*" + ], + "smart-email-alerts": [ + "cpe:2.3:a:followistic:smart_email_alerts:*:*:*:*:*:wordpress:*:*" + ], + "smart-forms": [ + "cpe:2.3:a:rednao:smart_forms:*:*:*:*:*:wordpress:*:*" + ], + "smart-google-code-inserter": [ + "cpe:2.3:a:oturia:smart_google_code_inserter:*:*:*:*:*:wordpress:*:*" + ], + "smart-grid-gallery": [ + "cpe:2.3:a:origincode:smart-grid-gallery:*:*:*:*:*:wordpress:*:*" + ], + "smart-id": [ + "cpe:2.3:a:eideasy:eid_easy:*:*:*:*:*:wordpress:*:*" + ], + "smart-logo-showcase-lite": [ + "cpe:2.3:a:accesspressthemes:smart_logo_showcase_lite:*:*:*:*:*:wordpress:*:*" + ], + "smart-marketing-for-wp": [ + "cpe:2.3:a:e-goi:smart_marketing_sms_and_newsletters_forms:*:*:*:*:*:*:*:*" + ], + "smart-seo-tool": [ + "cpe:2.3:a:wbolt:smart_seo_tool:*:*:*:*:*:wordpress:*:*" + ], + "smart-slider-3": [ + "cpe:2.3:a:nextendweb:smart_slider_3:*:*:*:*:*:wordpress:*:*" + ], + "smart-youtube": [ + "cpe:2.3:a:smart_youtube_pro_project:smart_youtube_pro:*:*:*:*:*:wordpress:*:*" + ], + "smartcrawl-seo": [ + "cpe:2.3:a:wpmudev:smartcrawl:*:*:*:*:*:wordpress:*:*" + ], + "smartsoftbutton-widget-de-botones-de-chat": [ + "cpe:2.3:a:smartsoft:button_widget_smartsoft:*:*:*:*:*:wordpress:*:*" + ], + "smarty-for-wordpress": [ + "cpe:2.3:a:presspage:smarty_for_wordpress:*:*:*:*:*:wordpress:*:*" + ], + "smokesignal": [ + "cpe:2.3:a:smokesignal_project:smokesignal:*:*:*:*:*:wordpress:*:*" + ], + "smooth-page-scroll-updown-buttons": [ + "cpe:2.3:a:smooth_scroll_page_up\\/down_buttons_project:smooth_scroll_page_up\\/down_buttons:*:*:*:*:*:wordpress:*:*" + ], + "smooth-scrolling-links-ssl": [ + "cpe:2.3:a:chetangole:smooth_scroll_links:*:*:*:*:*:wordpress:*:*" + ], + "smooth-slider": [ + "cpe:2.3:a:slidervilla:smooth_slider:*:*:*:*:*:wordpress:*:*" + ], + "smpl-shortcodes": [ + "cpe:2.3:a:simple_shortcodes_project:simple_shortcodes:*:*:*:*:*:wordpress:*:*" + ], + "sms-alert": [ + "cpe:2.3:a:cozyvision:sms_alert_order_notifications:*:*:*:*:*:wordpress:*:*" + ], + "sms-ovh": [ + "cpe:2.3:a:elyazalee:sms-ovh:*:*:*:*:*:wordpress:*:*" + ], + "smtp-mail": [ + "cpe:2.3:a:photoboxone:smtp_mail:*:*:*:*:*:wordpress:*:*" + ], + "smtp-mailing-queue": [ + "cpe:2.3:a:smtp_mailing_queue_project:smtp_mailing_queue:*:*:*:*:*:wordpress:*:*" + ], + "smtp2go": [ + "cpe:2.3:a:smtp2go:smtp2go:*:*:*:*:*:wordpress:*:*" + ], + "snap-pixel": [ + "cpe:2.3:a:hassanali:snap_pixel:*:*:*:*:*:wordpress:*:*" + ], + "snazzy-maps": [ + "cpe:2.3:a:atmist:snazzy_maps:*:*:*:*:*:wordpress:*:*" + ], + "so-pinyin-slugs": [ + "cpe:2.3:a:so-wp:pinyin_slugs:*:*:*:*:*:wordpress:*:*" + ], + "so-widgets-bundle": [ + "cpe:2.3:a:siteorigin:siteorigin_widgets_bundle:*:*:*:*:*:wordpress:*:*" + ], + "sociable": [ + "cpe:2.3:a:sociable_project:sociable:*:*:*:*:*:wordpress:*:*" + ], + "social-buttons-pack": [ + "cpe:2.3:a:bestwebsoft:social_buttons_pack:*:*:*:*:*:wordpress:*:*" + ], + "social-locker": [ + "cpe:2.3:a:byonepress:social_locker:*:*:*:*:*:wordpress:*:*" + ], + "social-login-bws": [ + "cpe:2.3:a:bestwebsoft:social_login:*:*:*:*:*:wordpress:*:*" + ], + "social-media-feather": [ + "cpe:2.3:a:sharethis:social_media_feather:*:*:*:*:*:wordpress:*:*" + ], + "social-networks-auto-poster-facebook-twitter-g": [ + "cpe:2.3:a:nextscripts:social_networks_auto_poster:*:*:*:*:*:wordpress:*:*" + ], + "social-photo-gallery": [ + "cpe:2.3:a:infoway:social_photo_gallery:*:*:*:*:*:wordpress:*:*" + ], + "social-proof-testimonials-slider": [ + "cpe:2.3:a:brandid:social_proof_\\(testimonial\\)_slider:*:*:*:*:*:wordpress:*:*" + ], + "social-pug": [ + "cpe:2.3:a:devpups:social_pug:*:*:*:*:*:wordpress:*:*" + ], + "social-rocket": [ + "cpe:2.3:a:wpsocialrocket:social_rocket:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpsocialrocket:social_sharing:*:*:*:*:*:wordpress:*:*" + ], + "social-share-boost": [ + "cpe:2.3:a:sumo:social_share_boost:*:*:*:*:*:wordpress:*:*" + ], + "social-share-buttons-by-supsystic": [ + "cpe:2.3:a:supsystic:social_share_buttons:*:*:*:*:*:wordpress:*:*" + ], + "social-slider": [ + "cpe:2.3:a:social_slider_project:social_slider:*:*:*:*:*:wordpress:*:*" + ], + "social-warfare": [ + "cpe:2.3:a:warfareplugins:social_warfare:*:*:*:*:*:wordpress:*:*" + ], + "sodahead-polls": [ + "cpe:2.3:a:sodahead:sodahead_polls:*:*:*:*:*:wordpress:*:*" + ], + "software-license-manager": [ + "cpe:2.3:a:tipsandtricks-hq:software_license_manager:*:*:*:*:*:wordpress:*:*" + ], + "soisy-pagamento-rateale": [ + "cpe:2.3:a:soisy:soisy_pagamento_rateale:*:*:*:*:*:wordpress:*:*" + ], + "sola-newsletters": [ + "cpe:2.3:a:sola-newsletters_project:sola-newsletters:*:*:*:*:*:wordpress:*:*" + ], + "sola-support-tickets": [ + "cpe:2.3:a:solaplugins:sola_support_tickets:*:*:*:*:*:wordpress:*:*" + ], + "solidres": [ + "cpe:2.3:a:solidres:solidres:*:*:*:*:*:wordpress:*:*" + ], + "soundcloud-is-gold": [ + "cpe:2.3:a:mightymess:soundcloud_is_gold:*:*:*:*:*:wordpress:*:*" + ], + "soundcloud-shortcode": [ + "cpe:2.3:a:soundcloud:soundcloud_shortcode:*:*:*:*:*:wordpress:*:*" + ], + "soundy-audio-playlist": [ + "cpe:2.3:a:webartisan:soundy_audio_playlist:*:*:*:*:*:wordpress:*:*" + ], + "soundy-background-music": [ + "cpe:2.3:a:webartisan:soundy_background_music:*:*:*:*:*:wordpress:*:*" + ], + "sp-client-document-manager": [ + "cpe:2.3:a:smartypantsplugins:sp_project_\\\u0026_document_manager:*:*:*:*:*:wordpress:*:*" + ], + "sp-rental-manager": [ + "cpe:2.3:a:smartypantsplugins:sp_rental_manager:*:*:*:*:*:wordpress:*:*" + ], + "spacer": [ + "cpe:2.3:a:clevelandwebdeveloper:spacer:*:*:*:*:*:wordpress:*:*" + ], + "spam-byebye": [ + "cpe:2.3:a:ohtanz:spam-byebye:*:*:*:*:*:wordpress:*:*" + ], + "spamreferrerblock": [ + "cpe:2.3:a:spamreferrerblock_project:spamreferrerblock:*:*:*:*:*:wordpress:*:*" + ], + "speed-booster-pack": [ + "cpe:2.3:a:optimocha:speed_booster_pack:*:*:*:*:*:wordpress:*:*" + ], + "speedycache": [ + "cpe:2.3:a:softaculous:speedycache:*:*:*:*:*:wordpress:*:*" + ], + "spice-post-slider": [ + "cpe:2.3:a:spicethemes:carousel\\,_recent_post_slider_and_banner_slider:*:*:*:*:*:wordpress:*:*" + ], + "spider-event-calendar": [ + "cpe:2.3:a:web-dorado:spider_calendar:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:web-dorado:spider_event_calendar:*:*:*:*:*:*:*:*" + ], + "spider-facebook": [ + "cpe:2.3:a:web-dorado:spider_facebook:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:web-dorado:wdsocialwidgets:*:*:*:*:*:wordpress:*:*" + ], + "spideranalyse": [ + "cpe:2.3:a:spideranalyse_project:spideranalyse:*:*:*:*:*:wordpress:*:*" + ], + "spiffy-calendar": [ + "cpe:2.3:a:spiffyplugins:spiffy_calendar:*:*:*:*:*:wordpress:*:*" + ], + "splash-header": [ + "cpe:2.3:a:zeesweb:splash_header:*:*:*:*:*:wordpress:*:*" + ], + "sponsors-carousel": [ + "cpe:2.3:a:sponsors_carousel_project:sponsors_carousel:*:*:*:*:*:wordpress:*:*" + ], + "sportspress": [ + "cpe:2.3:a:themeboy:sportspress:*:*:*:*:*:wordpress:*:*" + ], + "spotify-play-button-for-wordpress": [ + "cpe:2.3:a:followmedarling:spotify-play-button-for-wordpress:*:*:*:*:*:wordpress:*:*" + ], + "spotim-comments": [ + "cpe:2.3:a:spot:spot.im_comments:*:*:*:*:*:wordpress:*:*" + ], + "spotlight-social-photo-feeds": [ + "cpe:2.3:a:rebelcode:spotlight_social_feeds:*:*:*:*:*:wordpress:*:*" + ], + "spreadshirt-rss-3d-cube-flash-gallery": [ + "cpe:2.3:a:spreadshirt-rss-3d-cube-flash-gallery_project:spreadshirt-rss-3d-cube-flash-gallery:*:*:*:*:*:wordpress:*:*" + ], + "spreadshop": [ + "cpe:2.3:a:spreadshop:spreadshop:*:*:*:*:*:wordpress:*:*" + ], + "sprout-invoices": [ + "cpe:2.3:a:webventures:client_invoicing_by_sprout_invoices:*:*:*:*:*:wordpress:*:*" + ], + "squirrly-seo": [ + "cpe:2.3:a:squirrly:seo_plugin_by_squirrly_seo:*:*:*:*:*:wordpress:*:*" + ], + "srbtranslatin": [ + "cpe:2.3:a:srbtranslatin_project:srbtranslatin:*:*:*:*:*:wordpress:*:*" + ], + "st-daily-tip": [ + "cpe:2.3:a:sanskruti:st-daily-tip:*:*:*:*:*:wordpress:*:*" + ], + "staff-directory-pro": [ + "cpe:2.3:a:goldplugins:staff_directory_plugin:*:*:*:*:*:wordpress:*:*" + ], + "stafflist": [ + "cpe:2.3:a:era404:stafflist:*:*:*:*:*:wordpress:*:*" + ], + "stageshow": [ + "cpe:2.3:a:stageshow_project:stageshow:*:*:*:*:*:wordpress:*:*" + ], + "stagtools": [ + "cpe:2.3:a:codestag:stagtools:*:*:*:*:*:wordpress:*:*" + ], + "star-cloudprnt-for-woocommerce": [ + "cpe:2.3:a:star-emea:star-cloudprnt-for-woocommerce:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:star-emea:star_cloudprnt_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "starbox": [ + "cpe:2.3:a:squirrly:starbox:*:*:*:*:*:wordpress:*:*" + ], + "stars-rating": [ + "cpe:2.3:a:stars_rating_project:stars_rating:*:*:*:*:*:wordpress:*:*" + ], + "stats-counter": [ + "cpe:2.3:a:analytics_stats_counter_statistics_project:analytics_stats_counter_statistics:*:*:*:*:*:wordpress:*:*" + ], + "stax-addons-for-elementor": [ + "cpe:2.3:a:staxwp:stax:*:*:*:*:*:wordpress:*:*" + ], + "stetic": [ + "cpe:2.3:a:stetic:stetic:*:*:*:*:*:wordpress:*:*" + ], + "sticky-buttons": [ + "cpe:2.3:a:wow-company:sticky_buttons:*:*:*:*:*:wordpress:*:*" + ], + "sticky-chat-widget": [ + "cpe:2.3:a:gingerplugins:sticky_chat_widget:*:*:*:*:*:wordpress:*:*" + ], + "sticky-header-oceanwp": [ + "cpe:2.3:a:oceanwp:sticky_header:*:*:*:*:*:wordpress:*:*" + ], + "sticky-popup": [ + "cpe:2.3:a:sticky_popup_project:sticky_popup:*:*:*:*:*:wordpress:*:*" + ], + "stock-in": [ + "cpe:2.3:a:stock_in_\\\u0026_out_project:stock_in_\\\u0026_out:*:*:*:*:*:wordpress:*:*" + ], + "stock-locations-for-woocommerce": [ + "cpe:2.3:a:fahadmahmood8:stock_locations_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "stock-market-charts-from-finviz": [ + "cpe:2.3:a:finviz:stock_market_charts_from_finviz:*:*:*:*:*:wordpress:*:*" + ], + "stock-sync-for-woocommerce": [ + "cpe:2.3:a:wptrio:stock_sync_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "stock-ticker": [ + "cpe:2.3:a:urosevic:stock_ticker:*:*:*:*:*:wordpress:*:*" + ], + "stockdio-historical-chart": [ + "cpe:2.3:a:stockdio:stockdio_historical_chart:*:*:*:*:*:wordpress:*:*" + ], + "stockists-manager": [ + "cpe:2.3:a:berocket:stockists_manager_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "stop-referrer-spam": [ + "cpe:2.3:a:wielogorski:stop_referrer_spam:*:*:*:*:*:wordpress:*:*" + ], + "stop-spam-comments": [ + "cpe:2.3:a:stop_spam_comments_project:stop_spam_comments:*:*:*:*:*:wordpress:*:*" + ], + "stop-spammer-registrations-plugin": [ + "cpe:2.3:a:trumani:stop_spammers:*:*:*:*:*:wordpress:*:*" + ], + "stop-user-enumeration": [ + "cpe:2.3:a:fullworks:stop_user_enumeration:*:*:*:*:*:wordpress:*:*" + ], + "stopbadbots": [ + "cpe:2.3:a:stopbadbots:block_and_stop_bad_bots:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:stopbadbots_project:stopbadbots:*:*:*:*:*:wordpress:*:*" + ], + "stops-core-theme-and-plugin-updates": [ + "cpe:2.3:a:easyupdatesmanager:easy_updates_manager:*:*:*:*:*:wordpress:*:*" + ], + "store-locator": [ + "cpe:2.3:a:store_locator_project:store_locator:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:viadat:store_locator_for_wordpress_with_google_maps:*:*:*:*:*:wordpress:*:*" + ], + "storefront-footer-text": [ + "cpe:2.3:a:wooassist:storefront_footer_text:*:*:*:*:*:wordpress:*:*" + ], + "strategery-migrations": [ + "cpe:2.3:a:strategery_migrations_project:strategery_migrations:*:*:*:*:*:wordpress:*:*" + ], + "stream": [ + "cpe:2.3:a:xwp:stream:*:*:*:*:*:wordpress:*:*" + ], + "streamcast": [ + "cpe:2.3:a:bplugins:streamcast_radio_player:*:*:*:*:*:wordpress:*:*" + ], + "string-locator": [ + "cpe:2.3:a:instawp:string_locator:*:*:*:*:*:wordpress:*:*" + ], + "strong-testimonials": [ + "cpe:2.3:a:machothemes:strong_testimonials:*:*:*:*:*:wordpress:*:*" + ], + "structured-content": [ + "cpe:2.3:a:wpsc-plugin:structured_content:*:*:*:*:*:wordpress:*:*" + ], + "stylish-cost-calculator": [ + "cpe:2.3:a:stylishcostcalculator:stylish_cost_calculator:*:*:*:*:*:wordpress:*:*" + ], + "stylish-price-list": [ + "cpe:2.3:a:stylishpricelist:stylish_price_list:*:*:*:*:*:wordpress:*:*" + ], + "stylist": [ + "cpe:2.3:a:stylist_project:stylist:*:*:*:*:*:wordpress:*:*" + ], + "subscribe-sidebar": [ + "cpe:2.3:a:blubrry:subscribe_sidebar:*:*:*:*:*:wordpress:*:*" + ], + "subscribe-to-category": [ + "cpe:2.3:a:subscribe_to_category_project:subscribe_to_category:*:*:*:*:*:wordpress:*:*" + ], + "subscribe-to-comments": [ + "cpe:2.3:a:subscribe_to_comments_project:subscribe_to_comments:*:*:*:*:*:wordpress:*:*" + ], + "subscribe-to-comments-reloaded": [ + "cpe:2.3:a:wpkube:subscribe_to_comments_reloaded:*:*:*:*:*:wordpress:*:*" + ], + "subscribe2": [ + "cpe:2.3:a:subscribe2_project:subscribe2:*:*:*:*:*:wordpress:*:*" + ], + "subscriber": [ + "cpe:2.3:a:bestwebsoft:contact_form:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:bestwebsoft:subscriber:*:*:*:*:*:wordpress:*:*" + ], + "subscribers-com": [ + "cpe:2.3:a:hellobar:subscribers:*:*:*:*:*:wordpress:*:*" + ], + "sucuri-scanner": [ + "cpe:2.3:a:sucuri:security:*:*:*:*:*:wordpress:*:*" + ], + "sunshine-photo-cart": [ + "cpe:2.3:a:sunshinephotocart:sunshine_photo_cart:*:*:*:*:*:wordpress:*:*" + ], + "super-socializer": [ + "cpe:2.3:a:heateor:super_socializer:*:*:*:*:*:wordpress:*:*" + ], + "super-testimonial": [ + "cpe:2.3:a:themepoints:super_testimonials:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:themepoints:testimonials:*:*:*:*:*:wordpress:*:*" + ], + "superb-slideshow-gallery": [ + "cpe:2.3:a:gopiplus:superb_slideshow_gallery:*:*:*:*:*:wordpress:*:*" + ], + "superb-social-share-and-follow-buttons": [ + "cpe:2.3:a:superbthemes:superb_social_media_share_buttons_and_follow_buttons_for_wordpress:*:*:*:*:*:wordpress:*:*" + ], + "supportcandy": [ + "cpe:2.3:a:supportcandy:supportcandy:*:*:*:*:*:wordpress:*:*" + ], + "supportflow": [ + "cpe:2.3:a:supportflow_project:supportflow:*:*:*:*:*:wordpress:*:*" + ], + "supra-csv-parser": [ + "cpe:2.3:a:supra-csv-parser_project:supra-csv-parser:*:*:*:*:*:wordpress:*:*" + ], + "surbma-gdpr-proof-google-analytics": [ + "cpe:2.3:a:surbma:gdpr_proof_cookie_consent_\\\u0026_notice_bar:*:*:*:*:*:wordpress:*:*" + ], + "suretriggers": [ + "cpe:2.3:a:suretriggers:suretriggers:*:*:*:*:*:wordpress:*:*" + ], + "survey-maker": [ + "cpe:2.3:a:ays-pro:survey_maker:*:*:*:*:*:wordpress:*:*" + ], + "surveys": [ + "cpe:2.3:a:surveys_project:surveys:*:*:*:*:*:wordpress:*:*" + ], + "svg-support": [ + "cpe:2.3:a:benbodhi:svg_support:*:*:*:*:*:wordpress:*:*" + ], + "svg-vector-icon-plugin": [ + "cpe:2.3:a:wp_svg_icons_project:wp_svg_icons:*:*:*:*:*:wordpress:*:*" + ], + "swatchly": [ + "cpe:2.3:a:hasthemes:swatchly:*:*:*:*:*:wordpress:*:*" + ], + "swifty-bar": [ + "cpe:2.3:a:wpgens:swifty_bar:*:*:*:*:*:wordpress:*:*" + ], + "swifty-page-manager": [ + "cpe:2.3:a:swifty_page_manager_project:swifty_page_manager:*:*:*:*:*:wordpress:*:*" + ], + "swipehq-payment-gateway-woocommerce": [ + "cpe:2.3:a:cybercompany:swipehq-payment-gateway-woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "swipehq-payment-gateway-wp-e-commerce": [ + "cpe:2.3:a:cybercompay:swipehq-payment-gateway-wp-e-commerce:*:*:*:*:*:wordpress:*:*" + ], + "symbiostock": [ + "cpe:2.3:a:symbiostock:symbiostock:*:*:*:*:*:wordpress:*:*" + ], + "sync-qcloud-cos": [ + "cpe:2.3:a:sync_qcloud_cos_project:sync_qcloud_cos:*:*:*:*:*:wordpress:*:*" + ], + "syncee-global-dropshipping": [ + "cpe:2.3:a:syncee:syncee_-_global_dropshipping:*:*:*:*:*:wordpress:*:*" + ], + "syndication-links": [ + "cpe:2.3:a:syndication_links_project:syndication_links:*:*:*:*:*:wordpress:*:*" + ], + "synved-shortcodes": [ + "cpe:2.3:a:synved:wordpress_shortcodes:*:*:*:*:*:wordpress:*:*" + ], + "system-dashboard": [ + "cpe:2.3:a:bowo:system_dashboard:*:*:*:*:*:wordpress:*:*" + ], + "tabbed": [ + "cpe:2.3:a:rich-web:tab:*:*:*:*:*:wordpress:*:*" + ], + "table-of-contents-plus": [ + "cpe:2.3:a:dublue:table_of_contents_plus:*:*:*:*:*:wordpress:*:*" + ], + "tablepress": [ + "cpe:2.3:a:tablepress:tablepress:*:*:*:*:*:wordpress:*:*" + ], + "tabs-pro": [ + "cpe:2.3:a:themepoints:tab_ultimate:*:*:*:*:*:wordpress:*:*" + ], + "tabs-responsive": [ + "cpe:2.3:a:wpshopmart:tabs_responsive:*:*:*:*:*:wordpress:*:*" + ], + "tagregator": [ + "cpe:2.3:a:tagregator_project:tagregator:*:*:*:*:*:wordpress:*:*" + ], + "tags-cloud-manager": [ + "cpe:2.3:a:tags_cloud_manager_project:tags_cloud_manager:*:*:*:*:*:wordpress:*:*" + ], + "tarteaucitronjs": [ + "cpe:2.3:a:tarteaucitron.js_-_cookies_legislation_\\\u0026_gdpr_project:tarteaucitron.js_-_cookies_legislation_\\\u0026_gdpr:*:*:*:*:*:wordpress:*:*" + ], + "taskbuilder": [ + "cpe:2.3:a:taskbuilder:taskbuilder:*:*:*:*:*:wordpress:*:*" + ], + "tawkto-live-chat": [ + "cpe:2.3:a:tawk:tawk.to_live_chat:*:*:*:*:*:wordpress:*:*" + ], + "taxonomy-filter": [ + "cpe:2.3:a:andrealandonio:taxonomy_filter:*:*:*:*:*:wordpress:*:*" + ], + "tc-custom-javascript": [ + "cpe:2.3:a:tc_custom_javascript_project:tc_custom_javascript:*:*:*:*:*:wordpress:*:*" + ], + "tcd-google-maps": [ + "cpe:2.3:a:tcd-theme:tcd_google_maps:*:*:*:*:*:wordpress:*:*" + ], + "teachpress": [ + "cpe:2.3:a:mtrv:teachpress:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:teachpress_project:teachpress:*:*:*:*:*:wordpress:*:*" + ], + "team": [ + "cpe:2.3:a:pickplugins:team_showcase:*:*:*:*:*:wordpress:*:*" + ], + "team-members": [ + "cpe:2.3:a:wpdarko:team_members:*:*:*:*:*:wordpress:*:*" + ], + "team-showcase": [ + "cpe:2.3:a:themepoints:team_showcase:*:*:*:*:*:wordpress:*:*" + ], + "teamleader-form-integration": [ + "cpe:2.3:a:teamleade:teamleader_crm_forms:*:*:*:*:*:wordpress:*:*" + ], + "telephone-number-linker": [ + "cpe:2.3:a:gravitydesign:telephone_number_linker:*:*:*:*:*:wordpress:*:*" + ], + "template-events-calendar": [ + "cpe:2.3:a:coolplugins:events_shortcodes_for_the_events_calendar:*:*:*:*:*:wordpress:*:*" + ], + "templately": [ + "cpe:2.3:a:templately:templately:*:*:*:*:*:wordpress:*:*" + ], + "templates-patterns-collection": [ + "cpe:2.3:a:themeisle:cloud_templates_\\\u0026_patterns_collection:*:*:*:*:*:wordpress:*:*" + ], + "templatesnext-toolkit": [ + "cpe:2.3:a:templatesnext:templatesnext_toolkit:*:*:*:*:*:wordpress:*:*" + ], + "temporary-login-without-password": [ + "cpe:2.3:a:storeapps:temporary_login_without_password:*:*:*:*:*:wordpress:*:*" + ], + "tenweb-speed-optimizer": [ + "cpe:2.3:a:10web:10web_booster:*:*:*:*:*:wordpress:*:*" + ], + "terms-descriptions": [ + "cpe:2.3:a:simplecoding:terms_descriptions:*:*:*:*:*:wordpress:*:*" + ], + "testimonial-add": [ + "cpe:2.3:a:web-settler:testimonial_slider:*:*:*:*:*:wordpress:*:*" + ], + "testimonial-builder": [ + "cpe:2.3:a:wpshopmart:testimonial_builder:*:*:*:*:*:wordpress:*:*" + ], + "testimonial-free": [ + "cpe:2.3:a:shapedplugin:real_testimonials:*:*:*:*:*:wordpress:*:*" + ], + "testimonial-rotator": [ + "cpe:2.3:a:testimonial_rotator_project:testimonial_rotator:*:*:*:*:*:wordpress:*:*" + ], + "testimonial-slider": [ + "cpe:2.3:a:slidervilla:testimonial_slider:*:*:*:*:*:wordpress:*:*" + ], + "testimonial-slider-shortcode": [ + "cpe:2.3:a:sazzadh:testimonial_slider_shortcode:*:*:*:*:*:wordpress:*:*" + ], + "testimonial-widgets": [ + "cpe:2.3:a:fetchdesigns:sign-up_sheets:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:trustindex:wp_testimonials:*:*:*:*:*:wordpress:*:*" + ], + "testimonials": [ + "cpe:2.3:a:testimonials_project:testimonials:*:*:*:*:*:wordpress:*:*" + ], + "testimonials-widget": [ + "cpe:2.3:a:axelerant:testimonials_widget:*:*:*:*:*:wordpress:*:*" + ], + "text-hover": [ + "cpe:2.3:a:text_hover_project:text_hover:*:*:*:*:*:wordpress:*:*" + ], + "tf-numbers-number-counter-animaton": [ + "cpe:2.3:a:metagauss:themeflection_numbers:*:*:*:*:*:wordpress:*:*" + ], + "thank-me-later": [ + "cpe:2.3:a:thank_me_later_project:thank_me_later:*:*:*:*:*:wordpress:*:*" + ], + "the-events-calendar": [ + "cpe:2.3:a:tri:the_events_calendar:*:*:*:*:*:wordpress:*:*" + ], + "the-hackers-diet": [ + "cpe:2.3:a:wp-plugins:the_hackers_diet:*:*:*:*:*:wordpress:*:*" + ], + "the-holiday-calendar": [ + "cpe:2.3:a:theholidaycalendar:the_holiday_calendar:*:*:*:*:*:wordpress:*:*" + ], + "the-plus-addons-for-elementor-page-builder": [ + "cpe:2.3:a:posimyth:the_plus_addons_for_elementor:*:*:*:*:free:wordpress:*:*", + "cpe:2.3:a:posimyth:the_plus_addons_for_elementor_page_builder_lite:*:*:*:*:*:wordpress:*:*" + ], + "the-post-grid": [ + "cpe:2.3:a:radiustheme:post_grid:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:radiustheme:the_post_grid:*:*:*:*:*:wordpress:*:*" + ], + "the-sorter": [ + "cpe:2.3:a:ombu:the_sorter:*:*:*:*:*:wordpress:*:*" + ], + "the-very-simple-vimeo-shortcode": [ + "cpe:2.3:a:simple_vimeo_shortcode_project:simple_vimeo_shortcode:*:*:*:*:*:wordpress:*:*" + ], + "theatre": [ + "cpe:2.3:a:slimndap:theater_for_wordpress:*:*:*:*:*:wordpress:*:*" + ], + "thecartpress": [ + "cpe:2.3:a:thecartpress:thecartpress_ecommerce_shopping_cart:*:*:*:*:*:wordpress:*:*" + ], + "theme-blvd-responsive-google-maps": [ + "cpe:2.3:a:theme_blvd_responsive_google_maps_project:theme_blvd_responsive_google_maps:*:*:*:*:*:wordpress:*:*" + ], + "theme-blvd-shortcodes": [ + "cpe:2.3:a:themeblvd:theme_blvd_shortcodes:*:*:*:*:*:wordpress:*:*" + ], + "theme-demo-import": [ + "cpe:2.3:a:themely:theme_demo_import:*:*:*:*:*:wordpress:*:*" + ], + "theme-editor": [ + "cpe:2.3:a:themeeditor:theme_editor:*:*:*:*:*:wordpress:*:*" + ], + "theme-junkie-shortcodes": [ + "cpe:2.3:a:themejunkie:tj_shortcodes:*:*:*:*:*:wordpress:*:*" + ], + "theme-per-user": [ + "cpe:2.3:a:presslabs:theme_per_user:*:*:*:*:*:wordpress:*:*" + ], + "theme-switcha": [ + "cpe:2.3:a:plugin-planet:theme_switcha:*:*:*:*:*:wordpress:*:*" + ], + "theme-translation-for-polylang": [ + "cpe:2.3:a:theme_and_plugin_translation_for_polylang_project:theme_and_plugin_translation_for_polylang:*:*:*:*:*:wordpress:*:*" + ], + "themegrill-demo-importer": [ + "cpe:2.3:a:themegrill:themegrill_demo_importer:*:*:*:*:*:wordpress:*:*" + ], + "themehigh-multiple-addresses": [ + "cpe:2.3:a:themehigh:multiple_shipping_addresses:*:*:*:*:*:*:*:*" + ], + "themeisle-companion": [ + "cpe:2.3:a:themeisle:orbit_fox:*:*:*:*:*:wordpress:*:*" + ], + "themesflat-addons-for-elementor": [ + "cpe:2.3:a:themesflat:themesflat_addons_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "themify-portfolio-post": [ + "cpe:2.3:a:themify:portfolio_post:*:*:*:*:*:wordpress:*:*" + ], + "themify-wc-product-filter": [ + "cpe:2.3:a:themify:woocommerce_product_filter:*:*:*:*:*:wordpress:*:*" + ], + "thesography": [ + "cpe:2.3:a:kristarella:exifography:*:*:*:*:*:wordpress:*:*" + ], + "thinkific-uploader": [ + "cpe:2.3:a:thinkific:thinkific_uploader:*:*:*:*:*:wordpress:*:*" + ], + "thinktwit": [ + "cpe:2.3:a:thinktwit_project:thinktwit:*:*:*:*:*:wordpress:*:*" + ], + "thirstyaffiliates": [ + "cpe:2.3:a:caseproof:thirstyaffiliates_affiliate_link_manager:*:*:*:*:*:wordpress:*:*" + ], + "thumbs-rating": [ + "cpe:2.3:a:quicoto:thumbs_rating:*:*:*:*:*:wordpress:*:*" + ], + "tickera-event-ticketing-system": [ + "cpe:2.3:a:tickera:tickera:*:*:*:*:*:wordpress:*:*" + ], + "time-sheets": [ + "cpe:2.3:a:dcac:time_sheets:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:time_sheets_project:time_sheets:*:*:*:*:*:wordpress:*:*" + ], + "timeline-awesome": [ + "cpe:2.3:a:themesawesome:timeline_awesome:*:*:*:*:*:wordpress:*:*" + ], + "timeline-calendar": [ + "cpe:2.3:a:timeline_calendar_project:timeline_calendar:*:*:*:*:*:wordpress:*:*" + ], + "timeline-widget-addon-for-elementor": [ + "cpe:2.3:a:coolplugins:timeline_widget_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "timesheet": [ + "cpe:2.3:a:bestwebsoft:timesheet:*:*:*:*:*:wordpress:*:*" + ], + "timthumb-vulnerability-scanner": [ + "cpe:2.3:a:peterbutler:timthumb_vulnerability_scanner:*:*:*:*:*:wordpress:*:*" + ], + "tinychat-roomspy": [ + "cpe:2.3:a:tinychat:room_spy:*:*:*:*:*:wordpress:*:*" + ], + "tinymce-custom-styles": [ + "cpe:2.3:a:tinymce_custom_styles_project:tinymce_custom_styles:*:*:*:*:*:wordpress:*:*" + ], + "titan-framework": [ + "cpe:2.3:a:gambit:titan_framework:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:titan_framework_project:titan_framework:*:*:*:*:*:wordpress:*:*" + ], + "tk-google-fonts": [ + "cpe:2.3:a:themekraft:tk_google_fonts_gdpr_compliant:*:*:*:*:*:wordpress:*:*" + ], + "tlp-portfolio": [ + "cpe:2.3:a:radiustheme:portfolio:*:*:*:*:free:wordpress:*:*" + ], + "tlp-team": [ + "cpe:2.3:a:radiustheme:team_-_wordpress_team_members_showcase:*:*:*:*:*:wordpress:*:*" + ], + "to-top": [ + "cpe:2.3:a:catchplugins:to_top:*:*:*:*:*:wordpress:*:*" + ], + "toggle-the-title": [ + "cpe:2.3:a:toggle-the-title_project:toggle-the-title:*:*:*:*:*:wordpress:*:*" + ], + "toolbar-to-share": [ + "cpe:2.3:a:toolbar_to_share_project:toolbar_to_share:*:*:*:*:*:wordpress:*:*" + ], + "top-10": [ + "cpe:2.3:a:top_10_project:top_10:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:webberzone:top_10:*:*:*:*:*:wordpress:*:*" + ], + "top-25-social-icons": [ + "cpe:2.3:a:vyasdipen:top_25_social_icons:*:*:*:*:*:wordpress:*:*" + ], + "top-bar": [ + "cpe:2.3:a:wpdarko:top_bar:*:*:*:*:*:wordpress:*:*" + ], + "torro-forms": [ + "cpe:2.3:a:awesome:torro_forms:*:*:*:*:*:wordpress:*:*" + ], + "total-donations": [ + "cpe:2.3:a:calmar-webmedia:total_donations:*:*:*:*:*:wordpress:*:*" + ], + "total-security": [ + "cpe:2.3:a:fabrix:total_security:*:*:*:*:*:wordpress:*:*" + ], + "total-team-lite": [ + "cpe:2.3:a:accesspressthemes:total_team_lite:*:*:*:*:*:wordpress:*:*" + ], + "totop-link": [ + "cpe:2.3:a:nocean:totop_link:*:*:*:*:*:wordpress:*:*" + ], + "tp-education": [ + "cpe:2.3:a:themepalace:tp_education:*:*:*:*:*:wordpress:*:*" + ], + "tpg-redirect": [ + "cpe:2.3:a:tpginc:tpg_redirect:*:*:*:*:*:wordpress:*:*" + ], + "track-geolocation-of-users-using-contact-form-7": [ + "cpe:2.3:a:zealousweb:track_geolocation_of_users_using_contact_form_7:*:*:*:*:*:wordpress:*:*" + ], + "track-the-click": [ + "cpe:2.3:a:tracktheclick:track_the_click:*:*:*:*:*:wordpress:*:*" + ], + "tradetracker-store": [ + "cpe:2.3:a:wpaffiliatefeed:tradetracker-store:*:*:*:*:*:wordpress:*:*" + ], + "traffic-manager": [ + "cpe:2.3:a:sedlex:traffic_manager:*:*:*:*:*:wordpress:*:*" + ], + "transbank-webpay-plus-rest": [ + "cpe:2.3:a:transbank:transbank_webpay_rest:*:*:*:*:*:wordpress:*:*" + ], + "translatepress-multilingual": [ + "cpe:2.3:a:cozmoslabs:translatepress:*:*:*:*:*:wordpress:*:*" + ], + "transposh-translation-filter-for-wordpress": [ + "cpe:2.3:a:transposh:transposh_wordpress_translation:*:*:*:*:*:wordpress:*:*" + ], + "travelmap-blog": [ + "cpe:2.3:a:travelmap:travelmap:*:*:*:*:*:wordpress:*:*" + ], + "treepress": [ + "cpe:2.3:a:blackandwhitedigital:treepress:*:*:*:*:*:wordpress:*:*" + ], + "triberr-wordpress-plugin": [ + "cpe:2.3:a:triberr:triberr:*:*:*:*:*:wordpress:*:*" + ], + "tripay-payment-gateway": [ + "cpe:2.3:a:tripay:payment_gateway:*:*:*:*:*:wordpress:*:*" + ], + "tripetto": [ + "cpe:2.3:a:tripetto:tripetto:*:*:*:*:*:wordpress:*:*" + ], + "ts-webfonts-for-conoha": [ + "cpe:2.3:a:gmo:typesquare_webfonts_for_conoha:*:*:*:*:*:wordpress:*:*" + ], + "ts-webfonts-for-sakura": [ + "cpe:2.3:a:sakura:ts_webfonts_for_sakura:*:*:*:*:*:wordpress:*:*" + ], + "ttv-easy-embed-player": [ + "cpe:2.3:a:streamweasels:twitch_player:*:*:*:*:*:wordpress:*:*" + ], + "tubepress": [ + "cpe:2.3:a:tubepress:tubepress:*:*:*:*:*:wordpress:*:*" + ], + "tune-library": [ + "cpe:2.3:a:tune_library_project:tune_library:*:*:*:*:*:wordpress:*:*" + ], + "turn-off-comments-for-all-posts": [ + "cpe:2.3:a:turn_off_all_comments_project:turn_off_all_comments:*:*:*:*:*:*:*:*" + ], + "tutor": [ + "cpe:2.3:a:themeum:tutor_lms:*:*:*:*:*:wordpress:*:*" + ], + "tuxedo-big-file-uploads": [ + "cpe:2.3:a:infiniteuploads:big_file_uploads:*:*:*:*:*:wordpress:*:*" + ], + "tweeple": [ + "cpe:2.3:a:themeblvd:tweeple:*:*:*:*:*:wordpress:*:*" + ], + "tweet-wheel": [ + "cpe:2.3:a:nerdcow:tweet_wheel:*:*:*:*:*:wordpress:*:*" + ], + "twenty20": [ + "cpe:2.3:a:twenty20_project:twenty20:*:*:*:*:*:wordpress:*:*" + ], + "twitget": [ + "cpe:2.3:a:twitget_project:twitget:*:*:*:*:*:wordpress:*:*" + ], + "twittee-text-tweet": [ + "cpe:2.3:a:johnniejodelljr:twittee_text_tweet:*:*:*:*:*:wordpress:*:*" + ], + "twitter-cards-meta": [ + "cpe:2.3:a:wpdeveloper:twitter_cards_meta:*:*:*:*:*:wordpress:*:*" + ], + "twitter-friends-widget": [ + "cpe:2.3:a:twitter_friends_widget_project:twitter_friends_widget:*:*:*:*:*:wordpress:*:*" + ], + "twitter-plugin": [ + "cpe:2.3:a:bestwebsoft:twitter:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:bestwebsoft:twitter_button:*:*:*:*:*:wordpress:*:*" + ], + "two-factor-authentication": [ + "cpe:2.3:a:simbahosting:two-factor-authentication:*:*:*:*:*:wordpress:*:*" + ], + "typebot": [ + "cpe:2.3:a:typebot:typebot:*:*:*:*:*:wordpress:*:*" + ], + "typofr": [ + "cpe:2.3:a:typofr_project:typofr:*:*:*:*:*:wordpress:*:*" + ], + "ucontext": [ + "cpe:2.3:a:summitmediaconcepts:ucontext_for_clickbank:*:*:*:*:*:wordpress:*:*" + ], + "ucontext-for-amazon": [ + "cpe:2.3:a:summitmediaconcepts:ucontext_for_amazon:*:*:*:*:*:wordpress:*:*" + ], + "uji-countdown": [ + "cpe:2.3:a:wpmanage:uji_countdown:*:*:*:*:*:wordpress:*:*" + ], + "uji-popup": [ + "cpe:2.3:a:wpmanage:uji_popup:*:*:*:*:*:wordpress:*:*" + ], + "uk-cookie-consent": [ + "cpe:2.3:a:termly:gdpr_cookie_consent_banner:*:*:*:*:*:wordpress:*:*" + ], + "uleak-security-dashboard": [ + "cpe:2.3:a:uleak-security-dashboard_project:uleak-security-dashboard:*:*:*:*:*:wordpress:*:*" + ], + "ulisting": [ + "cpe:2.3:a:stylemixthemes:ulisting:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-addons-for-beaver-builder-lite": [ + "cpe:2.3:a:brainstormforce:ultimate_addons_for_beaver_builder:*:*:*:*:lite:wordpress:*:*" + ], + "ultimate-addons-for-contact-form-7": [ + "cpe:2.3:a:themefic:ultimate_addons_for_contact_form_7:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-addons-for-gutenberg": [ + "cpe:2.3:a:brainstormforce:spectra:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-appointment-scheduling": [ + "cpe:2.3:a:etoilewebdesign:ultimate_appointment_booking_\\\u0026_scheduling:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-author-box-lite": [ + "cpe:2.3:a:accesspressthemes:ultimate_author_box_lite:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-carousel-for-elementor": [ + "cpe:2.3:a:topdigitaltrends:ultimate_carousel_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-carousel-for-visual-composer": [ + "cpe:2.3:a:topdigitaltrends:ultimate_carousel_for_wpbakery_page_builder:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-category-excluder": [ + "cpe:2.3:a:infolific:ultimate_category_excluder:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-dashboard": [ + "cpe:2.3:a:davidvongries:ultimate_dashboard:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-faqs": [ + "cpe:2.3:a:etoilewebdesign:ultimate_faq:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-form-builder-lite": [ + "cpe:2.3:a:accesspressthemes:ultimate-form-builder-lite:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-instagram-feed": [ + "cpe:2.3:a:ultimate_instagram_feed_project:ultimate_instagram_feed:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-maps-by-supsystic": [ + "cpe:2.3:a:supsystic:ultimate_maps:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-member": [ + "cpe:2.3:a:ultimatemember:ultimate_member:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:ultimatemember:user_profile_\\\u0026_membership:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-noindex-nofollow-tool-ii": [ + "cpe:2.3:a:ultimate_noindex_nofollow_tool_ii_project:ultimate_noindex_nofollow_tool_ii:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-post": [ + "cpe:2.3:a:wpxpo:postx:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-posts-widget": [ + "cpe:2.3:a:themecheck:ultimate_posts_widget:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-product-catalogue": [ + "cpe:2.3:a:etoilewebdesign:ultimate_product_catalog:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-reviews": [ + "cpe:2.3:a:etoilewebdesign:ultimate_reviews:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-sms-notifications": [ + "cpe:2.3:a:homescript:ultimate_sms_notifications:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:ultimatesmsnotifications:ultimate_sms_notifications_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-social-media-icons": [ + "cpe:2.3:a:ultimatelysocial:social_media_share_buttons_\\\u0026_social_sharing_icons:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-social-media-plus": [ + "cpe:2.3:a:socialshare:social_share_icons_\\\u0026_social_share_buttons:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-tables": [ + "cpe:2.3:a:webpsilon:ultimate_tables:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-taxonomy-manager": [ + "cpe:2.3:a:xydac:ultimate_taxonomy_manager:*:*:*:*:*:*:*:*" + ], + "ultimate-weather-plugin": [ + "cpe:2.3:a:ultimate-weather_project:ultimate-weather:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-wp-query-search-filter": [ + "cpe:2.3:a:ultimate_wp_query_search_filter_project:ultimate_wp_query_search_filter:*:*:*:*:*:wordpress:*:*" + ], + "ultra-companion": [ + "cpe:2.3:a:wpoperation:ultra_companion:*:*:*:*:*:wordpress:*:*" + ], + "uncanny-automator": [ + "cpe:2.3:a:uncannyowl:uncanny_automator:*:*:*:*:*:wordpress:*:*" + ], + "uncanny-learndash-toolkit": [ + "cpe:2.3:a:uncannyowl:uncanny_toolkit_for_learndash:*:*:*:*:*:*:*:*", + "cpe:2.3:a:uncannyowl:uncanny_toolkit_for_learndash:*:*:*:*:*:wordpress:*:*" + ], + "unconfirmed": [ + "cpe:2.3:a:unconfirmed_project:unconfirmed:*:*:*:*:*:wordpress:*:*" + ], + "under-construction-page": [ + "cpe:2.3:a:webfactoryltd:under_construction:*:*:*:*:*:wordpress:*:*" + ], + "underconstruction": [ + "cpe:2.3:a:underconstruction_project:underconstruction:*:*:*:*:*:wordpress:*:*" + ], + "uninstall": [ + "cpe:2.3:a:wordpress_uninstall_project:wordpress_uninstall:*:*:*:*:*:wordpress:*:*" + ], + "unite-gallery-lite": [ + "cpe:2.3:a:unitegallery:unite_gallery_lite:*:*:*:*:*:wordpress:*:*" + ], + "universal-analytics": [ + "cpe:2.3:a:matchboxdesigngroup:universal_analytics:*:*:*:*:*:wordpress:*:*" + ], + "universal-star-rating": [ + "cpe:2.3:a:universal_star_rating_project:universal_star_rating:*:*:*:*:*:wordpress:*:*" + ], + "unlimited-addons-for-wpbakery-page-builder": [ + "cpe:2.3:a:unitecms:unlimited_addons_for_wpbakery_page_builder:*:*:*:*:*:wordpress:*:*" + ], + "unlimited-elements-for-elementor": [ + "cpe:2.3:a:unlimited-elements:unlimited_elements_for_elementor_\\(free_widgets\\,_addons\\,_templates\\):*:*:*:*:*:wordpress:*:*" + ], + "unlimited-popups": [ + "cpe:2.3:a:unlimited_popups_project:unlimited_popups:*:*:*:*:*:wordpress:*:*" + ], + "unusedcss": [ + "cpe:2.3:a:rapidload:rapidload_power-up_for_autoptimize:*:*:*:*:*:wordpress:*:*" + ], + "unyson": [ + "cpe:2.3:a:brizy:unyson:*:*:*:*:*:wordpress:*:*" + ], + "up-down-image-slideshow-gallery": [ + "cpe:2.3:a:gopiplus:up_down_image_slideshow_gallery:*:*:*:*:*:wordpress:*:*" + ], + "updater": [ + "cpe:2.3:a:bestwebsoft:updater:*:*:*:*:*:wordpress:*:*" + ], + "updraftplus": [ + "cpe:2.3:a:updraftplus:updraftplus:*:*:*:*:*:wordpress:*:*" + ], + "upload-fields-for-wpforms": [ + "cpe:2.3:a:softlabbd:upload_fields_for_wpforms:*:*:*:*:*:wordpress:*:*" + ], + "upload-file-type-settings-plugin": [ + "cpe:2.3:a:upload_file_type_settings_plugin_project:upload_file_type_settings_plugin:*:*:*:*:*:wordpress:*:*" + ], + "uploading-svgwebp-and-ico-files": [ + "cpe:2.3:a:uploading_svg\\,_webp_and_ico_files_project:uploading_svg\\,_webp_and_ico_files:*:*:*:*:*:wordpress:*:*" + ], + "upunzipper": [ + "cpe:2.3:a:upunzipper_project:upunzipper:*:*:*:*:*:wordpress:*:*" + ], + "url-shortify": [ + "cpe:2.3:a:kaizencoders:url_shortify:*:*:*:*:*:wordpress:*:*" + ], + "usc-e-shop": [ + "cpe:2.3:a:collne:welcart:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:collne:welcart_e-commerce:*:*:*:*:*:wordpress:*:*" + ], + "use-any-font": [ + "cpe:2.3:a:anyfont_plugin_project:anyfont:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:dineshkarki:use_any_font:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:dnesscarkey:use_any_font:*:*:*:*:*:wordpress:*:*" + ], + "useful-banner-manager": [ + "cpe:2.3:a:useful_banner_manager_project:useful_banner_manager:*:*:*:*:*:wordpress:*:*" + ], + "user-access-manager": [ + "cpe:2.3:a:user_access_manager_project:user_access_manager:*:*:*:*:*:wordpress:*:*" + ], + "user-activation-email": [ + "cpe:2.3:a:user-activation-email_project:user-activation-email:*:*:*:*:*:wordpress:*:*" + ], + "user-activity-log": [ + "cpe:2.3:a:solwininfotech:user_activity_log:*:*:*:*:*:wordpress:*:*" + ], + "user-avatar-reloaded": [ + "cpe:2.3:a:wpexperts:user_avatar-reloaded:*:*:*:*:*:wordpress:*:*" + ], + "user-blocker": [ + "cpe:2.3:a:solwininfotech:user_blocker:*:*:*:*:*:wordpress:*:*" + ], + "user-domain-whitelist": [ + "cpe:2.3:a:user_domain_whitelist_project:user_domain_whitelist:*:*:*:*:*:wordpress:*:*" + ], + "user-export-with-their-meta-data": [ + "cpe:2.3:a:export_users_with_meta_project:export_users_with_meta:*:*:*:*:*:wordpress:*:*" + ], + "user-location-and-ip": [ + "cpe:2.3:a:user_location_and_ip_project:user_location_and_ip:*:*:*:*:*:wordpress:*:*" + ], + "user-login-history": [ + "cpe:2.3:a:user-login-history_project:user-login-history:*:*:*:*:*:wordpress:*:*" + ], + "user-login-log": [ + "cpe:2.3:a:intechnosoftware:user_login_log:*:*:*:*:*:wordpress:*:*" + ], + "user-meta": [ + "cpe:2.3:a:user-meta:user_meta_user_profile_builder_and_user_management:*:*:*:*:*:wordpress:*:*" + ], + "user-meta-manager": [ + "cpe:2.3:a:user_meta_manager_project:user_meta_manager:*:*:*:*:*:wordpress:*:*" + ], + "user-meta-shortcodes": [ + "cpe:2.3:a:user_meta_shortcodes_project:user_meta_shortcodes:*:*:*:*:*:wordpress:*:*" + ], + "user-photo": [ + "cpe:2.3:a:user_photo_project:user_photo:*:*:*:*:*:wordpress:*:*" + ], + "user-private-files": [ + "cpe:2.3:a:mediajedi:user_private_files:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:userprivatefiles:wordpress_file_sharing_plugin:*:*:*:*:*:wordpress:*:*" + ], + "user-registration": [ + "cpe:2.3:a:wpeverest:user_registration:*:*:*:*:*:wordpress:*:*" + ], + "user-role": [ + "cpe:2.3:a:bestwebsoft:user_role:*:*:*:*:*:wordpress:*:*" + ], + "user-submitted-posts": [ + "cpe:2.3:a:plugin-planet:user_submitted_posts:*:*:*:*:*:wordpress:*:*" + ], + "user-verification": [ + "cpe:2.3:a:pickplugins:user_verification:*:*:*:*:*:wordpress:*:*" + ], + "userback": [ + "cpe:2.3:a:userback:userback:*:*:*:*:*:wordpress:*:*" + ], + "userfeedback-lite": [ + "cpe:2.3:a:monsterinsights:user_feedback:*:*:*:*:*:wordpress:*:*" + ], + "userheat": [ + "cpe:2.3:a:userlocal:userheat_plugin:*:*:*:*:*:wordpress:*:*" + ], + "userlike": [ + "cpe:2.3:a:userlike:userlike:*:*:*:*:*:wordpress:*:*" + ], + "userplus": [ + "cpe:2.3:a:wpuserplus:userplus:*:*:*:*:*:wordpress:*:*" + ], + "userpro": [ + "cpe:2.3:a:userproplugin:userpro:*:*:*:*:*:wordpress:*:*" + ], + "users-customers-import-export-for-wp-woocommerce": [ + "cpe:2.3:a:webtoffee:import_export_wordpress_users:*:*:*:*:*:wordpress:*:*" + ], + "users-ultra": [ + "cpe:2.3:a:usersultra:users_ultra_membership:*:*:*:*:*:wordpress:*:*" + ], + "userswp": [ + "cpe:2.3:a:ayecode:userswp:*:*:*:*:*:wordpress:*:*" + ], + "utubevideo-gallery": [ + "cpe:2.3:a:utubevideo_gallery_project:utubevideo_gallery:*:*:*:*:*:wordpress:*:*" + ], + "vaultpress": [ + "cpe:2.3:a:automattic:vaultpress:*:*:*:*:*:wordpress:*:*" + ], + "verge3d": [ + "cpe:2.3:a:soft8soft:verge3d:*:*:*:*:*:wordpress:*:*" + ], + "verse-o-matic": [ + "cpe:2.3:a:verse-o-matic_project:verse-o-matic:*:*:*:*:*:wordpress:*:*" + ], + "vertical-marquee-plugin": [ + "cpe:2.3:a:gopiplus:vertical_marquee_plugin:*:*:*:*:*:wordpress:*:*" + ], + "vertical-scroll-recent-registered-user": [ + "cpe:2.3:a:gopiplus:vertical_scroll_recent_registered_user:*:*:*:*:*:wordpress:*:*" + ], + "very-simple-contact-form": [ + "cpe:2.3:a:very_simple_contact_form_project:very_simple_contact_form:*:*:*:*:*:wordpress:*:*" + ], + "very-simple-google-maps": [ + "cpe:2.3:a:very_simple_google_maps_project:very_simple_google_maps:*:*:*:*:*:wordpress:*:*" + ], + "video-background": [ + "cpe:2.3:a:pushlabs:video_background:*:*:*:*:*:wordpress:*:*" + ], + "video-central": [ + "cpe:2.3:a:video_central_project:video_central:*:*:*:*:*:wordpress:*:*" + ], + "video-comments-webcam-recorder": [ + "cpe:2.3:a:videowhisper:video_comments_webcam_recorder:*:*:*:*:*:wordpress:*:*" + ], + "video-conferencing-with-zoom-api": [ + "cpe:2.3:a:imdpen:video_conferencing_with_zoom:*:*:*:*:*:wordpress:*:*" + ], + "video-embed-box": [ + "cpe:2.3:a:video-embed-box_project:video-embed-box:*:*:*:*:*:wordpress:*:*" + ], + "video-playlist-and-gallery-plugin": [ + "cpe:2.3:a:cincopa:video_and_media_plug-in:*:*:*:*:*:wordpress:*:*" + ], + "video-slider-with-thumbnails": [ + "cpe:2.3:a:i13websolution:video_gallery:*:*:*:*:*:wordpress:*:*" + ], + "video-thumbnails": [ + "cpe:2.3:a:video_thumbnails_project:video_thumbnails:*:*:*:*:*:wordpress:*:*" + ], + "videojs-html5-player": [ + "cpe:2.3:a:wphowto:videojs_html5_player:*:*:*:*:*:wordpress:*:*" + ], + "videowhisper-live-streaming-integration": [ + "cpe:2.3:a:videowhisper:videowhisper_live_streaming_integration:*:*:*:*:*:wordpress:*:*" + ], + "videowhisper-video-conference-integration": [ + "cpe:2.3:a:videowhisper:video_conference:*:*:*:*:*:wordpress:*:*" + ], + "videowhisper-video-presentation": [ + "cpe:2.3:a:videowhisper:video_presentation:*:*:*:*:*:wordpress:*:*" + ], + "view-all-posts-pages": [ + "cpe:2.3:a:oomphinc:view_all_post\\'s_pages:*:*:*:*:*:wordpress:*:*" + ], + "views-for-wpforms-lite": [ + "cpe:2.3:a:formviewswp:views_for_wpforms:*:*:*:*:*:wordpress:*:*" + ], + "vikbooking": [ + "cpe:2.3:a:vikwp:vikbooking_hotel_booking_engine_\\\u0026_pms:*:*:*:*:*:wordpress:*:*" + ], + "vikrentcar": [ + "cpe:2.3:a:e4jconnect:vikrentcar:*:*:*:*:*:wordpress:*:*" + ], + "vision": [ + "cpe:2.3:a:vision_interactive_project:vision_interactive:*:*:*:*:*:wordpress:*:*" + ], + "visitors-online": [ + "cpe:2.3:a:bestwebsoft:visitors_online:*:*:*:*:*:wordpress:*:*" + ], + "visitors-traffic-real-time-statistics": [ + "cpe:2.3:a:wp-buy:visitor_traffic_real_time_statistics:*:*:*:*:*:wordpress:*:*" + ], + "visual-form-builder": [ + "cpe:2.3:a:vfbpro:visual_form_builder:*:*:*:*:*:wordpress:*:*" + ], + "visual-link-preview": [ + "cpe:2.3:a:bootstrapped:visual_link_preview:*:*:*:*:*:wordpress:*:*" + ], + "visual-portfolio": [ + "cpe:2.3:a:visualportfolio:visual_portfolio\\,_photo_gallery_\\\u0026_post_grid:*:*:*:*:*:wordpress:*:*" + ], + "visualcomposer": [ + "cpe:2.3:a:visualcomposer:visual_composer_website_builder:*:*:*:*:*:wordpress:*:*" + ], + "visualizer": [ + "cpe:2.3:a:themeisle:visualizer:*:*:*:*:*:wordpress:*:*" + ], + "vk-all-in-one-expansion-unit": [ + "cpe:2.3:a:vektor-inc:vk_all_in_one_expansion_unit:*:*:*:*:*:wordpress:*:*" + ], + "vk-block-patterns": [ + "cpe:2.3:a:vektor-inc:vk_block_patterns:*:*:*:*:*:wordpress:*:*" + ], + "vk-blocks": [ + "cpe:2.3:a:vektor-inc:vk_blocks:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:vektor-inc:vk_blocks:*:*:*:*:-:wordpress:*:*", + "cpe:2.3:a:vektor-inc:vk_blocks:*:*:*:*:pro:wordpress:*:*" + ], + "vk-filter-search": [ + "cpe:2.3:a:vektor-inc:vk_filter_search:*:*:*:*:*:*:*:*" + ], + "vk-poster-group": [ + "cpe:2.3:a:zixn:vk_poster_group:*:*:*:*:*:wordpress:*:*" + ], + "vm-backups": [ + "cpe:2.3:a:vm_backups_project:vm_backups:*:*:*:*:*:wordpress:*:*" + ], + "vospari-forms": [ + "cpe:2.3:a:vospari_forms_project:vospari_forms:*:*:*:*:*:wordpress:*:*" + ], + "voting-record": [ + "cpe:2.3:a:voting_record_project:voting_record:*:*:*:*:*:wordpress:*:*" + ], + "vr-calendar-sync": [ + "cpe:2.3:a:vr_calendar_project:vr_calendar:*:*:*:*:*:wordpress:*:*" + ], + "vrm360": [ + "cpe:2.3:a:maurice:vrm360:*:*:*:*:*:wordpress:*:*" + ], + "vslider": [ + "cpe:2.3:a:vibethemes:vslider:*:*:*:*:*:wordpress:*:*" + ], + "w-dalil": [ + "cpe:2.3:a:w-dalil_project:w-dalil:*:*:*:*:*:wordpress:*:*" + ], + "w3-total-cache": [ + "cpe:2.3:a:boldgrid:w3_total_cache:*:*:*:*:*:wordpress:*:*" + ], + "w4-post-list": [ + "cpe:2.3:a:w4_post_list_project:w4_post_list:*:*:*:*:*:wordpress:*:*" + ], + "wa-sticky-button": [ + "cpe:2.3:a:okapitech:wp_sticky_button:*:*:*:*:*:wordpress:*:*" + ], + "waiting": [ + "cpe:2.3:a:plugin:waiting:*:*:*:*:*:wordpress:*:*" + ], + "waitlist-woocommerce": [ + "cpe:2.3:a:xootix:waitlist_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "wassup": [ + "cpe:2.3:a:wassup_real_time_analytics_project:wassup_real_time_analytics:*:*:*:*:*:wordpress:*:*" + ], + "watcheezy": [ + "cpe:2.3:a:targetfirst:watcheezy:*:*:*:*:*:wordpress:*:*" + ], + "watchtowerhq": [ + "cpe:2.3:a:watchtowerhq:watchtower:*:*:*:*:*:wordpress:*:*" + ], + "wats": [ + "cpe:2.3:a:ticket-system:wordpress_advanced_ticket_system:*:*:*:*:*:wordpress:*:*" + ], + "watu": [ + "cpe:2.3:a:kibokolabs:watu_quiz:*:*:*:*:*:wordpress:*:*" + ], + "wc-dynamic-pricing-and-discounts": [ + "cpe:2.3:a:rightpress:woocommerce_dynamic_pricing_\\\u0026_discounts:*:*:*:*:*:wordpress:*:*" + ], + "wc-frontend-manager": [ + "cpe:2.3:a:wclovers:frontend_manager_for_woocommerce_along_with_bookings_subscription_listings_compatible:*:*:*:*:*:wordpress:*:*" + ], + "wc-gsheetconnector": [ + "cpe:2.3:a:gsheetconnector:woocommerce_google_sheet_connector:*:*:*:*:*:wordpress:*:*" + ], + "wc-multivendor-marketplace": [ + "cpe:2.3:a:wclovers:wcfm_marketplace:*:*:*:*:*:wordpress:*:*" + ], + "wc-multivendor-membership": [ + "cpe:2.3:a:wclovers:wcfm_membership:*:*:*:*:*:wordpress:*:*" + ], + "wc-out-of-stock-message": [ + "cpe:2.3:a:coderstimes:out_of_stock_message_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "wc-product-table-lite": [ + "cpe:2.3:a:wcproducttable:woocommerce_product_table_lite:*:*:*:*:*:wordpress:*:*" + ], + "wc-return-warrranty": [ + "cpe:2.3:a:return_and_warranty_management_system_for_woocommerce_project:return_and_warranty_management_system_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "wc-sales-notification": [ + "cpe:2.3:a:hasthemes:wc_sales_notification:*:*:*:*:*:wordpress:*:*" + ], + "wc-serial-numbers": [ + "cpe:2.3:a:pluginever:wc_serial_numbers:*:*:*:*:*:wordpress:*:*" + ], + "wc-support-system": [ + "cpe:2.3:a:ilghera:woocommerce_support_system:*:*:*:*:*:wordpress:*:*" + ], + "wc-vendors": [ + "cpe:2.3:a:wcvendors:woocommerce_multi-vendor\\,_woocommerce_marketplace\\,_product_vendors:*:*:*:*:*:wordpress:*:*" + ], + "wc4bp": [ + "cpe:2.3:a:themekraft:buddypress_woocommerce_my_account_integration:*:*:*:*:*:wordpress:*:*" + ], + "wck-custom-fields-and-custom-post-types-creator": [ + "cpe:2.3:a:cozmoslabs:custom_post_types_and_custom_fields_creator:*:*:*:*:*:wordpress:*:*" + ], + "wcp-contact-form": [ + "cpe:2.3:a:webcodin:wcp_contact_form:*:*:*:*:*:wordpress:*:*" + ], + "wd-facebook-feed": [ + "cpe:2.3:a:10web:10web_social_post_feed:*:*:*:*:*:wordpress:*:*" + ], + "wd-google-analytics": [ + "cpe:2.3:a:10web:10webanalytics:*:*:*:*:*:wordpress:*:*" + ], + "wd-google-maps": [ + "cpe:2.3:a:10web:map_builder_for_google_maps:*:*:*:*:*:wordpress:*:*" + ], + "wd-instagram-feed": [ + "cpe:2.3:a:10web:10websocial:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:10web:social_feed_for_instagram:*:*:*:*:premium:wordpress:*:*" + ], + "wds-multisite-aggregate": [ + "cpe:2.3:a:webdevstudios:wds_multisite_aggregate:*:*:*:*:*:wordpress:*:*" + ], + "weather-effect": [ + "cpe:2.3:a:awplife:weather_effect:*:*:*:*:*:wordpress:*:*" + ], + "weaverx-theme-support": [ + "cpe:2.3:a:weavertheme:weaver_xtreme_theme_support:*:*:*:*:*:wordpress:*:*" + ], + "web-directory-free": [ + "cpe:2.3:a:salephpscripts:web_directory_free:*:*:*:*:*:wordpress:*:*" + ], + "web-invoice": [ + "cpe:2.3:a:mohanjith:web_invoice:*:*:*:*:*:wordpress:*:*" + ], + "web-stat": [ + "cpe:2.3:a:web-stat:web-stat:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:web-stat_project:web-stat:*:*:*:*:*:wordpress:*:*" + ], + "web-stories": [ + "cpe:2.3:a:google:web_stories:*:*:*:*:*:wordpress:*:*" + ], + "web3-authentication": [ + "cpe:2.3:a:miniorange:web3_-_crypto_wallet_login_\\\u0026_nft_token_gating:*:*:*:*:*:wordpress:*:*" + ], + "webapp-builder": [ + "cpe:2.3:a:webapp-builder_project:webapp-builder:*:*:*:*:*:wordpress:*:*" + ], + "webappick-product-feed-for-woocommerce": [ + "cpe:2.3:a:webappick:woocommerce_product_feed:*:*:*:*:*:wordpress:*:*" + ], + "webba-booking-lite": [ + "cpe:2.3:a:webba-booking:webba_booking:*:*:*:*:*:wordpress:*:*" + ], + "webcam-2way-videochat": [ + "cpe:2.3:a:videowhisper:2way_videocalls_and_random_chat:*:*:*:*:*:wordpress:*:*" + ], + "webful-simple-grocery-shop": [ + "cpe:2.3:a:wordpress_simple_shop_project:wordpress_simple_shop:*:*:*:*:*:wordpress:*:*" + ], + "webinar-ignition": [ + "cpe:2.3:a:saleswonder:webinarignition:*:*:*:*:*:wordpress:*:*" + ], + "weblibrarian": [ + "cpe:2.3:a:deepsoft:weblibrarian:*:*:*:*:*:wordpress:*:*" + ], + "weblizar-pinterest-feeds": [ + "cpe:2.3:a:weblizar:pinterest-feeds:*:*:*:*:*:wordpress:*:*" + ], + "webp-converter-for-media": [ + "cpe:2.3:a:webp_converter_for_media_project:webp_converter_for_media:*:*:*:*:*:wordpress:*:*" + ], + "webp-express": [ + "cpe:2.3:a:bitwise-it:webp_express:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:webp_express_project:webp_express:*:*:*:*:*:wordpress:*:*" + ], + "webpushr-web-push-notifications": [ + "cpe:2.3:a:webpushr:web_push_notifications:*:*:*:*:*:wordpress:*:*" + ], + "webriti-smtp-mail": [ + "cpe:2.3:a:webriti:webriti_smtp_mail:*:*:*:*:*:wordpress:*:*" + ], + "websimon-tables": [ + "cpe:2.3:a:websimon-tables_project:websimon-tables:*:*:*:*:*:wordpress:*:*" + ], + "website-monetization-by-magenet": [ + "cpe:2.3:a:magenet:website_monetization:*:*:*:*:*:wordpress:*:*" + ], + "webwinkelkeur": [ + "cpe:2.3:a:webwinkelkeur_project:webwinkelkeur:*:*:*:*:*:wordpress:*:*" + ], + "wechat-broadcast": [ + "cpe:2.3:a:wechat_broadcast_project:wechat_broadcast:*:*:*:*:*:wordpress:*:*" + ], + "wedevs-project-manager": [ + "cpe:2.3:a:wedevs:wp_project_manager:*:*:*:*:*:wordpress:*:*" + ], + "weekly-schedule": [ + "cpe:2.3:a:weekly_schedule_project:weekly_schedule:*:*:*:*:*:wordpress:*:*" + ], + "weforms": [ + "cpe:2.3:a:weformspro:weforms:*:*:*:*:*:wordpress:*:*" + ], + "weixin-robot-advanced": [ + "cpe:2.3:a:wpjam:wechat_robot:*:*:*:*:premium:wordpress:*:*" + ], + "wf-cookie-consent": [ + "cpe:2.3:a:wunderfarm:wf_cookie_consent:*:*:*:*:*:wordpress:*:*" + ], + "wh-testimonials": [ + "cpe:2.3:a:webhostings:wh_testimonials:*:*:*:*:*:wordpress:*:*" + ], + "wha-puzzle": [ + "cpe:2.3:a:webhelpagency:wha_puzzle:*:*:*:*:*:wordpress:*:*" + ], + "whatsapp": [ + "cpe:2.3:a:firecask:whatsapp_share_button:*:*:*:*:*:wordpress:*:*" + ], + "whatshelp-chat-button": [ + "cpe:2.3:a:getbutton:chat_button:*:*:*:*:*:wordpress:*:*" + ], + "which-template-file": [ + "cpe:2.3:a:gillesdumas:which_template_file:*:*:*:*:*:wordpress:*:*" + ], + "white-label": [ + "cpe:2.3:a:linksoftwarellc:white_label:*:*:*:*:*:wordpress:*:*" + ], + "white-label-branding-elementor": [ + "cpe:2.3:a:white_label_branding_for_elementor_page_builder_project:white_label_branding_for_elementor_page_builder:*:*:*:*:*:wordpress:*:*" + ], + "white-label-cms": [ + "cpe:2.3:a:videousermanuals:white_label_cms:*:*:*:*:*:wordpress:*:*" + ], + "whizz": [ + "cpe:2.3:a:browserweb:whizz:*:*:*:*:*:wordpress:*:*" + ], + "whydowork-adsense": [ + "cpe:2.3:a:whydowork_adsense_project:whydowork_adsense:*:*:*:*:*:wordpress:*:*" + ], + "wicked-folders": [ + "cpe:2.3:a:wickedplugins:wicked_folders:*:*:*:*:*:wordpress:*:*" + ], + "widget-google-reviews": [ + "cpe:2.3:a:richplugins:plugin_for_google_reviews:*:*:*:*:*:wordpress:*:*" + ], + "widget-logic": [ + "cpe:2.3:a:wpchef:widget_logic:*:*:*:*:*:wordpress:*:*" + ], + "widget-settings-importexport": [ + "cpe:2.3:a:porternovelli:widget_settings_importer\\/exporter:*:*:*:*:*:wordpress:*:*" + ], + "widget-shortcode": [ + "cpe:2.3:a:widget-shortcode_project:widget-shortcode:*:*:*:*:*:wordpress:*:*" + ], + "widget-twitter": [ + "cpe:2.3:a:web-dorado:wd_widgettwitter:*:*:*:*:*:wordpress:*:*" + ], + "widgetkit-for-elementor": [ + "cpe:2.3:a:themesgrove:all-in-one_addons_for_elementor:*:*:*:*:*:wordpress:*:*" + ], + "widgets-on-pages": [ + "cpe:2.3:a:widgets-on-pages_project:widgets-on-pages:*:*:*:*:*:wordpress:*:*" + ], + "winterlock": [ + "cpe:2.3:a:wp_system_log_project:wp_system_log:*:*:*:*:*:wordpress:*:*" + ], + "wip-custom-login": [ + "cpe:2.3:a:themeinprogress:wip_custom_login:*:*:*:*:*:wordpress:*:*" + ], + "wise-chat": [ + "cpe:2.3:a:kaine:wise_chat:*:*:*:*:*:wordpress:*:*" + ], + "wiseagentleadform": [ + "cpe:2.3:a:wiseagent:wise_agent_capture_forms:*:*:*:*:*:wordpress:*:*" + ], + "wishsuite": [ + "cpe:2.3:a:hasthemes:wishsuite:*:*:*:*:*:wordpress:*:*" + ], + "wonderm00ns-simple-facebook-open-graph-tags": [ + "cpe:2.3:a:webdados:open_graph_for_facebook\\,_google\\+_and_twitter_card_tags:*:*:*:*:*:wordpress:*:*" + ], + "wonderplugin-slider-lite": [ + "cpe:2.3:a:wonderplugin:wonder_slider_lite:*:*:*:*:*:wordpress:*:*" + ], + "woo-abandoned-cart-recovery": [ + "cpe:2.3:a:villatheme:abandoned_cart_recovery_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-address-book": [ + "cpe:2.3:a:hallme:woocommerce_address_book:*:*:*:*:*:wordpress:*:*" + ], + "woo-advance-search": [ + "cpe:2.3:a:dotstore:advance_search_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-advanced-sales-report-email": [ + "cpe:2.3:a:zorem:sales_report_email_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-alidropship": [ + "cpe:2.3:a:villatheme:dropshipping_and_fulfillment_for_aliexpress_and_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-altcoin-payment-gateway": [ + "cpe:2.3:a:coinmarketstats:bitcoin_\\/_altcoin_payment_gateway_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-badge-designer-lite": [ + "cpe:2.3:a:accesspressthemes:badge_designer_lite_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-billing-with-invoicexpress": [ + "cpe:2.3:a:ptwooplugins:invoicing_with_invoicexpress_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-billingo-plus": [ + "cpe:2.3:a:woo_billingo_plus_project:woo_billingo_plus:*:*:*:*:*:wordpress:*:*" + ], + "woo-blocker-lite-prevent-fake-orders-and-blacklist-fraud-customers": [ + "cpe:2.3:a:multidots:fraud_prevention_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-bulk-editor": [ + "cpe:2.3:a:pluginus:bear_-_woocommerce_bulk_editor_and_products_manager_professional:*:*:*:*:*:wordpress:*:*" + ], + "woo-bulk-price-update": [ + "cpe:2.3:a:technocrackers:bulk_price_update_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-cart-all-in-one": [ + "cpe:2.3:a:villatheme:cart_all_in_one_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-checkout-field-editor-pro": [ + "cpe:2.3:a:themehigh:checkout_field_editor_for_woocommerce:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:themehigh:checkout_field_editor_for_woocommerce:*:*:*:*:pro:wordpress:*:*" + ], + "woo-checkout-for-digital-goods": [ + "cpe:2.3:a:dotstore:woocommerce_checkout_for_digital_goods:*:*:*:*:*:wordpress:*:*" + ], + "woo-conditional-discount-rules-for-checkout": [ + "cpe:2.3:a:multidots:dynamic_pricing_and_discount_rules_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-confirmation-email": [ + "cpe:2.3:a:wisetr:user_email_verification_for_woocommerce:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:xlplugins:woo-confirmation-email:*:*:*:*:*:wordpress:*:*" + ], + "woo-coupon-usage": [ + "cpe:2.3:a:relywp:coupon_affiliates:*:*:*:*:*:wordpress:*:*" + ], + "woo-currency": [ + "cpe:2.3:a:woobewoo:wbw_currency_switcher_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-custom-and-sequential-order-number": [ + "cpe:2.3:a:vjinfotech:woo_custom_and_sequential_order_number:*:*:*:*:*:wordpress:*:*" + ], + "woo-custom-emails": [ + "cpe:2.3:a:wp3sixty:woo_custom_emails:*:*:*:*:*:wordpress:*:*" + ], + "woo-ecommerce-tracking-for-google-and-facebook": [ + "cpe:2.3:a:multidots:enhanced_ecommerce_google_analytics_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-esto": [ + "cpe:2.3:a:rebing:woocommerce_esto:*:*:*:*:*:wordpress:*:*" + ], + "woo-gift-cards-lite": [ + "cpe:2.3:a:wpswings:ultimate_gift_cards_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-gutenberg-products-block": [ + "cpe:2.3:a:automattic:woocommerce_blocks:*:*:*:*:*:wordpress:*:*" + ], + "woo-moneybird": [ + "cpe:2.3:a:techastha:integration_of_moneybird_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-order-export-lite": [ + "cpe:2.3:a:algolplus:advanced_order_export:*:*:*:*:*:wordpress:*:*" + ], + "woo-orders-tracking": [ + "cpe:2.3:a:villatheme:orders_tracking_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-parcel-pro": [ + "cpe:2.3:a:parcelpro:parcel_pro:*:*:*:*:*:wordpress:*:*" + ], + "woo-pdf-invoice-builder": [ + "cpe:2.3:a:rednao:woocommerce_pdf_invoice_builder:*:*:*:*:*:wordpress:*:*" + ], + "woo-popup": [ + "cpe:2.3:a:woo-popup_project:woo-popup:*:*:*:*:*:wordpress:*:*" + ], + "woo-preview-emails": [ + "cpe:2.3:a:preview_e-mails_for_woocommerce_project:preview_e-mails_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-product-bundle": [ + "cpe:2.3:a:wpclever:wpc_product_bundles_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-product-category-discount": [ + "cpe:2.3:a:quanticedgesolutions:category_discount_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-product-feed-pro": [ + "cpe:2.3:a:adtribes:product_feed_pro_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-product-slider": [ + "cpe:2.3:a:shapedplugin:product_slider_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-product-table": [ + "cpe:2.3:a:codeastrology:woo_product_table:*:*:*:*:*:wordpress:*:*" + ], + "woo-product-variation-gallery": [ + "cpe:2.3:a:radiustheme:variation_images_gallery_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-products-widgets-for-elementor": [ + "cpe:2.3:a:themelocation:widgets_for_woocommerce_products_on_elementor:*:*:*:*:*:wordpress:*:*" + ], + "woo-qiwi-payment-gateway": [ + "cpe:2.3:a:qiwi:woo-qiwi-payment-gateway:*:*:*:*:*:wordpress:*:*" + ], + "woo-quick-reports": [ + "cpe:2.3:a:dotstore:woocommerce_quick_reports:*:*:*:*:*:*:*:*" + ], + "woo-refund-and-exchange-lite": [ + "cpe:2.3:a:wpswings:return_refund_and_exchange_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-related-products-refresh-on-reload": [ + "cpe:2.3:a:peachpay:related_products_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-shipping-dpd-baltic": [ + "cpe:2.3:a:dpdgroup:woocommerce_shipping:*:*:*:*:*:wordpress:*:*" + ], + "woo-smart-wishlist": [ + "cpe:2.3:a:wpclever:wpc_smart_wishlist_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-stripe-payment": [ + "cpe:2.3:a:paymentplugins:stripe_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-thank-you-page-customizer": [ + "cpe:2.3:a:villatheme:thank_you_page_customizer_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-tranzila-gateway": [ + "cpe:2.3:a:antonbond:woocommerce_tranzila_payment_gateway:*:*:*:*:*:wordpress:*:*" + ], + "woo-variation-gallery": [ + "cpe:2.3:a:getwooplugins:additional_variation_images_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-variation-swatches": [ + "cpe:2.3:a:getwooplugins:woo-variation-swatches:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:variation_swatches_for_woocommerce_project:variation_swatches_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-vietnam-checkout": [ + "cpe:2.3:a:levantoan:woocommerce_vietnam_checkout:*:*:*:*:*:wordpress:*:*" + ], + "woo-vipps": [ + "cpe:2.3:a:wp-hosting:pay_with_vipps_and_mobilepay_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woo-wallet": [ + "cpe:2.3:a:standalonetech:terawallet:*:*:*:*:*:wordpress:*:*" + ], + "woo-zoho": [ + "cpe:2.3:a:crmperks:integration_for_woocommerce_and_zoho_crm\\,_books\\,_invoice\\,_inventory\\,_bigin:*:*:*:*:*:*:*:*" + ], + "woocommerce": [ + "cpe:2.3:a:woocommerce:woocommerce:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:woothemes:woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-abandoned-cart": [ + "cpe:2.3:a:tychesoftwares:abandoned_cart_lite_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-ajax-filters": [ + "cpe:2.3:a:berocket:advanced_ajax_product_filters:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-amazon-affiliates-light-version": [ + "cpe:2.3:a:wzone_project:wzone:*:*:*:*:lite:wordpress:*:*" + ], + "woocommerce-catalog-enquiry": [ + "cpe:2.3:a:multivendorx:product_catalog_mode_for_woocommerce:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wc-marketplace:wc_catalog_enquiry:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-currency-switcher": [ + "cpe:2.3:a:pluginus:fox_-_currency_switcher_professional_for_woocommerce:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:pluginus:woocommerce_currency_switcher:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-cvr-payment-gateway": [ + "cpe:2.3:a:yanco:woocommerce_cvr_payment_gateway:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-delivery-notes": [ + "cpe:2.3:a:tychesoftwares:print_invoice_\\\u0026_delivery_notes_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-exporter": [ + "cpe:2.3:a:visser:store_exporter_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-for-japan": [ + "cpe:2.3:a:artisanworkshop:japanized_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-gateway-paypal-express-checkout": [ + "cpe:2.3:a:woocommerce:paypal_checkout_payment_gateway:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-gateway-stripe": [ + "cpe:2.3:a:woocommerce:stripe_payment_gateway:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-jetpack": [ + "cpe:2.3:a:booster:booster_for_woocommerce:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:booster:booster_for_woocommerce:*:*:*:*:elite:wordpress:*:*" + ], + "woocommerce-menu-extension": [ + "cpe:2.3:a:augustinfotech:woocommerce_menu_extension:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-mercadopago": [ + "cpe:2.3:a:mercadopago:mercado_pago_payments_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-multi-currency": [ + "cpe:2.3:a:villatheme:woocommerce_multi_currency:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-payments": [ + "cpe:2.3:a:automattic:woopayments:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-pdf-invoices-packing-slips": [ + "cpe:2.3:a:wpovernight:woocommerce_pdf_invoices\\\u0026_packing_slips:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-product-addon": [ + "cpe:2.3:a:najeebmedia:ppom_for_woocommerce:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:themeisle:product_addons_\\\u0026_fields_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-product-importer": [ + "cpe:2.3:a:visser:woocommerce_-_product_importer:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-product-stock-alert": [ + "cpe:2.3:a:multivendorx:product_stock_manager_\\\u0026_notifier_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-products-designer": [ + "cpe:2.3:a:orion:woocommerce_products_designer:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-products-filter": [ + "cpe:2.3:a:pluginus:husky_-_products_filter_professional_for_woocommerce:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:pluginus:woocommerce_products_filter:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-products-slider": [ + "cpe:2.3:a:pickplugins:product_slider_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-square": [ + "cpe:2.3:a:automattic:woocommerce_square:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-stock-manager": [ + "cpe:2.3:a:storeapps:stock_manager_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-store-toolkit": [ + "cpe:2.3:a:visser:store_toolkit_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "woocommerce-wholesale-prices": [ + "cpe:2.3:a:rymera:wholesale_suite:*:*:*:*:*:wordpress:*:*" + ], + "woodiscuz-woocommerce-comments": [ + "cpe:2.3:a:gvectors:woodiscuz_-_woocommerce_comments:*:*:*:*:*:wordpress:*:*" + ], + "wooemailreport": [ + "cpe:2.3:a:eggemplo:woocommerce_email_report:*:*:*:*:*:wordpress:*:*" + ], + "wooframework-tweaks": [ + "cpe:2.3:a:woocommerce:wooframework_tweaks:*:*:*:*:*:wordpress:*:*" + ], + "woolentor-addons": [ + "cpe:2.3:a:hasthemes:woolentor_-_woocommerce_elementor_addons_\\+_builder:*:*:*:*:*:wordpress:*:*" + ], + "woosidebars": [ + "cpe:2.3:a:woocommerce:woosidebars:*:*:*:*:*:wordpress:*:*" + ], + "woostify-sites-library": [ + "cpe:2.3:a:wootsify:sites_library:*:*:*:*:*:wordpress:*:*" + ], + "woosupply": [ + "cpe:2.3:a:longwatchstudio:woosupply:*:*:*:*:*:wordpress:*:*" + ], + "wooswipe": [ + "cpe:2.3:a:thriveweb:wooswipe_woocommerce_gallery:*:*:*:*:*:wordpress:*:*" + ], + "woovip": [ + "cpe:2.3:a:longwatchstudio:woovip:*:*:*:*:*:wordpress:*:*" + ], + "woovirtualwallet": [ + "cpe:2.3:a:longwatchstudio:woovirtualwallet:*:*:*:*:*:wordpress:*:*" + ], + "word-balloon": [ + "cpe:2.3:a:back2nature:word_balloon:*:*:*:*:*:wordpress:*:*" + ], + "wordapp": [ + "cpe:2.3:a:wordapp:wordapp:*:*:*:*:*:wordpress:*:*" + ], + "wordfence": [ + "cpe:2.3:a:wordfence:wordfence_security:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wordfence_security_project:wordfence_security:*:*:*:*:*:wordpress:*:*" + ], + "wordlift": [ + "cpe:2.3:a:wordlift:wordlift:*:*:*:*:*:wordpress:*:*" + ], + "wordpress-backup-to-dropbox": [ + "cpe:2.3:a:wordpress_backup_to_dropbox_project:wordpress_backup_to_dropbox:*:*:*:*:*:wordpress:*:*" + ], + "wordpress-database-reset": [ + "cpe:2.3:a:webfactoryltd:wp_database_reset:*:*:*:*:*:wordpress:*:*" + ], + "wordpress-easy-paypal-payment-or-donation-accept-plugin": [ + "cpe:2.3:a:tipsandtricks-hq:easy_accept_payments_for_paypal:*:*:*:*:*:wordpress:*:*" + ], + "wordpress-feed-statistics": [ + "cpe:2.3:a:feed_statistics_project:feed_statistics:*:*:*:*:*:wordpress:*:*" + ], + "wordpress-flash-uploader": [ + "cpe:2.3:a:tinywebgallery:wordpress_flash_uploader:*:*:*:*:*:wordpress:*:*" + ], + "wordpress-form-manager": [ + "cpe:2.3:a:form_manager_project:form_manager:*:*:*:*:*:wordpress:*:*" + ], + "wordpress-gallery-plugin": [ + "cpe:2.3:a:gallery_project:gallery:*:*:*:*:*:wordpress:*:*" + ], + "wordpress-meta-robots": [ + "cpe:2.3:a:typomedia:wordpress_meta_robots:*:*:*:*:*:wordpress:*:*" + ], + "wordpress-mobile-pack": [ + "cpe:2.3:a:wpmobilepack:wordpress_mobile_pack:*:*:*:*:*:wordpress:*:*" + ], + "wordpress-nextgen-galleryview": [ + "cpe:2.3:a:wordpress_nextgen_galleryview_project:wordpress_nextgen_galleryview:*:*:*:*:*:wordpress:*:*" + ], + "wordpress-ping-optimizer": [ + "cpe:2.3:a:wordpress_ping_optimizer_project:wordpress_ping_optimizer:*:*:*:*:*:wordpress:*:*" + ], + "wordpress-popular-posts": [ + "cpe:2.3:a:wordpress_popular_posts_project:wordpress_popular_posts:*:*:*:*:*:wordpress:*:*" + ], + "wordpress-popup": [ + "cpe:2.3:a:incsub:hustle:*:*:*:*:*:wordpress:*:*" + ], + "wordpress-seo": [ + "cpe:2.3:a:yoast:wordpress_seo:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:yoast:yoast_seo:*:*:*:*:*:wordpress:*:*" + ], + "wordpress-simple-paypal-shopping-cart": [ + "cpe:2.3:a:tipsandtricks-hq:wordpress_simple_paypal_shopping_cart:*:*:*:*:*:wordpress:*:*" + ], + "wordpress-social-login": [ + "cpe:2.3:a:wordpress_social_login_project:wordpress_social_login:*:*:*:*:*:wordpress:*:*" + ], + "wordpress-toolbar": [ + "cpe:2.3:a:abhinavsingh:wordpress_toolbar:*:*:*:*:*:*:wordpress:*" + ], + "wordpress-tooltips": [ + "cpe:2.3:a:tooltips:wordpress_tooltips:*:*:*:*:free:wordpress:*:*" + ], + "wordpress-users": [ + "cpe:2.3:a:jonathonkemp:wordpress_users:*:*:*:*:*:wordpress:*:*" + ], + "wow-moodboard-lite": [ + "cpe:2.3:a:wownmedia:wow_moodboard:*:*:*:*:lite:wordpress:*:*" + ], + "wp-2fa": [ + "cpe:2.3:a:melapress:wp_2fa:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpwhitesecurity:wp_2fa:*:*:*:*:*:wordpress:*:*" + ], + "wp-404-auto-redirect-to-similar-post": [ + "cpe:2.3:a:hwk:wp_404_auto_redirect_to_similar_post:*:*:*:*:*:wordpress:*:*" + ], + "wp-academic-people": [ + "cpe:2.3:a:wp_academic_people_list_project:wp_academic_people_list:*:*:*:*:*:wordpress:*:*" + ], + "wp-admin-logo-changer": [ + "cpe:2.3:a:wp_admin_logo_changer_project:wp_admin_logo_changer:*:*:*:*:*:wordpress:*:*" + ], + "wp-advanced-search": [ + "cpe:2.3:a:wp-advanced-search_project:wp-advanced-search:*:*:*:*:*:wordpress:*:*" + ], + "wp-airbnb-review-slider": [ + "cpe:2.3:a:ljapps:wp_airbnb_review_slider:*:*:*:*:*:wordpress:*:*" + ], + "wp-all-export": [ + "cpe:2.3:a:soflyy:export_any_wordpress_data_to_xml\\/csv:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:soflyy:wp_all_export:*:*:*:*:pro:wordpress:*:*" + ], + "wp-all-import": [ + "cpe:2.3:a:soflyy:import_any_wordpress_data_to_xml\\/csv:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:soflyy:wp_all_import:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpallimport:wp_all_import:*:*:*:*:*:wordpress:*:*" + ], + "wp-amazon-shop": [ + "cpe:2.3:a:amadercode:dropshipping_\\\u0026_affiliation_with_amazon:*:*:*:*:*:wordpress:*:*" + ], + "wp-analytify": [ + "cpe:2.3:a:analytify:analytify_-_google_analytics_dashboard:*:*:*:*:*:wordpress:*:*" + ], + "wp-appbox": [ + "cpe:2.3:a:wp-appbox_project:wp-appbox:*:*:*:*:*:wordpress:*:*" + ], + "wp-asset-clean-up": [ + "cpe:2.3:a:asset_cleanup\\:_page_speed_booster_project:asset_cleanup\\:_page_speed_booster:*:*:*:*:*:wordpress:*:*" + ], + "wp-athletics": [ + "cpe:2.3:a:wp_athletics_project:wp_athletics:*:*:*:*:*:wordpress:*:*" + ], + "wp-attachment-export": [ + "cpe:2.3:a:wp_attachment_export_project:wp_attachment_export:*:*:*:*:*:wordpress:*:*" + ], + "wp-attachments": [ + "cpe:2.3:a:marcomilesi:wp_attachments:*:*:*:*:*:wordpress:*:*" + ], + "wp-auto-affiliate-links": [ + "cpe:2.3:a:autoaffiliatelinks:auto_affiliate_links:*:*:*:*:*:wordpress:*:*" + ], + "wp-backgrounds-lite": [ + "cpe:2.3:a:inoplugs:wp-backgrounds_lite:*:*:*:*:*:wordpress:*:*" + ], + "wp-baidu-submit": [ + "cpe:2.3:a:wp_baidu_submit_project:wp_baidu_submit:*:*:*:*:*:wordpress:*:*" + ], + "wp-ban": [ + "cpe:2.3:a:wp-ban_project:wp-ban:*:*:*:*:*:wordpress:*:*" + ], + "wp-best-quiz": [ + "cpe:2.3:a:subina:wp_best_quiz:*:*:*:*:*:wordpress:*:*" + ], + "wp-better-permalinks": [ + "cpe:2.3:a:wp_better_permalinks_project:wp_better_permalinks:*:*:*:*:*:wordpress:*:*" + ], + "wp-bitly": [ + "cpe:2.3:a:bitly:bitly:*:*:*:*:*:wordpress:*:*" + ], + "wp-blogs-planetarium": [ + "cpe:2.3:a:wp-blogs-planetarium_project:wp-blogs-planetarium:*:*:*:*:*:wordpress:*:*" + ], + "wp-board": [ + "cpe:2.3:a:wp-board_project:wp-board:*:*:*:*:*:wordpress:*:*" + ], + "wp-booking-system": [ + "cpe:2.3:a:wpbookingsystem:wp_booking_system:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpbookingsystem:wp_booking_system:*:*:*:*:free:wordpress:*:*", + "cpe:2.3:a:wpbookingsystem:wp_booking_system:*:*:*:*:premium:wordpress:*:*" + ], + "wp-booklet": [ + "cpe:2.3:a:binarystash:wp_booklet:*:*:*:*:*:wordpress:*:*" + ], + "wp-books-gallery": [ + "cpe:2.3:a:hmplugin:wordpress_books_gallery:*:*:*:*:*:wordpress:*:*" + ], + "wp-born-babies": [ + "cpe:2.3:a:wp_born_babies_project:wp_born_babies:*:*:*:*:*:wordpress:*:*" + ], + "wp-browser-update": [ + "cpe:2.3:a:browserupdate:wp_browserupdate:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:marcosteinbrecher:wp_browserupdate:*:*:*:*:*:wordpress:*:*" + ], + "wp-business-intelligence-lite": [ + "cpe:2.3:a:wpbusinessintelligence:wp_business_intelligence:*:*:*:*:lite:wordpress:*:*" + ], + "wp-cachecom": [ + "cpe:2.3:a:kenthhagstrom:wp-cachecom:*:*:*:*:*:wordpress:*:*" + ], + "wp-calendar": [ + "cpe:2.3:a:wp_calendar_project:wp_calendar:*:*:*:*:*:wordpress:*:*" + ], + "wp-captcha": [ + "cpe:2.3:a:devnath_verma:wp_captcha:*:*:*:*:*:wordpress:*:*" + ], + "wp-carousel-free": [ + "cpe:2.3:a:techearty:carousel\\,_slider\\,_gallery_by_wp_carousel:*:*:*:*:*:wordpress:*:*" + ], + "wp-catalogue": [ + "cpe:2.3:a:maevelander:wp_catalogue:*:*:*:*:*:wordpress:*:*" + ], + "wp-categories-widget": [ + "cpe:2.3:a:wp-experts:wp-categories-widget:*:*:*:*:*:wordpress:*:*" + ], + "wp-category-meta": [ + "cpe:2.3:a:randyhoyt:category_meta:*:*:*:*:*:wordpress:*:*" + ], + "wp-category-posts-list": [ + "cpe:2.3:a:swashata:wp_category_post_list_widget:*:*:*:*:*:wordpress:*:*" + ], + "wp-central": [ + "cpe:2.3:a:wpcentral:wpcentral:*:*:*:*:*:wordpress:*:*" + ], + "wp-cerber": [ + "cpe:2.3:a:cerber:wp_cerber_security\\,_anti-spam_\\\u0026_malware_scan:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpcerber:cerber_security_antispam_\\\u0026_malware_scan:*:*:*:*:*:wordpress:*:*" + ], + "wp-cfm": [ + "cpe:2.3:a:forumone:wp-cfm:*:*:*:*:*:wordpress:*:*" + ], + "wp-championship": [ + "cpe:2.3:a:wp-championship_project:wp-championship:*:*:*:*:*:wordpress:*:*" + ], + "wp-charts": [ + "cpe:2.3:a:wpartisan:wordpress_charts:*:*:*:*:*:wordpress:*:*" + ], + "wp-chgfontsize": [ + "cpe:2.3:a:wp-chgfontsize_project:wp-chgfontsize:*:*:*:*:*:wordpress:*:*" + ], + "wp-cirrus": [ + "cpe:2.3:a:wp-cirrus_project:wp-cirrus:*:*:*:*:*:wordpress:*:*" + ], + "wp-clean-up": [ + "cpe:2.3:a:wp_clean_up_project:wp_clean_up:*:*:*:*:*:wordpress:*:*" + ], + "wp-cleanfix": [ + "cpe:2.3:a:undolog:wp_cleanfix:*:*:*:*:*:wordpress:*:*" + ], + "wp-client-logo-carousel": [ + "cpe:2.3:a:client_logo_carousel_project:client_logo_carousel:*:*:*:*:*:wordpress:*:*" + ], + "wp-client-reports": [ + "cpe:2.3:a:switchwp:wp_client_reports:*:*:*:*:*:wordpress:*:*" + ], + "wp-clone-by-wp-academy": [ + "cpe:2.3:a:backupbliss:clone:*:*:*:*:*:wordpress:*:*" + ], + "wp-club-manager": [ + "cpe:2.3:a:wpclubmanager:wp_club_manager:*:*:*:*:*:wordpress:*:*" + ], + "wp-code-highlightjs": [ + "cpe:2.3:a:wp-code-highlightjs_project:wp-code-highlightjs:*:*:*:*:*:wordpress:*:*" + ], + "wp-coder": [ + "cpe:2.3:a:wow-company:wp_coder:*:*:*:*:*:wordpress:*:*" + ], + "wp-comment-fields": [ + "cpe:2.3:a:najeebmedia:wordpress_comments_fields:*:*:*:*:*:wordpress:*:*" + ], + "wp-commentnavi": [ + "cpe:2.3:a:wp-commentnavi_project:wp-commentnavi:*:*:*:*:*:wordpress:*:*" + ], + "wp-concours": [ + "cpe:2.3:a:olyos:wp-concours:*:*:*:*:*:wordpress:*:*" + ], + "wp-consultant": [ + "cpe:2.3:a:wp_consultant_project:wp_consultant:*:*:-:*:-:wordpress:*:*" + ], + "wp-contact-slider": [ + "cpe:2.3:a:wpexperts:wp_contact_slider:*:*:*:*:*:wordpress:*:*" + ], + "wp-contacts-manager": [ + "cpe:2.3:a:labarta:wp_contacts_manager:*:*:*:*:*:wordpress:*:*" + ], + "wp-content-copy-protector": [ + "cpe:2.3:a:wp-buy:wp_content_copy_protection_\\\u0026_no_right_click:*:*:*:*:*:wordpress:*:*" + ], + "wp-content-filter": [ + "cpe:2.3:a:wp_content_filter_-_censor_all_offensive_content_from_your_site_project:wp_content_filter_-_censor_all_offensive_content_from_your_site:*:*:*:*:*:wordpress:*:*" + ], + "wp-cookie-user-info": [ + "cpe:2.3:a:accesspressthemes:wp_cookie_user_info:*:*:*:*:*:wordpress:*:*" + ], + "wp-copyprotect": [ + "cpe:2.3:a:wp-copyprotect_project:wp-copyprotect:*:*:*:*:*:wordpress:*:*" + ], + "wp-copysafe-web": [ + "cpe:2.3:a:artistscope:copysafe_web_protection:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wp-ecommerce:easy_wp_smtp:*:*:*:*:*:wordpress:*:*" + ], + "wp-courses": [ + "cpe:2.3:a:stratospheredigital:wp_courses_lms:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpcoursesplugin:wp-courses:*:*:*:*:*:wordpress:*:*" + ], + "wp-crm": [ + "cpe:2.3:a:usabilitydynamics:wp-crm:*:*:*:*:*:wordpress:*:*" + ], + "wp-crowdfunding": [ + "cpe:2.3:a:themeum:wp_crowdfunding:*:*:*:*:*:wordpress:*:*" + ], + "wp-csv": [ + "cpe:2.3:a:cpkwebsolutions:wp_csv:*:*:*:*:*:wordpress:*:*" + ], + "wp-csv-exporter": [ + "cpe:2.3:a:kigurumi:csv_exporter:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wp_csv_exporter_project:wp_csv_exporter:*:*:*:*:*:wordpress:*:*" + ], + "wp-custom-admin-interface": [ + "cpe:2.3:a:wp_custom_admin_interface_project:wp_custom_admin_interface:*:*:*:*:*:*:*:*" + ], + "wp-custom-author-url": [ + "cpe:2.3:a:wp_custom_author_url_project:wp_custom_author_url:*:*:*:*:*:wordpress:*:*" + ], + "wp-custom-body-class": [ + "cpe:2.3:a:custom_body_class_project:custom_body_class:*:*:*:*:*:wordpress:*:*" + ], + "wp-custom-cursors": [ + "cpe:2.3:a:hamidrezasepehr:wp_custom_cursors_\\|_wordpress_cursor_plugin:*:*:*:*:*:wordpress:*:*" + ], + "wp-custom-fields-search": [ + "cpe:2.3:a:warhammer:wp_custom_fields_search:*:*:*:*:*:wordpress:*:*" + ], + "wp-custom-login-page": [ + "cpe:2.3:a:custom_login_page_project:custom_login_page:*:*:*:*:*:wordpress:*:*" + ], + "wp-custom-post-template": [ + "cpe:2.3:a:dotsquares:wp_custom_post_template:*:*:*:*:*:wordpress:*:*" + ], + "wp-custom-widget-area": [ + "cpe:2.3:a:kishorkhambu:wp_custom_widget_area:*:*:*:*:*:wordpress:*:*" + ], + "wp-customer-reviews": [ + "cpe:2.3:a:gowebsolutions:wp_customer_reviews:*:*:*:*:*:wordpress:*:*" + ], + "wp-d3": [ + "cpe:2.3:a:wp-d3_project:wp-d3:*:*:*:*:*:wordpress:*:*" + ], + "wp-dark-mode": [ + "cpe:2.3:a:wppool:wp_dark_mode:*:*:*:*:*:wordpress:*:*" + ], + "wp-data-access": [ + "cpe:2.3:a:wpdataaccess:wp_data_access:*:*:*:*:*:wordpress:*:*" + ], + "wp-database-backup": [ + "cpe:2.3:a:wpseeds:wp_database_backup:*:*:*:*:*:wordpress:*:*" + ], + "wp-db-backup": [ + "cpe:2.3:a:deliciousbrains:database_backup:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wp-db-backup_project:wp-db-backup:*:*:*:*:*:wordpress:*:*" + ], + "wp-dbmanager": [ + "cpe:2.3:a:wp-dbmanager_project:wp-dbmanager:*:*:*:*:*:wordpress:*:*" + ], + "wp-debugging": [ + "cpe:2.3:a:wp_debugging_project:wp_debugging:*:*:*:*:*:wordpress:*:*" + ], + "wp-design-maps-places": [ + "cpe:2.3:a:amazingweb:wp-design-maps-places:*:*:*:*:*:wordpress:*:*" + ], + "wp-discord-invite": [ + "cpe:2.3:a:sarveshmrao:wp_discord_invite:*:*:*:*:*:wordpress:*:*" + ], + "wp-display-users": [ + "cpe:2.3:a:display_users_project:display_users:*:*:*:*:*:wordpress:*:*" + ], + "wp-domain-redirect": [ + "cpe:2.3:a:wp_domain_redirect_project:wp_domain_redirect:*:*:*:*:*:wordpress:*:*" + ], + "wp-donate": [ + "cpe:2.3:a:wp_donate_project:wp_donate:*:*:*:*:*:wordpress:*:*" + ], + "wp-downgrade": [ + "cpe:2.3:a:wp_downgrade_project:wp_downgrade:*:*:*:*:*:wordpress:*:*" + ], + "wp-downloadmanager": [ + "cpe:2.3:a:wp-downloadmanager_project:wp-downloadmanager:*:*:*:*:*:wordpress:*:*" + ], + "wp-ds-blog-map": [ + "cpe:2.3:a:wp_ds_blog_map_project:wp_ds_blog_map:*:*:*:*:*:wordpress:*:*" + ], + "wp-dummy-content-generator": [ + "cpe:2.3:a:wp_dummy_content_generator_project:wp_dummy_content_generator:*:*:*:*:*:wordpress:*:*" + ], + "wp-duplicate-page": [ + "cpe:2.3:a:ninjateam:wp_duplicate_page:*:*:*:*:*:wordpress:*:*" + ], + "wp-easy-pay": [ + "cpe:2.3:a:wpeasypay:wp_easypay:*:*:*:*:*:wordpress:*:*" + ], + "wp-easycart": [ + "cpe:2.3:a:wpeasycart:wp_easycart:*:*:*:*:*:wordpress:*:*" + ], + "wp-ecommerce-paypal": [ + "cpe:2.3:a:wpplugin:easy_paypal_buy_now_button:*:*:*:*:*:wordpress:*:*" + ], + "wp-edit-menu": [ + "cpe:2.3:a:wp_edit_menu_project:wp_edit_menu:*:*:*:*:*:wordpress:*:*" + ], + "wp-edit-username": [ + "cpe:2.3:a:sajjadhsagor:wp_edit_username:*:*:*:*:*:wordpress:*:*" + ], + "wp-editor": [ + "cpe:2.3:a:benjaminrojas:wp_editor:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wp_editor_project:wp_editor:*:*:*:*:*:*:*:*" + ], + "wp-editormd": [ + "cpe:2.3:a:iiong:wp_editor.md:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wp_editor.md_project:wp_editor.md:*:*:*:*:*:wordpress:*:*" + ], + "wp-education": [ + "cpe:2.3:a:hasthemes:wp_education:*:*:*:*:*:wordpress:*:*" + ], + "wp-email": [ + "cpe:2.3:a:wp-email_project:wp-email:*:*:*:*:*:wordpress:*:*" + ], + "wp-email-capture": [ + "cpe:2.3:a:winwar:wp_email_capture:*:*:*:*:*:wordpress:*:*" + ], + "wp-email-users": [ + "cpe:2.3:a:techspawn:wp-email-users:*:*:*:*:*:wordpress:*:*" + ], + "wp-embed-facebook": [ + "cpe:2.3:a:wpembedfb:magic_embeds:*:*:*:*:*:wordpress:*:*" + ], + "wp-emoji-one": [ + "cpe:2.3:a:monchito:wp_emoji_one:*:*:*:*:*:wordpress:*:*" + ], + "wp-event-manager": [ + "cpe:2.3:a:wp-eventmanager:wp_event_manager:*:*:*:*:*:wordpress:*:*" + ], + "wp-event-solution": [ + "cpe:2.3:a:themewinter:eventin:*:*:*:*:*:wordpress:*:*" + ], + "wp-events-manager": [ + "cpe:2.3:a:thimpress:wp_events_manager:*:*:*:*:*:wordpress:*:*" + ], + "wp-expand-tabs-free": [ + "cpe:2.3:a:shapedplugin:wp_tabs:*:*:*:*:*:wordpress:*:*" + ], + "wp-express-checkout": [ + "cpe:2.3:a:tipsandtricks-hq:wp_express_checkout:*:*:*:*:*:wordpress:*:*" + ], + "wp-extra": [ + "cpe:2.3:a:wpvnteam:wp_extra:*:*:*:*:*:wordpress:*:*" + ], + "wp-extra-file-types": [ + "cpe:2.3:a:wp_extra_file_types_project:wp_extra_file_types:*:*:*:*:*:wordpress:*:*" + ], + "wp-facebook-feed": [ + "cpe:2.3:a:arrowplugins:the_awesome_feed:*:*:*:*:*:wordpress:*:*" + ], + "wp-facebook-reviews": [ + "cpe:2.3:a:ljapps:wp_review_slider:*:*:*:*:*:wordpress:*:*" + ], + "wp-fade-in-text-news": [ + "cpe:2.3:a:gopiplus:wp_fade_in_text_news:*:*:*:*:*:wordpress:*:*" + ], + "wp-fastest-cache": [ + "cpe:2.3:a:wpfastestcache:wp_fastest_cache:*:*:*:*:*:wordpress:*:*" + ], + "wp-favorite-posts": [ + "cpe:2.3:a:wp_favorite_posts_project:wp_favorite_posts:*:*:*:*:*:wordpress:*:*" + ], + "wp-fb-autoconnect": [ + "cpe:2.3:a:wp_social_autoconnect_project:wp_social_autoconnect:*:*:*:*:*:wordpress:*:*" + ], + "wp-fevents-book": [ + "cpe:2.3:a:wp_fevents_book_project:wp_fevents_book:*:*:*:*:*:wordpress:*:*" + ], + "wp-file-checker": [ + "cpe:2.3:a:sc_filechecker_project:sc_filechecker:*:*:*:*:*:wordpress:*:*" + ], + "wp-file-get-contents": [ + "cpe:2.3:a:surniaulula:jsm_file_get_contents\\(\\)_shortcode:*:*:*:*:*:wordpress:*:*" + ], + "wp-file-manager": [ + "cpe:2.3:a:webdesi9:file_manager:*:*:*:*:*:wordpress:*:*" + ], + "wp-file-upload": [ + "cpe:2.3:a:iptanus:wordpress_file_upload:*:*:*:*:*:wordpress:*:*" + ], + "wp-filebase": [ + "cpe:2.3:a:wp-filebase_download_manager_project:wp-filebase_download_manager:*:*:*:*:*:wordpress:*:*" + ], + "wp-film-studio": [ + "cpe:2.3:a:hasthemes:wp_film_studio:*:*:*:*:*:wordpress:*:*" + ], + "wp-flipclock": [ + "cpe:2.3:a:winwar:wp_flipclock:*:*:*:*:*:wordpress:*:*" + ], + "wp-floating-menu": [ + "cpe:2.3:a:accesspressthemes:wp_floating_menu:*:*:*:*:*:wordpress:*:*" + ], + "wp-flybox": [ + "cpe:2.3:a:wp-flybox_project:wp-flybox:*:*:*:*:*:wordpress:*:*" + ], + "wp-font-awesome": [ + "cpe:2.3:a:wp_font_awesome_project:wp_font_awesome:*:*:*:*:*:wordpress:*:*" + ], + "wp-food-manager": [ + "cpe:2.3:a:wpfoodmanager:wp_food_manager:*:*:*:*:*:wordpress:*:*" + ], + "wp-football": [ + "cpe:2.3:a:wp-football_project:wp-football:*:*:*:*:*:*:*:*" + ], + "wp-forms-puzzle-captcha": [ + "cpe:2.3:a:nitinrathod:wp_forms_puzzle_captcha:*:*:*:*:*:wordpress:*:*" + ], + "wp-fountain": [ + "cpe:2.3:a:wp_fountain_project:wp_fountain:*:*:*:*:*:wordpress:*:*" + ], + "wp-front-end-profile": [ + "cpe:2.3:a:wp_front_end_profile_project:wp_front_end_profile:*:*:*:*:*:wordpress:*:*" + ], + "wp-full-auto-tags-manager": [ + "cpe:2.3:a:guillemantdavid:full_auto_tags_manager:*:*:*:*:*:wordpress:*:*" + ], + "wp-full-stripe-free": [ + "cpe:2.3:a:paymentsplugin:wp_full_stripe_free:*:*:*:*:*:wordpress:*:*" + ], + "wp-fullcalendar": [ + "cpe:2.3:a:pixelite:wp_fullcalendar:*:*:*:*:*:wordpress:*:*" + ], + "wp-fundraising-donation": [ + "cpe:2.3:a:wpmet:wp_fundraising_donation_and_crowdfunding_platform:*:*:*:*:*:wordpress:*:*" + ], + "wp-gallery-metabox": [ + "cpe:2.3:a:wp_gallery_metabox_project:wp_gallery_metabox:*:*:*:*:*:wordpress:*:*" + ], + "wp-gdpr-compliance": [ + "cpe:2.3:a:cookieinformation:wp-gdpr-compliance:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:van-ons:wp-gdpr-compliance:*:*:*:*:*:wordpress:*:*" + ], + "wp-gdpr-core": [ + "cpe:2.3:a:appsaloon:wp-gdpr:*:*:*:*:*:wordpress:*:*" + ], + "wp-githuber-md": [ + "cpe:2.3:a:terryl:wp_githuber_md:*:*:*:*:*:wordpress:*:*" + ], + "wp-glossary": [ + "cpe:2.3:a:wp_glossary_project:wp_glossary:*:*:*:*:*:wordpress:*:*" + ], + "wp-gmappity-easy-google-maps": [ + "cpe:2.3:a:matthewschwartz:google_maps_made_simple:*:*:*:*:*:wordpress:*:*" + ], + "wp-google-fonts": [ + "cpe:2.3:a:wp_google_fonts_project:wp_google_fonts:*:*:*:*:*:*:*:*" + ], + "wp-google-map-plugin": [ + "cpe:2.3:a:flippercode:wp_google_map:*:*:*:*:*:wordpress:*:*" + ], + "wp-google-maps": [ + "cpe:2.3:a:codecabin:wp_go_maps:*:*:*:*:basic:wordpress:*:*" + ], + "wp-google-my-business-auto-publish": [ + "cpe:2.3:a:auto_publish_for_google_my_business_project:auto_publish_for_google_my_business:*:*:*:*:*:wordpress:*:*" + ], + "wp-google-places-review-slider": [ + "cpe:2.3:a:ljapps:wp_google_review_slider:*:*:*:*:*:wordpress:*:*" + ], + "wp-google-tag-manager": [ + "cpe:2.3:a:conlabz:wp_google_tag_manager:*:*:*:*:*:wordpress:*:*" + ], + "wp-gpx-maps": [ + "cpe:2.3:a:devfarm:wp_gpx_maps:*:*:*:*:*:wordpress:*:*" + ], + "wp-graphql": [ + "cpe:2.3:a:wpengine:wpgraphql:*:*:*:*:*:wordpress:*:*" + ], + "wp-header-images": [ + "cpe:2.3:a:androidbubbles:wp_header_images:*:*:*:*:*:wordpress:*:*" + ], + "wp-helper-lite": [ + "cpe:2.3:a:matbao:wp_helper_premium:*:*:*:*:*:wordpress:*:*" + ], + "wp-hide": [ + "cpe:2.3:a:weberge:wp_hide:*:*:*:*:*:wordpress:*:*" + ], + "wp-hide-pages": [ + "cpe:2.3:a:nxsn:wp_hide_pages:*:*:*:*:*:wordpress:*:*" + ], + "wp-home-page-menu": [ + "cpe:2.3:a:wp_home_page_menu_project:wp_home_page_menu:*:*:*:*:*:wordpress:*:*" + ], + "wp-hotel-booking": [ + "cpe:2.3:a:thimpress:wp_hotel_booking:*:*:*:*:*:wordpress:*:*" + ], + "wp-html-author-bio-by-ahmad-awais": [ + "cpe:2.3:a:wp_html_author_bio_project:wp_html_author_bio:*:*:*:*:*:wordpress:*:*" + ], + "wp-html-mail": [ + "cpe:2.3:a:codemiq:wordpress_email_template_designer:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:codemiq:wp_html_mail:*:*:*:*:*:wordpress:*:*" + ], + "wp-html-sitemap": [ + "cpe:2.3:a:wp-html-sitemap_project:wp-html-sitemap:*:*:*:*:*:*:*:*" + ], + "wp-htpasswd": [ + "cpe:2.3:a:wp_htpasswd_project:wp_htpasswd:*:*:*:*:*:wordpress:*:*" + ], + "wp-humanstxt": [ + "cpe:2.3:a:wp_humans.txt_project:wp_humans.txt:*:*:*:*:*:wordpress:*:*" + ], + "wp-ical-availability": [ + "cpe:2.3:a:wpicalavailability:wp_ical_availability:*:*:*:*:*:wordpress:*:*" + ], + "wp-icommerce": [ + "cpe:2.3:a:solvercircle:wp_icommerce:*:*:*:*:*:wordpress:*:*" + ], + "wp-image-carousel": [ + "cpe:2.3:a:itzoovim:wp_image_carousel:*:*:*:*:*:wordpress:*:*" + ], + "wp-image-slideshow": [ + "cpe:2.3:a:gopiplus:wp_image_slideshow:*:*:*:*:*:wordpress:*:*" + ], + "wp-image-zoooom": [ + "cpe:2.3:a:silkypress:wp_image_zoom:*:*:*:*:*:wordpress:*:*" + ], + "wp-imageflow2": [ + "cpe:2.3:a:spiffyplugins:wp_flow_plus:*:*:*:*:*:wordpress:*:*" + ], + "wp-import-export-lite": [ + "cpe:2.3:a:vjinfotech:wp_import_export_lite:*:*:*:*:*:wordpress:*:*" + ], + "wp-inject": [ + "cpe:2.3:a:wpscoop:imageinject:*:*:*:*:*:wordpress:*:*" + ], + "wp-insert": [ + "cpe:2.3:a:smartlogix:wp-insert:*:*:*:*:*:wordpress:*:*" + ], + "wp-instance-rename": [ + "cpe:2.3:a:rename_project:rename:*:*:*:*:*:wordpress:*:*" + ], + "wp-insurance": [ + "cpe:2.3:a:hasthemes:wp_insurance:*:*:*:*:*:wordpress:*:*" + ], + "wp-inventory-manager": [ + "cpe:2.3:a:wpinventory:wp_inventory_manager:*:*:*:*:*:wordpress:*:*" + ], + "wp-invoice": [ + "cpe:2.3:a:usabilitydynamics:wp-invoice:*:*:*:*:*:wordpress:*:*" + ], + "wp-job-openings": [ + "cpe:2.3:a:awsm:wp_job_openings:*:*:*:*:*:wordpress:*:*" + ], + "wp-job-portal": [ + "cpe:2.3:a:wpjobportal:wp_job_portal:*:*:*:*:*:wordpress:*:*" + ], + "wp-jobs": [ + "cpe:2.3:a:intensewp:wp_jobs:*:*:*:*:*:wordpress:*:*" + ], + "wp-js": [ + "cpe:2.3:a:wp-js_project:wp-js:*:*:*:*:*:wordpress:*:*" + ], + "wp-knowledgebase": [ + "cpe:2.3:a:wpknowledgebase:wordpress_knowledge_base_\\\u0026_documentation_plugin:*:*:*:*:*:wordpress:*:*" + ], + "wp-latest-posts": [ + "cpe:2.3:a:joomunited:wp_latest_posts:*:*:*:*:*:wordpress:*:*" + ], + "wp-libre-form": [ + "cpe:2.3:a:wp_libre_form_project:wp_libre_form:*:*:*:*:*:wordpress:*:*" + ], + "wp-lightbox-2": [ + "cpe:2.3:a:syedbalkhi:wp_lightbox_2:*:*:*:*:*:wordpress:*:*" + ], + "wp-like-button": [ + "cpe:2.3:a:crudlab:wp_like_button:*:*:*:*:*:wordpress:*:*" + ], + "wp-limit-failed-login-attempts": [ + "cpe:2.3:a:wp-buy:login_protection_-_limit_failed_login_attempts:*:*:*:*:*:wordpress:*:*" + ], + "wp-limit-login-attempts": [ + "cpe:2.3:a:ciphercoin:wp_limit_login_attempts:*:*:*:*:*:wordpress:*:*" + ], + "wp-limits": [ + "cpe:2.3:a:wp_limits_project:wp_limits:*:*:*:*:*:wordpress:*:*" + ], + "wp-line-notify": [ + "cpe:2.3:a:simonchuang:wp_line_notify:*:*:*:*:*:wordpress:*:*" + ], + "wp-links-page": [ + "cpe:2.3:a:wplinkspage:wp_links_page:*:*:*:*:*:wordpress:*:*" + ], + "wp-lister-for-ebay": [ + "cpe:2.3:a:wplab:wp-lister_lite_for_ebay:*:*:*:*:*:wordpress:*:*" + ], + "wp-listings": [ + "cpe:2.3:a:agentevolution:impress_listings:*:*:*:*:*:wordpress:*:*" + ], + "wp-live-chat-software-for-wordpress": [ + "cpe:2.3:a:livechat:live_chat:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:livechat:livechat:*:*:*:*:*:wordpress:*:*" + ], + "wp-live-chat-support": [ + "cpe:2.3:a:3cx:live_chat:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:3cx:wp-live_chat:*:*:*:*:*:wordpress:*:*" + ], + "wp-login-security-and-history": [ + "cpe:2.3:a:clogica:wp_login_security_and_history:*:*:*:*:*:wordpress:*:*" + ], + "wp-logo-showcase": [ + "cpe:2.3:a:radiustheme:logo_slider_and_showcase:*:*:*:*:*:wordpress:*:*" + ], + "wp-mail": [ + "cpe:2.3:a:wp_mail_project:wp_mail:*:*:*:*:*:wordpress:*:*" + ], + "wp-mail-catcher": [ + "cpe:2.3:a:jamesward:wp_mail_catcher:*:*:*:*:*:wordpress:*:*" + ], + "wp-mail-log": [ + "cpe:2.3:a:wpvibes:wp_mail_log:*:*:*:*:*:wordpress:*:*" + ], + "wp-mail-logging": [ + "cpe:2.3:a:awesomemotive:wp_mail_logging:*:*:*:*:*:wordpress:*:*" + ], + "wp-mailster": [ + "cpe:2.3:a:wpmailster:wp_mailster:*:*:*:*:*:wordpress:*:*" + ], + "wp-mailto-links": [ + "cpe:2.3:a:ironikus:wp_mailto_links:*:*:*:*:*:wordpress:*:*" + ], + "wp-maintenance": [ + "cpe:2.3:a:wp_maintenance_project:wp_maintenance:*:*:*:*:*:wordpress:*:*" + ], + "wp-maintenance-mode": [ + "cpe:2.3:a:designmodo:wp_maintenance_mode:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:themeisle:lightstart:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:themeisle:wp_maintenance_mode_\\\u0026_coming_soon:*:*:*:*:*:wordpress:*:*" + ], + "wp-map-block": [ + "cpe:2.3:a:wp_map_block_project:wp_map_block:*:*:*:*:*:wordpress:*:*" + ], + "wp-mapit": [ + "cpe:2.3:a:chandnipatel:wp_mapit:*:*:*:*:*:wordpress:*:*" + ], + "wp-markdown-editor": [ + "cpe:2.3:a:wp_markdown_editor_project:wp_markdown_editor:*:*:*:*:*:wordpress:*:*" + ], + "wp-marketing-automations": [ + "cpe:2.3:a:funnelkit:funnelkit_automations:*:*:*:*:*:wordpress:*:*" + ], + "wp-media-cleaner": [ + "cpe:2.3:a:wp_media_cleaner_project:wp_media_cleaner:*:*:*:*:*:wordpress:*:*" + ], + "wp-media-library-categories": [ + "cpe:2.3:a:jeffrey-wp:media_library_categories:*:*:*:*:*:wordpress:*:*" + ], + "wp-members": [ + "cpe:2.3:a:wp-members_project:wp-members:*:*:*:*:*:wordpress:*:*" + ], + "wp-memory": [ + "cpe:2.3:a:wp-memory_project:wp-memory:*:*:*:*:*:wordpress:*:*" + ], + "wp-meta-and-date-remover": [ + "cpe:2.3:a:prasadkirpekar:wp_meta_and_date_remover:*:*:*:*:*:wordpress:*:*" + ], + "wp-meta-data-filter-and-taxonomy-filter": [ + "cpe:2.3:a:pluginus:wordpress_meta_data_and_taxonomies_filter:*:*:*:*:*:wordpress:*:*" + ], + "wp-meta-seo": [ + "cpe:2.3:a:joomunited:wp_meta_seo:*:*:*:*:*:wordpress:*:*" + ], + "wp-meteor": [ + "cpe:2.3:a:wp-meteor:wp_meteor:*:*:*:*:*:wordpress:*:*" + ], + "wp-migration-duplicator": [ + "cpe:2.3:a:webtoffee:backup_and_migration:*:*:*:*:*:wordpress:*:*" + ], + "wp-miniaudioplayer": [ + "cpe:2.3:a:mb.miniaudioplayer_project:mb.miniaudioplayer:*:*:*:*:*:wordpress:*:*" + ], + "wp-mpdf": [ + "cpe:2.3:a:wp-mpdf_project:wp-mpdf:*:*:*:*:*:wordpress:*:*" + ], + "wp-nested-pages": [ + "cpe:2.3:a:kylephillips:nested_pages:*:*:*:*:*:wordpress:*:*" + ], + "wp-news-magazine": [ + "cpe:2.3:a:hasthemes:wp_news:*:*:*:*:*:wordpress:*:*" + ], + "wp-noexternallinks": [ + "cpe:2.3:a:wp_no_external_links_project:wp_no_external_links:*:*:*:*:*:wordpress:*:*" + ], + "wp-olivecart": [ + "cpe:2.3:a:wp-olivecart_project:wp-olivecart:*:*:*:*:*:wordpress:*:*" + ], + "wp-open-graph": [ + "cpe:2.3:a:custom4web:wp_open_graph:*:*:*:*:*:wordpress:*:*" + ], + "wp-opt-in": [ + "cpe:2.3:a:wp_opt-in_project:wp_opt-in:*:*:*:*:*:wordpress:*:*" + ], + "wp-optimize": [ + "cpe:2.3:a:updraftplus:wp-optimize:*:*:*:*:*:wordpress:*:*" + ], + "wp-optin-wheel": [ + "cpe:2.3:a:studiowombat:wp_optin_wheel:*:*:*:*:*:wordpress:*:*" + ], + "wp-original-media-path": [ + "cpe:2.3:a:rvola:wp_original_media_path:*:*:*:*:*:wordpress:*:*" + ], + "wp-page-widget": [ + "cpe:2.3:a:codeandmore:wp_page_widget:*:*:*:*:*:wordpress:*:*" + ], + "wp-pagebuilder": [ + "cpe:2.3:a:themeum:wp_page_builder:*:*:*:*:*:wordpress:*:*" + ], + "wp-paginate": [ + "cpe:2.3:a:maxfoundry:wp-paginate:*:*:*:*:*:wordpress:*:*" + ], + "wp-payeezy-pay": [ + "cpe:2.3:a:payeezy:wp_payeezy_pay:*:*:*:*:*:wordpress:*:*" + ], + "wp-payment-form": [ + "cpe:2.3:a:paymattic:simple_payment_donations_\\\u0026_subscriptions:*:*:*:*:*:wordpress:*:*" + ], + "wp-paytm-pay": [ + "cpe:2.3:a:freelancetoindia:paytm:*:*:*:*:*:wordpress:*:*" + ], + "wp-pdf-generator": [ + "cpe:2.3:a:wpexperts:wp_pdf_generator:*:*:*:*:*:wordpress:*:*" + ], + "wp-performance-score-booster": [ + "cpe:2.3:a:wp_performance_score_booster_project:wp_performance_score_booster:*:*:*:*:*:wordpress:*:*" + ], + "wp-photo-album-plus": [ + "cpe:2.3:a:wp_photo_album_plus_project:wp_photo_album_plus:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wppa.opajaap:wp-photo-album-plus:*:*:*:*:*:wordpress:*:*" + ], + "wp-photo-text-slider-50": [ + "cpe:2.3:a:gopiplus:wp_photo_text_slider_50:*:*:*:*:*:wordpress:*:*" + ], + "wp-phpmyadmin-extension": [ + "cpe:2.3:a:puvox:wp_phpmyadmin:*:*:*:*:*:wordpress:*:*" + ], + "wp-pipes": [ + "cpe:2.3:a:thimpress:wp_pipes:*:*:*:*:*:wordpress:*:*" + ], + "wp-piwik": [ + "cpe:2.3:a:braekling:connect_matomo:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wp-piwik_project:wp-piwik:*:*:*:*:*:wordpress:*:*" + ], + "wp-planet": [ + "cpe:2.3:a:czepol:wp-planet:*:*:*:*:*:wordpress:*:*" + ], + "wp-plotly": [ + "cpe:2.3:a:plot:plotly:*:*:*:*:*:wordpress:*:*" + ], + "wp-plugin-lister": [ + "cpe:2.3:a:paulgriffinpetty:wp_plugin_lister:*:*:*:*:*:wordpress:*:*" + ], + "wp-plugin-manager": [ + "cpe:2.3:a:hasthemes:wp_plugin_manager:*:*:*:*:*:wordpress:*:*" + ], + "wp-pocket-urls": [ + "cpe:2.3:a:coderevolution:wp_pocket_urls:*:*:*:*:*:wordpress:*:*" + ], + "wp-politic": [ + "cpe:2.3:a:hasthemes:ht_politic:*:*:*:*:*:wordpress:*:*" + ], + "wp-polls": [ + "cpe:2.3:a:wp-polls_project:wp-polls:*:*:*:*:*:wordpress:*:*" + ], + "wp-popup-banners": [ + "cpe:2.3:a:accesspressthemes:wp_popup_banners:*:*:*:*:*:wordpress:*:*" + ], + "wp-popup-builder": [ + "cpe:2.3:a:themehunk:wp_popup_builder:*:*:*:*:*:wordpress:*:*" + ], + "wp-popups-lite": [ + "cpe:2.3:a:timersys:wp_popups:*:*:*:*:*:wordpress:*:*" + ], + "wp-post-columns": [ + "cpe:2.3:a:wp_post_columns_project:wp_post_columns:*:*:*:*:*:wordpress:*:*" + ], + "wp-post-page-clone": [ + "cpe:2.3:a:wp_post_page_clone_project:wp_post_page_clone:*:*:*:*:*:wordpress:*:*" + ], + "wp-postratings": [ + "cpe:2.3:a:lesterchan:wp-postratings:*:*:*:*:*:wordpress:*:*" + ], + "wp-powerplaygallery": [ + "cpe:2.3:a:powerplay_gallery_project:powerplay_gallery:*:*:*:*:*:wordpress:*:*" + ], + "wp-prayer": [ + "cpe:2.3:a:goprayer:wp_prayer:*:*:*:*:*:wordpress:*:*" + ], + "wp-print-friendly": [ + "cpe:2.3:a:oomphinc:wp_print_friendly:*:*:*:*:*:wordpress:*:*" + ], + "wp-private-content-plus": [ + "cpe:2.3:a:wpexpertdeveloper:wp_private_content_plus:*:*:*:*:*:wordpress:*:*" + ], + "wp-pro-quiz": [ + "cpe:2.3:a:wp-pro-quiz_project:wp-pro-quiz:*:*:*:*:*:wordpress:*:*" + ], + "wp-product-gallery-lite": [ + "cpe:2.3:a:accesspressthemes:wp_product_gallery_lite:*:*:*:*:*:wordpress:*:*" + ], + "wp-publications": [ + "cpe:2.3:a:wp-publications_project:wp-publications:*:*:*:*:*:wordpress:*:*" + ], + "wp-radio": [ + "cpe:2.3:a:wpmilitary:wp_radio:*:*:*:*:*:wordpress:*:*" + ], + "wp-reactions-lite": [ + "cpe:2.3:a:wpreactions:wp_reactions_lite:*:*:*:*:*:wordpress:*:*" + ], + "wp-recipe-maker": [ + "cpe:2.3:a:bootstrapped:wp_recipe_maker:*:*:*:*:*:wordpress:*:*" + ], + "wp-remote-site-search": [ + "cpe:2.3:a:brainstormforce:wp_remote_site_search:*:*:*:*:*:wordpress:*:*" + ], + "wp-remote-users-sync": [ + "cpe:2.3:a:froger:wp_remote_users_sync:*:*:*:*:*:wordpress:*:*" + ], + "wp-report-post": [ + "cpe:2.3:a:alexraven:wp_report_post:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:esiteq:wp_report_post:*:*:*:*:*:wordpress:*:*" + ], + "wp-reroute-email": [ + "cpe:2.3:a:wp_reroute_email_project:wp_reroute_email:*:*:*:*:*:wordpress:*:*" + ], + "wp-reset": [ + "cpe:2.3:a:webfactoryltd:wp_reset:*:*:*:*:*:wordpress:*:*" + ], + "wp-responsive-slider-with-lightbox": [ + "cpe:2.3:a:i13websolution:thumbnail_slider_with_lightbox:*:*:*:*:*:wordpress:*:*" + ], + "wp-responsive-thumbnail-slider": [ + "cpe:2.3:a:i13websolution:thumbnail_carousel_slider:*:*:*:*:*:wordpress:*:*" + ], + "wp-responsive-video-gallery-with-lightbox": [ + "cpe:2.3:a:i13websolution:video_carousel_slider_with_lightbox:*:*:*:*:*:wordpress:*:*" + ], + "wp-rest-api-authentication": [ + "cpe:2.3:a:miniorange:wordpress_rest_api_authentication:*:*:*:*:*:wordpress:*:*" + ], + "wp-retina-2x": [ + "cpe:2.3:a:meowapps:perfect_images:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:meowapps:wp_retina_2x:*:*:*:*:*:wordpress:*:*" + ], + "wp-roadmap": [ + "cpe:2.3:a:iqonic:wp_roadmap:*:*:*:*:*:wordpress:*:*" + ], + "wp-rollback": [ + "cpe:2.3:a:impress:wp_rollback:*:*:*:*:*:wordpress:*:*" + ], + "wp-rss-aggregator": [ + "cpe:2.3:a:wprssaggregator:wp_rss_aggregator:*:*:*:*:*:wordpress:*:*" + ], + "wp-rss-images": [ + "cpe:2.3:a:wp_rss_images_project:wp_rss_images:*:*:*:*:*:wordpress:*:*" + ], + "wp-s3": [ + "cpe:2.3:a:wordpress_amazon_s3_project:wordpress_amazon_s3:*:*:*:*:*:wordpress:*:*" + ], + "wp-scrippets": [ + "cpe:2.3:a:wp_scrippets_project:wp_scrippets:*:*:*:*:*:wordpress:*:*" + ], + "wp-security-hardening": [ + "cpe:2.3:a:getastra:wp_hardening:*:*:*:*:*:wordpress:*:*" + ], + "wp-security-questions": [ + "cpe:2.3:a:flippercode:wp_security_question:*:*:*:*:*:wordpress:*:*" + ], + "wp-seo-redirect-301": [ + "cpe:2.3:a:wp_seo_redirect_301_project:wp_seo_redirect_301:*:*:*:*:*:wordpress:*:*" + ], + "wp-seo-tags": [ + "cpe:2.3:a:wp_seo_tags_project:wp_seo_tags:*:*:*:*:*:wordpress:*:*" + ], + "wp-seopress": [ + "cpe:2.3:a:seopress:seopress:*:*:*:*:*:wordpress:*:*" + ], + "wp-ses": [ + "cpe:2.3:a:deliciousbrains:wp_offload_ses_lite:*:*:*:*:*:wordpress:*:*" + ], + "wp-shamsi": [ + "cpe:2.3:a:wpvar:wp_shamsi:*:*:*:*:*:wordpress:*:*" + ], + "wp-share-buttons-analytics-by-getsocial": [ + "cpe:2.3:a:getsocial:social_share_buttons_\\\u0026_analytics:*:*:*:*:*:wordpress:*:*" + ], + "wp-shieldon": [ + "cpe:2.3:a:terryl:wp_shieldon:*:*:*:*:*:wordpress:*:*" + ], + "wp-shortcode": [ + "cpe:2.3:a:mythemeshop:wp_shortcode:*:*:*:*:*:wordpress:*:*" + ], + "wp-shoutbox-live-chat": [ + "cpe:2.3:a:wp_live_chat_shoutbox_project:wp_live_chat_shoutbox:*:*:*:*:*:wordpress:*:*" + ], + "wp-show-posts": [ + "cpe:2.3:a:wp_show_posts_project:wp_show_posts:*:*:*:*:*:wordpress:*:*" + ], + "wp-simple-booking-calendar": [ + "cpe:2.3:a:wpsimplebookingcalendar:wp_simple_booking_calendar:*:*:*:*:*:wordpress:*:*" + ], + "wp-simple-events": [ + "cpe:2.3:a:wp_simple_events_project:wp_simple_events:*:*:*:*:*:wordpress:*:*" + ], + "wp-simple-firewall": [ + "cpe:2.3:a:getshieldsecurity:shield_security:*:*:*:*:*:wordpress:*:*" + ], + "wp-simple-galleries": [ + "cpe:2.3:a:maca134:wp_simple_galleries:*:*:*:*:*:wordpress:*:*" + ], + "wp-simple-html-sitemap": [ + "cpe:2.3:a:freelancer-coder:wordpress_simple_html_sitemap:*:*:*:*:*:wordpress:*:*" + ], + "wp-site-protector": [ + "cpe:2.3:a:moriyan_jay:wp_site_protector:*:*:*:*:*:wordpress:*:*" + ], + "wp-sitemap-page": [ + "cpe:2.3:a:wp_sitemap_page_project:wp_sitemap_page:*:*:*:*:*:wordpress:*:*" + ], + "wp-slimstat": [ + "cpe:2.3:a:getusedtoit:wp_slimstat:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wp-slimstat:slimstat_analytics:*:*:*:*:*:wordpress:*:*" + ], + "wp-smart-contracts": [ + "cpe:2.3:a:wpsmartcontracts:wpsmartcontracts:*:*:*:*:*:wordpress:*:*" + ], + "wp-smart-crm-invoices-free": [ + "cpe:2.3:a:softrade:wp_smart_crm_\\\u0026_invoices:*:*:*:*:free:wordpress:*:*" + ], + "wp-smart-editor": [ + "cpe:2.3:a:joomunited:wp-smart-editor:*:*:*:*:*:wordpress:*:*" + ], + "wp-smart-import": [ + "cpe:2.3:a:xylusthemes:wp_smart_import:*:*:*:*:*:wordpress:*:*" + ], + "wp-smart-preloader": [ + "cpe:2.3:a:catchsquare:wp_smart_preloader:*:*:*:*:*:wordpress:*:*" + ], + "wp-smiley": [ + "cpe:2.3:a:wp_smiley_project:wp_smiley:*:*:*:*:*:wordpress:*:*" + ], + "wp-sms": [ + "cpe:2.3:a:veronalabs:wp_sms:*:*:*:*:*:wordpress:*:*" + ], + "wp-smushit": [ + "cpe:2.3:a:wpmudev:smush_image_compression_and_optimization:*:*:*:*:*:wordpress:*:*" + ], + "wp-social": [ + "cpe:2.3:a:wpmet:wp_social_login_and_register_social_counter:*:*:*:*:*:wordpress:*:*" + ], + "wp-social-bookmarking-light": [ + "cpe:2.3:a:wp_social_bookmarking_light_project:wp_social_bookmarking_light:*:*:*:*:*:wordpress:*:*" + ], + "wp-social-feed": [ + "cpe:2.3:a:arrowplugins:social_feed:*:*:*:*:*:wordpress:*:*" + ], + "wp-socializer": [ + "cpe:2.3:a:wp_socializer_project:wp_socializer:*:*:*:*:*:wordpress:*:*" + ], + "wp-songbook": [ + "cpe:2.3:a:wp_songbook_project:wp_songbook:*:*:*:*:*:wordpress:*:*" + ], + "wp-source-control": [ + "cpe:2.3:a:wp_content_source_control_project:wp_content_source_control:*:*:-:-:-:wordpress:*:*" + ], + "wp-special-textboxes": [ + "cpe:2.3:a:wp-special-textboxes_project:wp-special-textboxes:*:*:*:*:*:wordpress:*:*" + ], + "wp-spell-check": [ + "cpe:2.3:a:wpspellcheck:wpspellcheck:*:*:*:*:*:wordpress:*:*" + ], + "wp-splashing-images": [ + "cpe:2.3:a:splashing_images_project:splashing_images:*:*:*:*:*:wordpress:*:*" + ], + "wp-sponsors": [ + "cpe:2.3:a:wpsimplesponsorships:sponsors:*:*:*:*:*:wordpress:*:*" + ], + "wp-staging": [ + "cpe:2.3:a:wp-staging:wp_staging:*:*:*:*:*:wordpress:*:*" + ], + "wp-statistics": [ + "cpe:2.3:a:veronalabs:wp_statistics:*:*:*:*:*:wordpress:*:*" + ], + "wp-stats": [ + "cpe:2.3:a:wp-stats_project:wp-stats:*:*:*:*:*:wordpress:*:*" + ], + "wp-stats-dashboard": [ + "cpe:2.3:a:trivetechnology:wp-stats-dashboard:*:*:*:*:*:wordpress:*:*" + ], + "wp-stats-manager": [ + "cpe:2.3:a:plugins-market:wp_visitor_statistics:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wp_visitor_statistics_\\(real_time_traffic\\)_project:wp_visitor_statistics_\\(real_time_traffic\\):*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wp_visitor_statistics_project:wp_visitor_statistics:*:*:*:*:*:wordpress:*:*" + ], + "wp-sticky-social": [ + "cpe:2.3:a:wp_sticky_social_project:wp_sticky_social:*:*:*:*:*:wordpress:*:*" + ], + "wp-stripe-checkout": [ + "cpe:2.3:a:noorsplugin:wp_stripe_checkout:*:*:*:*:*:wordpress:*:*" + ], + "wp-structuring-markup": [ + "cpe:2.3:a:terakoya:markup_\\(json-ld\\)_structured_in_schema.org:*:*:*:*:*:wordpress:*:*" + ], + "wp-subtitle": [ + "cpe:2.3:a:wp_subtitle_project:wp_subtitle:*:*:*:*:*:wordpress:*:*" + ], + "wp-super-cache": [ + "cpe:2.3:a:automattic:wp_super_cache:*:*:*:*:*:wordpress:*:*" + ], + "wp-super-minify": [ + "cpe:2.3:a:dipakgajjar:wp_super_minify:*:*:*:*:*:wordpress:*:*" + ], + "wp-super-popup": [ + "cpe:2.3:a:wp_super_popup_project:wp_super_popup:*:*:*:*:*:wordpress:*:*" + ], + "wp-support-plus-responsive-ticket-system": [ + "cpe:2.3:a:wpsupportplus:wp_support_plus_responsive_ticket_system:*:*:*:*:*:wordpress:*:*" + ], + "wp-survey-plus": [ + "cpe:2.3:a:wp_survey_plus_project:wp_survey_plus:*:*:*:*:*:wordpress:*:*" + ], + "wp-svg-images": [ + "cpe:2.3:a:kubiq:wp_svg_images:*:*:*:*:*:wordpress:*:*" + ], + "wp-swimteam": [ + "cpe:2.3:a:swim_team_project:swim_team:*:*:*:*:*:wordpress:*:*" + ], + "wp-symposium": [ + "cpe:2.3:a:wpsymposiumpro:wp-symposium:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpsymposiumpro:wp_symposium:*:*:*:*:*:wordpress:*:*" + ], + "wp-symposium-pro": [ + "cpe:2.3:a:wpsymposiumpro:wp_symposium_pro:*:*:*:*:*:wordpress:*:*" + ], + "wp-t-wap": [ + "cpe:2.3:a:wp-t-wap_project:wp-t-wap:*:*:*:*:*:wordpress:*:*" + ], + "wp-table-builder": [ + "cpe:2.3:a:wptablebuilder:wp_table_builder:*:*:*:*:*:wordpress:*:*" + ], + "wp-table-reloaded": [ + "cpe:2.3:a:wp-table_reloaded_project:wp-table_reloaded:*:*:*:*:*:wordpress:*:*" + ], + "wp-taxonomy-import": [ + "cpe:2.3:a:wp_taxonomy_import_project:wp_taxonomy_import:*:*:*:*:*:wordpress:*:*" + ], + "wp-tell-a-friend-popup-form": [ + "cpe:2.3:a:gopiplus:wp-tell-a-friend-popup-form:*:*:*:*:*:wordpress:*:*" + ], + "wp-terms-popup": [ + "cpe:2.3:a:linksoftwarellc:wp_terms_popup:*:*:*:*:*:wordpress:*:*" + ], + "wp-testing": [ + "cpe:2.3:a:psychological_tests_\\\u0026_quizzes_project:psychological_tests_\\\u0026_quizzes:*:*:*:*:*:wordpress:*:*" + ], + "wp-ticket": [ + "cpe:2.3:a:emarketdesign:customer_service_software_\\\u0026_support_ticket_system:*:*:*:*:*:wordpress:*:*" + ], + "wp-tiles": [ + "cpe:2.3:a:keetrax:wp_tiles:*:*:*:*:*:wordpress:*:*" + ], + "wp-time-capsule": [ + "cpe:2.3:a:revmakx:backup_and_staging_by_wp_time_capsule:*:*:*:*:*:wordpress:*:*" + ], + "wp-time-slots-booking-form": [ + "cpe:2.3:a:codepeople:wp_time_slots_booking_form:*:*:*:*:*:wordpress:*:*" + ], + "wp-timed-popup": [ + "cpe:2.3:a:timed_popup_project:timed_popup:*:*:*:*:*:wordpress:*:*" + ], + "wp-todo": [ + "cpe:2.3:a:delower:wp_to_do:*:*:*:*:*:wordpress:*:*" + ], + "wp-total-hacks": [ + "cpe:2.3:a:wp_total_hacks_project:wp_total_hacks:*:*:*:*:*:wordpress:*:*" + ], + "wp-travel": [ + "cpe:2.3:a:wensolutions:wp_travel:*:*:*:*:*:wordpress:*:*" + ], + "wp-travel-engine": [ + "cpe:2.3:a:wptravelengine:wp_travel_engine:*:*:*:*:*:wordpress:*:*" + ], + "wp-tripadvisor-review-slider": [ + "cpe:2.3:a:ljapps:wp_tripadvisor_review_slider:*:*:*:*:*:wordpress:*:*" + ], + "wp-ulike": [ + "cpe:2.3:a:technowich:wp_ulike_-_most_advanced_wordpress_marketing_toolkit:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpulike:wp_ulike:*:*:*:*:*:wordpress:*:*" + ], + "wp-ultimate-csv-importer": [ + "cpe:2.3:a:smackcoders:import_all_pages\\,_post_types\\,_products\\,_orders\\,_and_users_as_xml_\\\u0026_csv:*:*:*:*:*:wordpress:*:*" + ], + "wp-ultimate-exporter": [ + "cpe:2.3:a:smackcoders:export_all_posts\\,_products\\,_orders\\,_refunds_\\\u0026_users:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:smackcoders:ultimate_encoder:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:smackcoders:ultimate_exporter:*:*:*:*:*:wordpress:*:*" + ], + "wp-ultimate-recipe": [ + "cpe:2.3:a:bootstrapped:wp_ultimate_recipe:*:*:*:*:*:wordpress:*:*" + ], + "wp-ultimate-review": [ + "cpe:2.3:a:wpmet:wp_ultimate_review:*:*:*:*:*:wordpress:*:*" + ], + "wp-ultra-simple-paypal-shopping-cart": [ + "cpe:2.3:a:ultra-prod:wordpress_ultra_simple_paypal_shopping_cart:*:*:*:*:*:wordpress:*:*" + ], + "wp-upload-restriction": [ + "cpe:2.3:a:wp-upload-restriction_project:wp-upload-restriction:*:*:*:*:*:wordpress:*:*" + ], + "wp-user": [ + "cpe:2.3:a:wp_user_project:wp_user:*:*:*:*:*:wordpress:*:*" + ], + "wp-user-avatar": [ + "cpe:2.3:a:profilepress:profilepress:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:profilepress:user_registration\\,_login_form\\,_user_profile_\\\u0026_membership:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:properfraction:profilepress:*:*:*:*:*:wordpress:*:*" + ], + "wp-user-frontend": [ + "cpe:2.3:a:wedevs:wp_user_frontend:*:*:*:*:*:wordpress:*:*" + ], + "wp-user-manager": [ + "cpe:2.3:a:wpusermanager:wp_user_manager:*:*:*:*:*:wordpress:*:*" + ], + "wp-user-merger": [ + "cpe:2.3:a:wp_user_merger_project:wp_user_merger:*:*:*:*:*:wordpress:*:*" + ], + "wp-user-profile-avatar": [ + "cpe:2.3:a:wpeventsmanager:user_profile_avatar:*:*:*:*:*:wordpress:*:*" + ], + "wp-useronline": [ + "cpe:2.3:a:lesterchan:wp-useronline:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wp-useronline_project:wp-useronline:*:*:*:*:*:wordpress:*:*" + ], + "wp-users-disable": [ + "cpe:2.3:a:brainvire:disable_user_login:*:*:*:*:*:wordpress:*:*" + ], + "wp-users-exporter": [ + "cpe:2.3:a:wp-users-exporter_project:wp-users-exporter:*:*:*:*:*:wordpress:*:*" + ], + "wp-vertical-image-slider": [ + "cpe:2.3:a:i13websolution:wordpress_vertical_image_slider:*:*:*:*:*:wordpress:*:*" + ], + "wp-video-lightbox": [ + "cpe:2.3:a:tipsandtricks-hq:wp_video_lightbox:*:*:*:*:*:wordpress:*:*" + ], + "wp-vipergb": [ + "cpe:2.3:a:wp-vipergb_project:wp-vipergb:*:*:*:*:*:wordpress:*:*" + ], + "wp-visual-slidebox-builder": [ + "cpe:2.3:a:visual_slide_box_builder_project:visual_slide_box_builder:*:*:*:*:*:wordpress:*:*" + ], + "wp-voting-contest": [ + "cpe:2.3:a:ohiowebtech:wp_voting_contest:*:*:*:*:*:wordpress:*:*" + ], + "wp-whatsapp-chat": [ + "cpe:2.3:a:quadlayers:wp_social_chat:*:*:*:*:*:wordpress:*:*" + ], + "wp-whois-domain": [ + "cpe:2.3:a:netattingo:wp-whois-domain:*:*:*:*:*:wordpress:*:*" + ], + "wp-woocommerce-quickbooks": [ + "cpe:2.3:a:crmperks:integration_for_woocommerce_and_quickbooks:*:*:*:*:*:wordpress:*:*" + ], + "wp-word-count": [ + "cpe:2.3:a:redlettuce:wp_word_count:*:*:*:*:*:wordpress:*:*" + ], + "wp-worthy": [ + "cpe:2.3:a:tiggerswelt:worthy:*:*:*:*:*:wordpress:*:*" + ], + "wp-yelp-review-slider": [ + "cpe:2.3:a:ljapps:wp_yelp_review_slider:*:*:*:*:*:wordpress:*:*" + ], + "wp-youtube-live": [ + "cpe:2.3:a:andrewrminion:wp_youtube_live:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wp_youtube_live_project:wp_youtube_live:*:*:*:*:*:wordpress:*:*" + ], + "wp-youtube-lyte": [ + "cpe:2.3:a:wp_youtube_lyte_project:wp_youtube_lyte:*:*:*:*:*:wordpress:*:*" + ], + "wp2android-turn-wp-site-into-android-app": [ + "cpe:2.3:a:wp2android-turn-wp-site-into-android-app_project:wp2android-turn-wp-site-into-android-app:*:*:*:*:*:wordpress:*:*" + ], + "wp2syslog": [ + "cpe:2.3:a:wp2syslog_project:wp2syslog:*:*:*:*:*:wordpress:*:*" + ], + "wpagecontact": [ + "cpe:2.3:a:wordpress_page_contact_project:wordpress_page_contact:*:*:*:*:*:wordpress:*:*" + ], + "wpappninja": [ + "cpe:2.3:a:wpmobile.app_project:wpmobile.app:*:*:*:*:*:wordpress:*:*" + ], + "wpaudio-mp3-player": [ + "cpe:2.3:a:wpaudio_mp3_player_project:wpaudio_mp3_player:*:*:*:*:*:wordpress:*:*" + ], + "wpb-advanced-faq": [ + "cpe:2.3:a:wpbean:wpb_advanced_faq:*:*:*:*:*:wordpress:*:*" + ], + "wpb-show-core": [ + "cpe:2.3:a:wpb_show_core_project:wpb_show_core:*:*:*:*:*:wordpress:*:*" + ], + "wpbulky-wp-bulk-edit-post-types": [ + "cpe:2.3:a:villatheme:wpbulky:*:*:*:*:*:wordpress:*:*" + ], + "wpcalc": [ + "cpe:2.3:a:wow-company:wpcalc:*:*:*:*:*:wordpress:*:*" + ], + "wpcargo": [ + "cpe:2.3:a:wptaskforce:track_\\\u0026_trace:*:*:*:*:*:wordpress:*:*" + ], + "wpcf7-redirect": [ + "cpe:2.3:a:redirection-for-contact-form7:redirection_for_contact_form_7:*:*:*:*:*:wordpress:*:*" + ], + "wpcodefactory-helper": [ + "cpe:2.3:a:wpfactory:wpfactory_helper:*:*:*:*:*:wordpress:*:*" + ], + "wpcommenttwit": [ + "cpe:2.3:a:wpcommenttwit_project:wpcommenttwit:*:*:*:*:*:wordpress:*:*" + ], + "wpcomplete": [ + "cpe:2.3:a:liquidweb:wpcomplete:*:*:*:*:*:wordpress:*:*" + ], + "wpdatatables": [ + "cpe:2.3:a:tms-outsource:wpdatatables:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:tms-outsource:wpdatatables_lite:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpdatatables:wpdatatables:*:*:*:*:*:wordpress:*:*" + ], + "wpdeepl": [ + "cpe:2.3:a:fluenx:deepl_pro_api_translation:*:*:*:*:*:wordpress:*:*" + ], + "wpdevart-pricing-table": [ + "cpe:2.3:a:wpdevart:pricing_table_builder:*:*:*:*:*:wordpress:*:*" + ], + "wpdevart-vertical-menu": [ + "cpe:2.3:a:wpdevart:responsive_vertical_icon_menu:*:*:*:*:*:wordpress:*:*" + ], + "wpdirectorykit": [ + "cpe:2.3:a:wpdirectorykit:wp_directory_kit:*:*:*:*:*:wordpress:*:*" + ], + "wpdiscuz": [ + "cpe:2.3:a:gvectors:wpdiscuz:*:*:*:*:*:wordpress:*:*" + ], + "wpdm-gutenberg-blocks": [ + "cpe:2.3:a:wpdownloadmanager:gutenberg_blocks_for_wordpress_download_manager:*:*:*:*:*:wordpress:*:*" + ], + "wpdm-premium-packages": [ + "cpe:2.3:a:wpdownloadmanager:premium_packages_-_sell_digital_products_securely:*:*:*:*:*:wordpress:*:*" + ], + "wpematico": [ + "cpe:2.3:a:etruel:wpematico_rss_feed_fetcher:*:*:*:*:*:wordpress:*:*" + ], + "wpforms": [ + "cpe:2.3:a:wpforms:wpforms:*:*:*:*:pro:wordpress:*:*" + ], + "wpforms-lite": [ + "cpe:2.3:a:wpforms:contact_form:*:*:*:*:*:wordpress:*:*" + ], + "wpforo": [ + "cpe:2.3:a:gvectors:wpforo:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:gvectors:wpforo_forum:*:*:*:*:*:wordpress:*:*" + ], + "wpfrom-email": [ + "cpe:2.3:a:wpfrom_email_project:wpfrom_email:*:*:*:*:*:wordpress:*:*" + ], + "wpfront-notification-bar": [ + "cpe:2.3:a:wpfront:wpfront_notification_bar:*:*:*:*:*:wordpress:*:*" + ], + "wpfront-scroll-top": [ + "cpe:2.3:a:wpfront:scroll_top:*:*:*:*:*:wordpress:*:*" + ], + "wpfront-user-role-editor": [ + "cpe:2.3:a:wpfront:wpfront_user_role_editor:*:*:*:*:*:wordpress:*:*" + ], + "wpfunnels": [ + "cpe:2.3:a:coderex:wpfunnels:*:*:*:*:*:wordpress:*:*" + ], + "wpgenious-job-listing": [ + "cpe:2.3:a:wpgenious:wpgenius_job_listing:*:*:*:*:*:wordpress:*:*" + ], + "wpgform": [ + "cpe:2.3:a:google_forms_project:google_forms:*:*:*:*:*:wordpress:*:*" + ], + "wpglobus": [ + "cpe:2.3:a:wpglobus:wpglobus:*:*:*:*:*:wordpress:*:*" + ], + "wpglobus-translate-options": [ + "cpe:2.3:a:wpglobus:wpglobus_translate_options:*:*:*:*:*:wordpress:*:*" + ], + "wpide": [ + "cpe:2.3:a:xplodedthemes:wpide:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:xplodedthemes:wpide_-_file_manager_\\\u0026_code_editor:*:*:*:*:*:wordpress:*:*" + ], + "wpjam-basic": [ + "cpe:2.3:a:wpjam_basic_project:wpjam_basic:*:*:*:*:*:wordpress:*:*" + ], + "wplegalpages": [ + "cpe:2.3:a:wpeka:wplegalpages:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wplegalpages:wp_legal_pages:*:*:*:*:*:wordpress:*:*" + ], + "wplr-sync": [ + "cpe:2.3:a:meowapps:photo_engine:*:*:*:*:*:wordpress:*:*" + ], + "wpmarketplace": [ + "cpe:2.3:a:wpmarketplace_project:wpmarketplace:*:*:*:*:*:wordpress:*:*" + ], + "wpo365-login": [ + "cpe:2.3:a:wpo365:wordpress_\\+_azure_ad_\\/_microsoft_office_365:*:*:*:*:*:wordpress:*:*" + ], + "wpopal-core-features": [ + "cpe:2.3:a:wpopal:wpopal_core_features:*:*:*:*:*:wordpress:*:*" + ], + "wppageflip": [ + "cpe:2.3:a:agence_web_360:page_flip_book:*:*:*:*:*:wordpress:*:*" + ], + "wppizza": [ + "cpe:2.3:a:wp-pizza:wppizza:*:*:*:*:*:wordpress:*:*" + ], + "wps-child-theme-generator": [ + "cpe:2.3:a:wpserveur:wps_child_theme_generator:*:*:*:*:*:wordpress:*:*" + ], + "wps-hide-login": [ + "cpe:2.3:a:wpserveur:wps_hide_login:*:*:*:*:*:wordpress:*:*" + ], + "wpschoolpress": [ + "cpe:2.3:a:igexsolutions:wpschoolpress:*:*:*:*:*:wordpress:*:*" + ], + "wpshopgermany-it-recht-kanzlei": [ + "cpe:2.3:a:maennchen1:wpshopgermany_it-recht_kanzlei:*:*:*:*:*:wordpress:*:*" + ], + "wpshopgermany-protectedshops": [ + "cpe:2.3:a:maennchen1:wpshopgermany_-_protected_shops:*:*:*:*:*:wordpress:*:*" + ], + "wpsimpletools-upload-limit": [ + "cpe:2.3:a:manage_upload_limit_project:manage_upload_limit:*:*:*:*:*:wordpress:*:*" + ], + "wpsolr-search-engine": [ + "cpe:2.3:a:wpsolr:wpsolr-search-engine:*:*:*:*:*:wordpress:*:*" + ], + "wpstream": [ + "cpe:2.3:a:wpstream:wpstream:*:*:*:*:*:wordpress:*:*" + ], + "wptools": [ + "cpe:2.3:a:wptools_project:wptools:*:*:*:*:*:wordpress:*:*" + ], + "wptouch": [ + "cpe:2.3:a:bravenewcode:wptouch:*:*:*:*:*:wordpress:*:*" + ], + "wpupper-share-buttons": [ + "cpe:2.3:a:wpupper_share_buttons_project:wpupper_share_buttons:*:*:*:*:*:wordpress:*:*" + ], + "wpvivid-backup-mainwp": [ + "cpe:2.3:a:wpvivid:wpvivid_backup_for_mainwp:*:*:*:*:*:wordpress:*:*" + ], + "wpvivid-backuprestore": [ + "cpe:2.3:a:wpvivid:migration\\,_backup\\,_staging:*:*:*:*:*:wordpress:*:*" + ], + "wpvr": [ + "cpe:2.3:a:coderex:wp_vr:*:*:*:*:*:wordpress:*:*" + ], + "wpzoom-portfolio": [ + "cpe:2.3:a:wpzoom:wpzoom_portfolio:*:*:*:*:*:wordpress:*:*" + ], + "wpzoom-shortcodes": [ + "cpe:2.3:a:wpzoom:wpzoom_shortcodes:*:*:*:*:*:wordpress:*:*" + ], + "wrc-pricing-tables": [ + "cpe:2.3:a:realwebcare:wrc_pricing_tables:*:*:*:*:*:wordpress:*:*" + ], + "ws-form": [ + "cpe:2.3:a:westguardsolutions:ws_form:*:*:*:*:lite:wordpress:*:*" + ], + "wsecure": [ + "cpe:2.3:a:joomlaserviceprovider:wsecure:*:*:*:*:lite:wordpress:*:*" + ], + "wsm-downloader": [ + "cpe:2.3:a:wsm_downloader_project:wsm_downloader:*:*:*:*:*:wordpress:*:*" + ], + "wti-like-post": [ + "cpe:2.3:a:webtechideas:wti_like_post:*:*:*:*:*:wordpress:*:*" + ], + "www-xml-sitemap-generator-org": [ + "cpe:2.3:a:xmlsitemapgenerator:xml_sitemap_generator:*:*:*:*:*:wordpress:*:*" + ], + "wxsync": [ + "cpe:2.3:a:tencent:wxsync:*:*:*:*:*:wordpress:*:*" + ], + "wysija-newsletters": [ + "cpe:2.3:a:mailpoet:mailpoet_newsletters:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:mailpoet:mailpoet_newsletters:*:*:-:-:-:wordpress:*:*" + ], + "x-forms-express": [ + "cpe:2.3:a:nex-forms_lite_project:nex-forms_lite:*:*:*:*:*:wordpress:*:*" + ], + "xcloner-backup-and-restore": [ + "cpe:2.3:a:xcloner:xcloner:*:*:*:*:*:wordpress:*:*" + ], + "xili-tidy-tags": [ + "cpe:2.3:a:xiligroup:xili-tidy-tags:*:*:*:*:*:wordpress:*:*" + ], + "xllentech-english-islamic-calendar": [ + "cpe:2.3:a:xllentech:english_islamic_calendar:*:*:*:*:*:wordpress:*:*" + ], + "xml-sitemap-generator-for-google": [ + "cpe:2.3:a:wpgrim:dynamic_xml_sitemaps_generator_for_google:*:*:*:*:*:wordpress:*:*" + ], + "xml-sitemaps-for-videos": [ + "cpe:2.3:a:digitalinspiration:google_xml_sitemap_for_videos:*:*:*:*:*:wordpress:*:*" + ], + "xo-liteslider": [ + "cpe:2.3:a:xakuro:xo_slider:*:*:*:*:*:wordpress:*:*" + ], + "xo-security": [ + "cpe:2.3:a:xakuro:xo_security:*:*:*:*:*:*:*:*" + ], + "xpinner-lite": [ + "cpe:2.3:a:cyberseo:xpinner_lite:*:*:*:*:*:wordpress:*:*" + ], + "xqueue-maileon": [ + "cpe:2.3:a:maileon:maileon:*:*:*:*:*:wordpress:*:*" + ], + "xtremelocator": [ + "cpe:2.3:a:xtremelocator:xtremelocator:*:*:*:*:*:wordpress:*:*" + ], + "yabp": [ + "cpe:2.3:a:tromit:yabp:*:*:*:*:*:wordpress:*:*" + ], + "yada-wiki": [ + "cpe:2.3:a:yada_wiki_project:yada_wiki:*:*:*:*:*:wordpress:*:*" + ], + "yamaps": [ + "cpe:2.3:a:yamaps_project:yamaps:*:*:*:*:*:wordpress:*:*" + ], + "yandexnews-feed-by-teplitsa": [ + "cpe:2.3:a:te-st:yandex.news_feed_by_teplitsa:*:*:*:*:*:wordpress:*:*" + ], + "yaysmtp": [ + "cpe:2.3:a:yaycommerce:yaysmtp:*:*:*:*:*:wordpress:*:*" + ], + "yds-support-ticket-system": [ + "cpe:2.3:a:ydesignservices:yds_support_ticket_system:*:*:*:*:*:wordpress:*:*" + ], + "yellow-pencil-visual-theme-customizer": [ + "cpe:2.3:a:yellowpencil:visual_css_style_editor:*:*:*:*:*:wordpress:*:*" + ], + "yellow-yard": [ + "cpe:2.3:a:yellowyard:yellow_yard_searchbar:*:*:*:*:*:wordpress:*:*" + ], + "yesno": [ + "cpe:2.3:a:kohsei-works:yes\\/no_chart:*:*:*:*:*:wordpress:*:*" + ], + "yet-another-related-posts-plugin": [ + "cpe:2.3:a:yarpp:yet_another_related_posts_plugin:*:*:*:*:*:wordpress:*:*" + ], + "yet-another-stars-rating": [ + "cpe:2.3:a:yet_another_stars_rating_project:yet_another_stars_rating:*:*:*:*:*:wordpress:*:*" + ], + "yikes-inc-easy-custom-woocommerce-product-tabs": [ + "cpe:2.3:a:yikesinc:custom_product_tabs_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "yikes-inc-easy-mailchimp-extender": [ + "cpe:2.3:a:codeparrots:easy_forms_for_mailchimp:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:yikesinc:easy_forms_for_mailchimp:*:*:*:*:*:wordpress:*:*" + ], + "yith-desktop-notifications-for-woocommerce": [ + "cpe:2.3:a:yithemes:yith_desktop_notifications_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "yith-maintenance-mode": [ + "cpe:2.3:a:yithemes:yith_maintenance_mode:*:*:*:*:*:wordpress:*:*" + ], + "yith-woocommerce-gift-cards": [ + "cpe:2.3:a:yithemes:yith_woocommerce_gift_cards:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:yithemes:yith_woocommerce_gift_cards:*:*:*:*:free:wordpress:*:*" + ], + "yith-woocommerce-product-add-ons": [ + "cpe:2.3:a:yithemes:yith_woocommerce_product_add-ons:*:*:*:*:free:wordpress:*:*" + ], + "yookassa": [ + "cpe:2.3:a:yookassa:yukassa_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "yop-poll": [ + "cpe:2.3:a:yop-poll:yop-poll:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:yop-poll:yop_poll:*:*:*:*:*:wordpress:*:*" + ], + "yotpo-reviews-for-woocommerce": [ + "cpe:2.3:a:yotpo_reviews_for_woocommerce_project:yotpo_reviews_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "yourchannel": [ + "cpe:2.3:a:plugin:yourchannel:*:*:*:*:*:wordpress:*:*" + ], + "youtube-channel": [ + "cpe:2.3:a:my_youtube_channel_project:my_youtube_channel:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:urosevic:my_youtube_channel:*:*:*:*:*:wordpress:*:*" + ], + "youtube-channel-gallery": [ + "cpe:2.3:a:poselab:youtube-channel-gallery:*:*:*:*:*:wordpress:*:*" + ], + "youtube-embed": [ + "cpe:2.3:a:youtube_embed_project:youtube_embed:*:*:*:*:*:wordpress:*:*" + ], + "youtube-embed-plus": [ + "cpe:2.3:a:embedplus:youtube:*:*:*:*:*:wordpress:*:*" + ], + "youtube-feeder": [ + "cpe:2.3:a:youtube_feeder_project:youtube_feeder:*:*:*:*:*:wordpress:*:*" + ], + "youtube-playlist-player": [ + "cpe:2.3:a:getbutterfly:youtube_playlist_player:*:*:*:*:*:wordpress:*:*" + ], + "youtube-showcase": [ + "cpe:2.3:a:emarketdesign:youtube_video_gallery:*:*:*:*:*:wordpress:*:*" + ], + "youtube-speedload": [ + "cpe:2.3:a:alexufo:youtube_speedload:*:*:*:*:*:wordpress:*:*" + ], + "youtube-video-inserter": [ + "cpe:2.3:a:ueberhamm-design:youtube_video_inserter:*:*:*:*:*:wordpress:*:*" + ], + "youtube-video-player": [ + "cpe:2.3:a:wpdevart:youtube_embed\\,_playlist_and_popup:*:*:*:*:*:wordpress:*:*" + ], + "youtube-widget-responsive": [ + "cpe:2.3:a:stefanoai:widget_responsive_for_youtube:*:*:*:*:*:wordpress:*:*" + ], + "youzify": [ + "cpe:2.3:a:kainelabs:youzify:*:*:*:*:*:wordpress:*:*" + ], + "yt-player": [ + "cpe:2.3:a:video_player_for_youtube_project:video_player_for_youtube:*:*:*:*:*:wordpress:*:*" + ], + "yurl-retwitt": [ + "cpe:2.3:a:yurl_retwitt_project:yurl_retwitt:*:*:*:*:*:wordpress:*:*" + ], + "yuzo-related-post": [ + "cpe:2.3:a:yuzopro:yuzo:*:*:*:*:*:wordpress:*:*" + ], + "z-url-preview": [ + "cpe:2.3:a:z-url_preview_project:z-url_preview:*:*:*:*:*:wordpress:*:*" + ], + "zen-carousel": [ + "cpe:2.3:a:xen_carousel_plugin_project:xen_carousel:*:*:*:*:*:wordpress:*:*" + ], + "zen-mobile-app-native": [ + "cpe:2.3:a:zen_mobile_app_native_project:zen_mobile_app_native:*:*:*:*:*:wordpress:*:*" + ], + "zendesk-help-center": [ + "cpe:2.3:a:bestwebsoft:zendesk_help_center:*:*:*:*:*:wordpress:*:*" + ], + "zendrop-dropshipping-and-fulfillment": [ + "cpe:2.3:a:zendrop:zendrop:*:*:*:*:*:wordpress:*:*" + ], + "zephyr-project-manager": [ + "cpe:2.3:a:zephyr_project_manager_project:zephyr_project_manager:*:*:*:*:*:wordpress:*:*" + ], + "zero-bs-crm": [ + "cpe:2.3:a:automattic:jetpack_crm:*:*:*:*:*:wordpress:*:*" + ], + "zero-spam": [ + "cpe:2.3:a:highfivery:zero-spam:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:highfivery:zero_spam_for_wordpress:*:*:*:*:*:wordpress:*:*" + ], + "zerobounce": [ + "cpe:2.3:a:zerobounce:zerobounce_email_verification_\\\u0026_validation:*:*:*:*:*:wordpress:*:*" + ], + "zip-attachments": [ + "cpe:2.3:a:zip_attachments_project:zip_attachments:*:*:*:*:*:wordpress:*:*" + ], + "zip-recipes": [ + "cpe:2.3:a:really-simple-plugins:recipe_maker_for_your_food_blog_from_zip_recipes:*:*:*:*:*:wordpress:*:*" + ], + "zippy": [ + "cpe:2.3:a:gesundheit-bewegt:zippy:*:*:*:*:*:wordpress:*:*" + ], + "ziteboard-online-whiteboard": [ + "cpe:2.3:a:ziteboard:ziteboard:*:*:*:*:*:wordpress:*:*" + ], + "zm-ajax-login-register": [ + "cpe:2.3:a:zanematthew:zm_ajax_login_\\\u0026_register:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:zm_ajax_login_\\\u0026_register_project:zm_ajax_login_\\\u0026_register:*:*:*:*:*:wordpress:*:*" + ], + "zm-gallery": [ + "cpe:2.3:a:zm-gallery_project:zm-gallery:*:*:*:*:*:wordpress:*:*" + ], + "zoho-crm-forms": [ + "cpe:2.3:a:zoho:lead_magnet:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:zohocorp:zoho_crm_lead_magnet:*:*:*:*:*:wordpress:*:*" + ], + "zoho-forms": [ + "cpe:2.3:a:zohocorp:zoho_forms:*:*:*:*:*:wordpress:*:*" + ], + "zoho-salesiq": [ + "cpe:2.3:a:zoho:salesiq:*:*:*:*:*:wordpress:*:*" + ], + "zotpress": [ + "cpe:2.3:a:zotpress_project:zotpress:*:*:*:*:*:wordpress:*:*" + ], + "zx-csv-upload": [ + "cpe:2.3:a:zx-csv-upload_project:zx-csv-upload:*:*:*:*:*:wordpress:*:*" + ] + }, + "wordpress_themes": { + "Divi": [ + "cpe:2.3:a:elegantthemes:divi:*:*:*:*:*:wordpress:*:*" + ], + "accesspress-basic": [ + "cpe:2.3:a:accesspressthemes:accesspress_basic:*:*:*:*:*:wordpress:*:*" + ], + "accesspress-lite": [ + "cpe:2.3:a:accesspressthemes:accesspress_lite:*:*:*:*:*:wordpress:*:*" + ], + "accesspress-mag": [ + "cpe:2.3:a:accesspressthemes:accesspress_mag:*:*:*:*:*:wordpress:*:*" + ], + "accesspress-parallax": [ + "cpe:2.3:a:accesspressthemes:accesspress_parallax:*:*:*:*:*:wordpress:*:*" + ], + "accesspress-root": [ + "cpe:2.3:a:accesspressthemes:accesspress_root:*:*:*:*:*:wordpress:*:*" + ], + "activello": [ + "cpe:2.3:a:colorlib:activello:*:*:*:*:*:wordpress:*:*" + ], + "affluent": [ + "cpe:2.3:a:cpothemes:affluent:*:*:*:*:*:wordpress:*:*" + ], + "allegiant": [ + "cpe:2.3:a:cpothemes:allegiant:*:*:*:*:*:wordpress:*:*" + ], + "antreas": [ + "cpe:2.3:a:machothemes:antreas:*:*:*:*:*:wordpress:*:*" + ], + "arya-multipurpose": [ + "cpe:2.3:a:everestthemes:arya_multipurpose:*:*:*:*:*:wordpress:*:*" + ], + "atahualpa": [ + "cpe:2.3:a:bytesforall:atahualpa:*:*:*:*:*:wordpress:*:*" + ], + "attorney": [ + "cpe:2.3:a:hennessey:attorney:*:*:*:*:*:wordpress:*:*" + ], + "auberge": [ + "cpe:2.3:a:webmandesign:auberge_theme:*:*:*:*:*:wordpress:*:*" + ], + "big-store": [ + "cpe:2.3:a:themehunk:big_store:*:*:*:*:*:wordpress:*:*" + ], + "bingle": [ + "cpe:2.3:a:accesspressthemes:bingle:*:*:*:*:*:wordpress:*:*" + ], + "blocksy": [ + "cpe:2.3:a:creativethemes:blocksy:*:*:*:*:*:wordpress:*:*" + ], + "bloger": [ + "cpe:2.3:a:accesspressthemes:bloger:*:*:*:*:*:wordpress:*:*" + ], + "bonkers": [ + "cpe:2.3:a:colorlib:bonkers:*:*:*:*:*:wordpress:*:*" + ], + "brilliance": [ + "cpe:2.3:a:cpothemes:brilliance:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpchill:brilliance:*:*:*:*:*:wordpress:*:*" + ], + "cakifo": [ + "cpe:2.3:a:jayj:cakifo:*:*:*:*:*:wordpress:*:*" + ], + "colormag": [ + "cpe:2.3:a:themegrill:colormag:*:*:*:*:*:wordpress:*:*" + ], + "colorway": [ + "cpe:2.3:a:inkthemes:colorway:*:*:*:*:*:wordpress:*:*" + ], + "construction-lite": [ + "cpe:2.3:a:accesspressthemes:construction_lite:*:*:*:*:*:wordpress:*:*" + ], + "customizr": [ + "cpe:2.3:a:presscustomizr:customizr:*:*:*:*:*:wordpress:*:*" + ], + "darcie": [ + "cpe:2.3:a:catchthemes:darcie:*:*:*:*:*:wordpress:*:*" + ], + "digitally": [ + "cpe:2.3:a:omarfolgheraiter:digitally:*:*:*:*:*:wordpress:*:*" + ], + "doko": [ + "cpe:2.3:a:accesspressthemes:doko:*:*:*:*:*:wordpress:*:*" + ], + "drop": [ + "cpe:2.3:a:competethemes:drop:*:*:*:*:*:wordpress:*:*" + ], + "eightstore-lite": [ + "cpe:2.3:a:accesspressthemes:eightstore-lite:*:*:*:*:*:wordpress:*:*" + ], + "enlighten": [ + "cpe:2.3:a:accesspressthemes:enlighten:*:*:*:*:*:wordpress:*:*" + ], + "everest-news": [ + "cpe:2.3:a:everestthemes:everest_news:*:*:*:*:*:wordpress:*:*" + ], + "flashy": [ + "cpe:2.3:a:flashy_project:flashy:*:*:*:*:*:wordpress:*:*" + ], + "fullbase": [ + "cpe:2.3:a:marchettidesign:fullbase:*:*:*:*:*:wordpress:*:*" + ], + "gaga-corp": [ + "cpe:2.3:a:accesspressthemes:gaga_corp:*:*:*:*:*:wordpress:*:*" + ], + "gaga-lite": [ + "cpe:2.3:a:accesspressthemes:gaga_lite:*:*:*:*:*:wordpress:*:*" + ], + "generatepress": [ + "cpe:2.3:a:generatepress:generatepress:*:*:*:*:-:wordpress:*:*", + "cpe:2.3:a:generatepress:generatepress:*:*:*:*:premium:wordpress:*:*" + ], + "hueman": [ + "cpe:2.3:a:presscustomizr:hueman:*:*:*:*:*:wordpress:*:*" + ], + "illdy": [ + "cpe:2.3:a:colorlib:illdy:*:*:*:*:*:wordpress:*:*" + ], + "kata": [ + "cpe:2.3:a:climaxthemes:kata:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:climaxthemes:kata_apps:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:climaxthemes:kata_business:*:*:*:*:*:wordpress:*:*" + ], + "materialis": [ + "cpe:2.3:a:extendthemes:materialis:*:*:*:*:*:wordpress:*:*" + ], + "medzone-lite": [ + "cpe:2.3:a:machothemes:medzone_lite:*:*:*:*:*:wordpress:*:*" + ], + "mesmerize": [ + "cpe:2.3:a:extendthemes:mesmerize:*:*:*:*:*:wordpress:*:*" + ], + "modern": [ + "cpe:2.3:a:webmandesign:modern_theme:*:*:*:*:*:wordpress:*:*" + ], + "morning-coffee": [ + "cpe:2.3:a:adazing:morning_coffee:*:*:*:*:*:wordpress:*:*" + ], + "newsmag": [ + "cpe:2.3:a:machothemes:newsmag:*:*:*:*:*:wordpress:*:*" + ], + "newspaper-x": [ + "cpe:2.3:a:colorlib:newspaper_x:*:*:*:*:*:wordpress:*:*" + ], + "nexter": [ + "cpe:2.3:a:posimyth:nexter:*:*:*:*:*:wordpress:*:*" + ], + "nova-lite": [ + "cpe:2.3:a:themeinprogress:nova_lite:*:*:*:*:*:wordpress:*:*" + ], + "nsc": [ + "cpe:2.3:a:saleswizard:nsc:*:*:*:*:*:wordpress:*:*" + ], + "pinzolo": [ + "cpe:2.3:a:thriveweb:pinzolo:*:*:*:*:*:wordpress:*:*" + ], + "pixova-lite": [ + "cpe:2.3:a:colorlib:pixova_lite:*:*:*:*:*:wordpress:*:*" + ], + "regina-lite": [ + "cpe:2.3:a:machothemes:regina_lite:*:*:*:*:*:wordpress:*:*" + ], + "responsive": [ + "cpe:2.3:a:cyberchimps:responsive:*:*:*:*:*:wordpress:*:*" + ], + "royal-elementor-kit": [ + "cpe:2.3:a:royal-elementor-addons:royal_elementor_kit:*:*:*:*:*:wordpress:*:*" + ], + "shapely": [ + "cpe:2.3:a:colorlib:shapely:*:*:*:*:*:wordpress:*:*" + ], + "sparkling": [ + "cpe:2.3:a:colorlib:sparklinkg:*:*:*:*:*:wordpress:*:*" + ], + "tijaji": [ + "cpe:2.3:a:tijaji:tijaji:*:*:*:*:*:wordpress:*:*" + ], + "transcend": [ + "cpe:2.3:a:cpothemes:transcend:*:*:*:*:*:wordpress:*:*" + ], + "upfrontwp": [ + "cpe:2.3:a:wpazure:upfrontwp:*:*:*:*:*:wordpress:*:*" + ], + "viala": [ + "cpe:2.3:a:davidgarlitz:viala:*:*:*:*:*:wordpress:*:*" + ], + "weaver-xtreme": [ + "cpe:2.3:a:weavertheme:weaver_xtreme_theme:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:weavertheme:weaver_xtreme_theme_support:*:*:*:*:*:wordpress:*:*" + ], + "winters": [ + "cpe:2.3:a:myshopkit:winters:*:*:*:*:*:wordpress:*:*" + ], + "wishful-blog": [ + "cpe:2.3:a:wishfulthemes:wishful_blog:*:*:*:*:*:wordpress:*:*" + ], + "wlow": [ + "cpe:2.3:a:marchettidesign:wlow:*:*:*:*:*:wordpress:*:*" + ], + "yourjourney": [ + "cpe:2.3:a:wiloke:your_journey:*:*:*:*:*:wordpress:*:*" + ], + "zigcy-baby": [ + "cpe:2.3:a:accesspressthemes:zigcy_baby:*:*:*:*:*:wordpress:*:*" + ], + "zigcy-cosmetics": [ + "cpe:2.3:a:accesspressthemes:zigcy_cosmetics:*:*:*:*:*:wordpress:*:*" + ], + "zigcy-lite": [ + "cpe:2.3:a:accesspressthemes:zigcy_lite:*:*:*:*:*:wordpress:*:*" + ] } } } \ No newline at end of file diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator/generate.go b/syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator/generate.go index 04a308273..c456ddec3 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator/generate.go +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator/generate.go @@ -102,20 +102,29 @@ func normalizeCPE(cpe *wfn.Attributes) *wfn.Attributes { } const ( - prefixForNPMPackages = "https://www.npmjs.com/package/" - prefixForRubyGems = "https://rubygems.org/gems/" - prefixForRubyGemsHTTP = "http://rubygems.org/gems/" - prefixForNativeRubyGems = "https://github.com/ruby/" - prefixForPyPIPackages = "https://pypi.org/project/" - prefixForJenkinsPlugins = "https://plugins.jenkins.io/" - prefixForJenkinsPluginsGitHub = "https://github.com/jenkinsci/" - prefixForRustCrates = "https://crates.io/crates/" - prefixForPHPPear = "https://pear.php.net/" - prefixForPHPPearHTTP = "http://pear.php.net/" - prefixForPHPPecl = "https://pecl.php.net/" - prefixForPHPPeclHTTP = "http://pecl.php.net/" - prefixForPHPComposer = "https://packagist.org/packages/" - prefixForGoModules = "https://pkg.go.dev/" + prefixForNPMPackages = "https://www.npmjs.com/package/" + prefixForRubyGems = "https://rubygems.org/gems/" + prefixForRubyGemsHTTP = "http://rubygems.org/gems/" + prefixForNativeRubyGems = "https://github.com/ruby/" + prefixForPyPIPackages = "https://pypi.org/project/" + prefixForJenkinsPlugins = "https://plugins.jenkins.io/" + prefixForJenkinsPluginsGitHub = "https://github.com/jenkinsci/" + prefixForRustCrates = "https://crates.io/crates/" + prefixForPHPPear = "https://pear.php.net/" + prefixForPHPPearHTTP = "http://pear.php.net/" + prefixForPHPPecl = "https://pecl.php.net/" + prefixForPHPPeclHTTP = "http://pecl.php.net/" + prefixForPHPComposer = "https://packagist.org/packages/" + prefixForGoModules = "https://pkg.go.dev/" + prefixForWordpressPlugins = "https://wordpress.org/plugins/" + prefixForWordpressPluginsTracBrowser = "https://plugins.trac.wordpress.org/browser/" + prefixForWordpressPluginsTracLog = "https://plugins.trac.wordpress.org/log/" + prefixForWordpressPluginsGitHubArchive = "https://github.com/wp-plugins/" + prefixForWordpressPluginsWordfence = "https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/" + prefixForWordpressThemes = "https://wordpress.org/themes/" + prefixForWordpressThemesTracBrowser = "https://themes.trac.wordpress.org/browser/" + prefixForWordpressThemesTracLog = "https://themes.trac.wordpress.org/log/" + prefixForWordpressThemesWordfence = "https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-themes/" ) // indexCPEList creates an index of CPEs by ecosystem. @@ -164,6 +173,12 @@ func indexCPEList(list CpeList) *dictionary.Indexed { case strings.HasPrefix(ref, prefixForGoModules): addEntryForGoModulePackage(indexed, ref, cpeItemName) + + case strings.HasPrefix(ref, prefixForWordpressPlugins), strings.HasPrefix(ref, prefixForWordpressPluginsTracBrowser), strings.HasPrefix(ref, prefixForWordpressPluginsTracLog), strings.HasPrefix(ref, prefixForWordpressPluginsGitHubArchive), strings.HasPrefix(ref, prefixForWordpressPluginsWordfence): + addEntryForWordpressPlugin(indexed, ref, cpeItemName) + + case strings.HasPrefix(ref, prefixForWordpressThemes), strings.HasPrefix(ref, prefixForWordpressThemesTracBrowser), strings.HasPrefix(ref, prefixForWordpressThemesTracLog), strings.HasPrefix(ref, prefixForWordpressThemesWordfence): + addEntryForWordpressTheme(indexed, ref, cpeItemName) } } } @@ -183,6 +198,37 @@ func updateIndex(indexed *dictionary.Indexed, ecosystem string, pkgName string, indexed.EcosystemPackages[ecosystem][pkgName].Add(cpe) } +func addEntryForWordpressPlugin(indexed *dictionary.Indexed, ref string, cpeItemName string) { + // Prune off the non-package-name parts of the URL + ref = strings.TrimPrefix(ref, prefixForWordpressPlugins) + ref = strings.TrimPrefix(ref, prefixForWordpressPluginsTracBrowser) + ref = strings.TrimPrefix(ref, prefixForWordpressPluginsTracLog) + ref = strings.TrimPrefix(ref, prefixForWordpressPluginsGitHubArchive) + ref = strings.TrimPrefix(ref, prefixForWordpressPluginsWordfence) + ref = strings.Split(ref, "?")[0] + ref = strings.Split(ref, "/")[0] + if ref == "" { + return + } + + updateIndex(indexed, dictionary.EcosystemWordpressPlugins, ref, cpeItemName) +} + +func addEntryForWordpressTheme(indexed *dictionary.Indexed, ref string, cpeItemName string) { + // Prune off the non-package-name parts of the URL + ref = strings.TrimPrefix(ref, prefixForWordpressThemes) + ref = strings.TrimPrefix(ref, prefixForWordpressThemesTracBrowser) + ref = strings.TrimPrefix(ref, prefixForWordpressThemesTracLog) + ref = strings.TrimPrefix(ref, prefixForWordpressThemesWordfence) + ref = strings.Split(ref, "?")[0] + ref = strings.Split(ref, "/")[0] + if ref == "" { + return + } + + updateIndex(indexed, dictionary.EcosystemWordpressThemes, ref, cpeItemName) +} + func addEntryForRustCrate(indexed *dictionary.Indexed, ref string, cpeItemName string) { // Prune off the non-package-name parts of the URL ref = strings.TrimPrefix(ref, prefixForRustCrates) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator/generate_test.go b/syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator/generate_test.go index 48167b17d..10f767d06 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator/generate_test.go +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator/generate_test.go @@ -243,6 +243,123 @@ func Test_addEntryFuncs(t *testing.T) { }, }, }, + { + name: "addEntryForWordpressPlugin", + addEntryFunc: addEntryForWordpressPlugin, + inputRef: "https://wordpress.org/plugins/armadillo/releases", + inputCpeItemName: "cpe:2.3:a:armadillo:armadillo:1.23:*:*:*:*:wordpress:*:*", + expectedIndexed: dictionary.Indexed{ + EcosystemPackages: map[string]dictionary.Packages{ + dictionary.EcosystemWordpressPlugins: { + "armadillo": dictionary.NewSet("cpe:2.3:a:armadillo:armadillo:1.23:*:*:*:*:wordpress:*:*"), + }, + }, + }, + }, + { + name: "addEntryForWordpressPlugin from Trac Browser", + addEntryFunc: addEntryForWordpressPlugin, + inputRef: "https://plugins.trac.wordpress.org/browser/armadillo/something", + inputCpeItemName: "cpe:2.3:a:armadillo:armadillo:1.23:*:*:*:*:wordpress:*:*", + expectedIndexed: dictionary.Indexed{ + EcosystemPackages: map[string]dictionary.Packages{ + dictionary.EcosystemWordpressPlugins: { + "armadillo": dictionary.NewSet("cpe:2.3:a:armadillo:armadillo:1.23:*:*:*:*:wordpress:*:*"), + }, + }, + }, + }, + { + name: "addEntryForWordpressPlugin from Trac Log", + addEntryFunc: addEntryForWordpressPlugin, + inputRef: "https://plugins.trac.wordpress.org/log/armadillo/log", + inputCpeItemName: "cpe:2.3:a:armadillo:armadillo:1.23:*:*:*:*:wordpress:*:*", + expectedIndexed: dictionary.Indexed{ + EcosystemPackages: map[string]dictionary.Packages{ + dictionary.EcosystemWordpressPlugins: { + "armadillo": dictionary.NewSet("cpe:2.3:a:armadillo:armadillo:1.23:*:*:*:*:wordpress:*:*"), + }, + }, + }, + }, + { + name: "addEntryForWordpressPlugin from GitHub wp-plugins archive", + addEntryFunc: addEntryForWordpressPlugin, + inputRef: "https://github.com/wp-plugins/armadillo/something", + inputCpeItemName: "cpe:2.3:a:armadillo:armadillo:1.23:*:*:*:*:wordpress:*:*", + expectedIndexed: dictionary.Indexed{ + EcosystemPackages: map[string]dictionary.Packages{ + dictionary.EcosystemWordpressPlugins: { + "armadillo": dictionary.NewSet("cpe:2.3:a:armadillo:armadillo:1.23:*:*:*:*:wordpress:*:*"), + }, + }, + }, + }, + { + name: "addEntryForWordpressPlugin wordfence", + addEntryFunc: addEntryForWordpressPlugin, + inputRef: "https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/armadillo/skjfhskdjhf/12344", + inputCpeItemName: "cpe:2.3:a:armadillo:armadillo:1.23:*:*:*:*:wordpress:*:*", + expectedIndexed: dictionary.Indexed{ + EcosystemPackages: map[string]dictionary.Packages{ + dictionary.EcosystemWordpressPlugins: { + "armadillo": dictionary.NewSet("cpe:2.3:a:armadillo:armadillo:1.23:*:*:*:*:wordpress:*:*"), + }, + }, + }, + }, + { + name: "addEntryForWordpressTheme", + addEntryFunc: addEntryForWordpressTheme, + inputRef: "https://wordpress.org/themes/basic/releases", + inputCpeItemName: "cpe:2.3:a:basic:basic:1.23:*:*:*:*:wordpress:*:*", + expectedIndexed: dictionary.Indexed{ + EcosystemPackages: map[string]dictionary.Packages{ + dictionary.EcosystemWordpressThemes: { + "basic": dictionary.NewSet("cpe:2.3:a:basic:basic:1.23:*:*:*:*:wordpress:*:*"), + }, + }, + }, + }, + { + name: "addEntryForWordpressTheme from Trac Browser", + addEntryFunc: addEntryForWordpressTheme, + inputRef: "https://themes.trac.wordpress.org/browser/basic/something", + inputCpeItemName: "cpe:2.3:a:basic:basic:1.23:*:*:*:*:wordpress:*:*", + expectedIndexed: dictionary.Indexed{ + EcosystemPackages: map[string]dictionary.Packages{ + dictionary.EcosystemWordpressThemes: { + "basic": dictionary.NewSet("cpe:2.3:a:basic:basic:1.23:*:*:*:*:wordpress:*:*"), + }, + }, + }, + }, + { + name: "addEntryForWordpressTheme from Trac Log", + addEntryFunc: addEntryForWordpressTheme, + inputRef: "https://themes.trac.wordpress.org/log/basic/log", + inputCpeItemName: "cpe:2.3:a:basic:basic:1.23:*:*:*:*:wordpress:*:*", + expectedIndexed: dictionary.Indexed{ + EcosystemPackages: map[string]dictionary.Packages{ + dictionary.EcosystemWordpressThemes: { + "basic": dictionary.NewSet("cpe:2.3:a:basic:basic:1.23:*:*:*:*:wordpress:*:*"), + }, + }, + }, + }, + { + name: "addEntryForWordpressTheme wordfence", + addEntryFunc: addEntryForWordpressTheme, + inputRef: "https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-themes/basic/skjfhskdjhf/12344", + inputCpeItemName: "cpe:2.3:a:basic:basic:1.23:*:*:*:*:wordpress:*:*", + expectedIndexed: dictionary.Indexed{ + EcosystemPackages: map[string]dictionary.Packages{ + dictionary.EcosystemWordpressThemes: { + "basic": dictionary.NewSet("cpe:2.3:a:basic:basic:1.23:*:*:*:*:wordpress:*:*"), + }, + }, + }, + }, } for _, tt := range tests { diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator/testdata/expected-cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator/testdata/expected-cpe-index.json index 294c687c9..132292c77 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator/testdata/expected-cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator/testdata/expected-cpe-index.json @@ -106,6 +106,58 @@ "unicycle": [ "cpe:2.3:a:unicycle_project:unicycle:*:*:*:*:*:rust:*:*" ] + }, + "wordpress_plugins": { + "0mk-shortener": [ + "cpe:2.3:a:0mk_shortener_project:0mk_shortener:*:*:*:*:*:wordpress:*:*" + ], + "jobboardwp": [ + "cpe:2.3:a:ultimatemember:jobboardwp:*:*:*:*:*:wordpress:*:*" + ], + "nofollow": [ + "cpe:2.3:a:ultimate_nofollow_project:ultimate_nofollow:*:*:*:*:*:wordpress:*:*" + ], + "petfinder-listings": [ + "cpe:2.3:a:unboxinteractive:petfinder-listings:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-instagram-feed": [ + "cpe:2.3:a:ultimate_instagram_feed_project:ultimate_instagram_feed:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-member": [ + "cpe:2.3:a:ultimatemember:ultimate_member:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:ultimatemember:user_profile_\\\u0026_membership:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-noindex-nofollow-tool-ii": [ + "cpe:2.3:a:ultimate_noindex_nofollow_tool_ii_project:ultimate_noindex_nofollow_tool_ii:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-sms-notifications": [ + "cpe:2.3:a:ultimatesmsnotifications:ultimate_sms_notifications_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-weather-plugin": [ + "cpe:2.3:a:ultimate-weather_project:ultimate-weather:*:*:*:*:*:wordpress:*:*" + ], + "ultimate-wp-query-search-filter": [ + "cpe:2.3:a:ultimate_wp_query_search_filter_project:ultimate_wp_query_search_filter:*:*:*:*:*:wordpress:*:*" + ], + "uncanny-automator": [ + "cpe:2.3:a:uncannyowl:uncanny_automator:*:*:*:*:*:wordpress:*:*" + ], + "uncanny-learndash-toolkit": [ + "cpe:2.3:a:uncannyowl:uncanny_toolkit_for_learndash:*:*:*:*:*:*:*:*", + "cpe:2.3:a:uncannyowl:uncanny_toolkit_for_learndash:*:*:*:*:*:wordpress:*:*" + ], + "unconfirmed": [ + "cpe:2.3:a:unconfirmed_project:unconfirmed:*:*:*:*:*:wordpress:*:*" + ], + "underconstruction": [ + "cpe:2.3:a:underconstruction_project:underconstruction:*:*:*:*:*:wordpress:*:*" + ], + "wp-cleanfix": [ + "cpe:2.3:a:undolog:wp_cleanfix:*:*:*:*:*:wordpress:*:*" + ], + "wp-ultra-simple-paypal-shopping-cart": [ + "cpe:2.3:a:ultra-prod:wordpress_ultra_simple_paypal_shopping_cart:*:*:*:*:*:wordpress:*:*" + ] } } } \ No newline at end of file diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator/testdata/official-cpe-dictionary_v2.3.xml b/syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator/testdata/official-cpe-dictionary_v2.3.xml index 6aeeba82f..0dd2651ee 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator/testdata/official-cpe-dictionary_v2.3.xml +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator/testdata/official-cpe-dictionary_v2.3.xml @@ -25093,6 +25093,14 @@ + + 0mk Shortener Project 0mk Shortener 0.2 for WordPress + + Advisory + Project + + + diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/types.go b/syft/pkg/cataloger/internal/cpegenerate/dictionary/types.go index e44477779..1b83655f4 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/types.go +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/types.go @@ -8,15 +8,17 @@ import ( ) const ( - EcosystemNPM = "npm" - EcosystemRubyGems = "rubygems" - EcosystemPyPI = "pypi" - EcosystemPHPPear = "php_pear" - EcosystemPHPPecl = "php_pecl" - EcosystemPHPComposer = "php_composer" - EcosystemJenkinsPlugins = "jenkins_plugins" - EcosystemRustCrates = "rust_crates" - EcosystemGoModules = "go_modules" + EcosystemNPM = "npm" + EcosystemRubyGems = "rubygems" + EcosystemPyPI = "pypi" + EcosystemPHPPear = "php_pear" + EcosystemPHPPecl = "php_pecl" + EcosystemPHPComposer = "php_composer" + EcosystemJenkinsPlugins = "jenkins_plugins" + EcosystemRustCrates = "rust_crates" + EcosystemGoModules = "go_modules" + EcosystemWordpressPlugins = "wordpress_plugins" + EcosystemWordpressThemes = "wordpress_themes" ) type Indexed struct { diff --git a/syft/pkg/cataloger/internal/cpegenerate/generate.go b/syft/pkg/cataloger/internal/cpegenerate/generate.go index 4860116a0..174076460 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/generate.go +++ b/syft/pkg/cataloger/internal/cpegenerate/generate.go @@ -96,6 +96,13 @@ func FromDictionaryFind(p pkg.Package) ([]cpe.CPE, bool) { case pkg.GoModulePkg: cpes, ok = dict.EcosystemPackages[dictionary.EcosystemGoModules][p.Name] + case pkg.WordpressPluginPkg: + metadata, valid := p.Metadata.(pkg.WordpressPluginEntry) + if !valid { + return parsedCPEs, false + } + cpes, ok = dict.EcosystemPackages[dictionary.EcosystemWordpressPlugins][metadata.PluginInstallDirectory] + default: // The dictionary doesn't support this package type yet. return parsedCPEs, false From 784b17f66c34a462d818a9568bddf1542ebaf839 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Jun 2024 08:18:25 -0700 Subject: [PATCH 040/284] chore(deps): bump github/codeql-action from 3.25.9 to 3.25.10 (#2964) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.9 to 3.25.10. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/530d4feaa9c62aaab2d250371e2061eb7a172363...23acc5c183826b7a8a97bce3cecc52db901f8251) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e555bdb22..648198a6e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@530d4feaa9c62aaab2d250371e2061eb7a172363 #v3.25.9 + uses: github/codeql-action/init@23acc5c183826b7a8a97bce3cecc52db901f8251 #v3.25.10 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@530d4feaa9c62aaab2d250371e2061eb7a172363 #v3.25.9 + uses: github/codeql-action/autobuild@23acc5c183826b7a8a97bce3cecc52db901f8251 #v3.25.10 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@530d4feaa9c62aaab2d250371e2061eb7a172363 #v3.25.9 + uses: github/codeql-action/analyze@23acc5c183826b7a8a97bce3cecc52db901f8251 #v3.25.10 From 70098e20bb2a9138743808b864371dc7843a5228 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Fri, 14 Jun 2024 08:18:41 -0700 Subject: [PATCH 041/284] chore(deps): update tools to latest versions (#2961) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index 15d5fc834..9dc99fa5c 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -111,7 +111,7 @@ tools: # used for triggering a release - name: gh version: - want: v2.50.0 + want: v2.51.0 method: github-release with: repo: cli/cli From af3aaa0397996d6431facebfbc7497af23e34e80 Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Fri, 14 Jun 2024 14:45:48 -0400 Subject: [PATCH 042/284] fix: make caching options more explicit (#2966) Signed-off-by: Keith Zantow --- cmd/syft/internal/options/cache.go | 49 +++++---- cmd/syft/internal/options/cache_test.go | 129 ++++++++++++++++++++++++ internal/cache/cache.go | 3 +- internal/cache/cache_test.go | 11 ++ internal/cache/memory.go | 3 + 5 files changed, 174 insertions(+), 21 deletions(-) diff --git a/cmd/syft/internal/options/cache.go b/cmd/syft/internal/options/cache.go index d8e4130a2..a8ee1c55f 100644 --- a/cmd/syft/internal/options/cache.go +++ b/cmd/syft/internal/options/cache.go @@ -24,29 +24,37 @@ type Cache struct { } func (c *Cache) DescribeFields(descriptions clio.FieldDescriptionSet) { - descriptions.Add(&c.Dir, "root directory to cache any downloaded content") - descriptions.Add(&c.TTL, "time to live for cached data") + descriptions.Add(&c.Dir, "root directory to cache any downloaded content; empty string will use an in-memory cache") + descriptions.Add(&c.TTL, "time to live for cached data; setting this to 0 will disable caching entirely") } func (c *Cache) PostLoad() error { - if c.Dir != "" { - ttl, err := parseDuration(c.TTL) - if err != nil { - log.Warnf("unable to parse duration '%v', using default (%s) due to: %v", c.TTL, durationToString(defaultTTL()), err) - ttl = defaultTTL() - } - dir, err := homedir.Expand(c.Dir) + ttl, err := parseDuration(c.TTL) + if err != nil { + log.Warnf("unable to parse duration '%v', using default (%s) due to: %v", c.TTL, durationToString(defaultTTL()), err) + ttl = defaultTTL() + } + // if TTL is <= 0, disable caching entirely + if ttl <= 0 { + cache.SetManager(nil) + return nil + } + // if dir == "" but we have a TTL, use an in-memory cache + if c.Dir == "" { + cache.SetManager(cache.NewInMemory(ttl)) + return nil + } + dir, err := homedir.Expand(c.Dir) + if err != nil { + log.Warnf("unable to expand cache directory %s: %v", c.Dir, err) + cache.SetManager(cache.NewInMemory(ttl)) + } else { + m, err := cache.NewFromDir(dir, ttl) if err != nil { - log.Warnf("unable to expand cache directory %s: %v", c.Dir, err) + log.Warnf("unable to get filesystem cache at %s: %v", c.Dir, err) cache.SetManager(cache.NewInMemory(ttl)) } else { - m, err := cache.NewFromDir(dir, ttl) - if err != nil { - log.Warnf("unable to get filesystem cache at %s: %v", c.Dir, err) - cache.SetManager(cache.NewInMemory(ttl)) - } else { - cache.SetManager(m) - } + cache.SetManager(m) } } return nil @@ -100,9 +108,8 @@ func durationToString(duration time.Duration) string { return out } -var whitespace = regexp.MustCompile(`\s+`) - func parseDuration(duration string) (time.Duration, error) { + whitespace := regexp.MustCompile(`\s+`) duration = strings.ToLower(whitespace.ReplaceAllString(duration, "")) parts := strings.SplitN(duration, "d", 2) var days time.Duration @@ -114,7 +121,9 @@ func parseDuration(duration string) (time.Duration, error) { return 0, daysErr } days = time.Duration(numDays) * 24 * time.Hour - remain, err = time.ParseDuration(parts[1]) + if len(parts[1]) > 0 { + remain, err = time.ParseDuration(parts[1]) + } } else { remain, err = time.ParseDuration(duration) } diff --git a/cmd/syft/internal/options/cache_test.go b/cmd/syft/internal/options/cache_test.go index e9bf92087..e4d527d3a 100644 --- a/cmd/syft/internal/options/cache_test.go +++ b/cmd/syft/internal/options/cache_test.go @@ -1,6 +1,7 @@ package options import ( + "io" "os" "path/filepath" "strings" @@ -10,6 +11,9 @@ import ( "github.com/adrg/xdg" "github.com/mitchellh/go-homedir" "github.com/stretchr/testify/require" + + "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/cache" ) func Test_defaultDir(t *testing.T) { @@ -91,12 +95,135 @@ func Test_defaultDir(t *testing.T) { } } +func Test_cacheOptions(t *testing.T) { + tmp := t.TempDir() + tests := []struct { + name string + opts Cache + test func(t *testing.T) + }{ + { + name: "disable-1", + opts: Cache{ + Dir: "some-dir", + TTL: "0", + }, + test: func(t *testing.T) { + c := cache.GetManager().GetCache("test-disable-1", "v-disable-1") + err := c.Write("key-disable-1", strings.NewReader("some-value-disable-1")) + require.NoError(t, err) + rdr, err := c.Read("key-disable-1") + require.Nil(t, rdr) + require.Error(t, err) + }, + }, + { + name: "disable-2", + opts: Cache{ + Dir: "some-dir", + TTL: "0s", + }, + test: func(t *testing.T) { + c := cache.GetManager().GetCache("test-disable-2", "v-disable-2") + err := c.Write("key-disable-2", strings.NewReader("some-value-disable-2")) + require.NoError(t, err) + rdr, err := c.Read("key-disable-2") + require.Nil(t, rdr) + require.Error(t, err) + }, + }, + + { + name: "disable-3", + opts: Cache{ + Dir: "some-dir", + TTL: "0d", + }, + test: func(t *testing.T) { + c := cache.GetManager().GetCache("test-disable-3", "v-disable-3") + err := c.Write("key-disable-3", strings.NewReader("some-value-disable-3")) + require.NoError(t, err) + rdr, err := c.Read("key-disable-3") + require.Nil(t, rdr) + require.Error(t, err) + }, + }, + { + name: "in-memory", + opts: Cache{ + Dir: "", + TTL: "10m", + }, + test: func(t *testing.T) { + c := cache.GetManager().GetCache("test-mem", "v-mem") + err := c.Write("key-mem", strings.NewReader("some-value-mem")) + require.NoError(t, err) + rdr, err := c.Read("key-mem") + require.NotNil(t, rdr) + defer internal.CloseAndLogError(rdr, "") + require.NoError(t, err) + data, err := io.ReadAll(rdr) + require.NoError(t, err) + require.Equal(t, "some-value-mem", string(data)) + require.NoDirExists(t, filepath.Join("test-mem", "v-mem")) + }, + }, + { + name: "on disk", + opts: Cache{ + Dir: tmp, + TTL: "10m", + }, + test: func(t *testing.T) { + c := cache.GetManager().GetCache("test-disk", "v-disk") + err := c.Write("key-disk", strings.NewReader("some-value-disk")) + require.NoError(t, err) + rdr, err := c.Read("key-disk") + require.NotNil(t, rdr) + defer internal.CloseAndLogError(rdr, "") + require.NoError(t, err) + data, err := io.ReadAll(rdr) + require.NoError(t, err) + require.Equal(t, "some-value-disk", string(data)) + require.DirExists(t, filepath.Join(tmp, "test-disk", "v-disk")) + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + original := cache.GetManager() + defer cache.SetManager(original) + + err := test.opts.PostLoad() + require.NoError(t, err) + + test.test(t) + }) + } +} + func Test_parseDuration(t *testing.T) { tests := []struct { duration string expect time.Duration err require.ErrorAssertionFunc }{ + { + duration: "0d", + expect: 0, + }, + { + duration: "0m", + expect: 0, + }, + { + duration: "0s", + expect: 0, + }, + { + duration: "0", + expect: 0, + }, { duration: "1d", expect: 24 * time.Hour, @@ -141,6 +268,8 @@ func Test_parseDuration(t *testing.T) { if test.err != nil { test.err(t, err) return + } else { + require.NoError(t, err) } require.Equal(t, test.expect, got) }) diff --git a/internal/cache/cache.go b/internal/cache/cache.go index 02208504e..3ca2ece98 100644 --- a/internal/cache/cache.go +++ b/internal/cache/cache.go @@ -36,7 +36,8 @@ func GetManager() Manager { return manager } -// SetManager sets the global cache manager, which is used to instantiate all caches +// SetManager sets the global cache manager, which is used to instantiate all caches. +// Setting this to nil disables caching. func SetManager(m Manager) { if m == nil { manager = &bypassedCache{} diff --git a/internal/cache/cache_test.go b/internal/cache/cache_test.go index 548a4b03b..2fceda3af 100644 --- a/internal/cache/cache_test.go +++ b/internal/cache/cache_test.go @@ -2,6 +2,7 @@ package cache import ( "testing" + "time" "github.com/stretchr/testify/require" ) @@ -10,8 +11,18 @@ func Test_SetManager(t *testing.T) { original := GetManager() defer SetManager(original) + SetManager(nil) + + require.NotNil(t, GetManager()) + require.IsType(t, &bypassedCache{}, GetManager()) + SetManager(NewInMemory(0)) + require.NotNil(t, GetManager()) + require.IsType(t, &bypassedCache{}, GetManager()) + + SetManager(NewInMemory(1 * time.Hour)) + require.NotNil(t, GetManager()) require.IsType(t, &filesystemCache{}, GetManager()) diff --git a/internal/cache/memory.go b/internal/cache/memory.go index 247e67e0d..696f8c9be 100644 --- a/internal/cache/memory.go +++ b/internal/cache/memory.go @@ -8,6 +8,9 @@ import ( // NewInMemory returns an in-memory only cache manager func NewInMemory(ttl time.Duration) Manager { + if ttl <= 0 { + return &bypassedCache{} + } return &filesystemCache{ dir: "", fs: afero.NewMemMapFs(), From 22d57314826fce1bff469d8173884489f8212925 Mon Sep 17 00:00:00 2001 From: Christopher Angelo Phillips <32073428+spiffcs@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:32:17 -0700 Subject: [PATCH 043/284] fix: fix parsing for complex toml types (#2965) * fix: fix parsing for complex toml types --------- Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> Signed-off-by: Alex Goodman Co-authored-by: Alex Goodman --- go.mod | 1 + go.sum | 2 + .../pkg/cataloger/python/parse_poetry_lock.go | 106 ++++++++---------- .../python/parse_poetry_lock_test.go | 4 + .../test-fixtures/poetry/dev-deps/poetry.lock | 7 ++ 5 files changed, 61 insertions(+), 59 deletions(-) diff --git a/go.mod b/go.mod index 3c345cef0..07038673d 100644 --- a/go.mod +++ b/go.mod @@ -87,6 +87,7 @@ require ( require google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect require ( + github.com/BurntSushi/toml v1.4.0 github.com/adrg/xdg v0.4.0 github.com/magiconair/properties v1.8.7 ) diff --git a/go.sum b/go.sum index 1605ba10b..b97838b46 100644 --- a/go.sum +++ b/go.sum @@ -57,6 +57,8 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg6 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/CycloneDX/cyclonedx-go v0.9.0 h1:inaif7qD8bivyxp7XLgxUYtOXWtDez7+j72qKTMQTb8= github.com/CycloneDX/cyclonedx-go v0.9.0/go.mod h1:NE/EWvzELOFlG6+ljX/QeMlVt9VKcTwu8u0ccsACEsw= diff --git a/syft/pkg/cataloger/python/parse_poetry_lock.go b/syft/pkg/cataloger/python/parse_poetry_lock.go index dbc702d53..84e67ddb5 100644 --- a/syft/pkg/cataloger/python/parse_poetry_lock.go +++ b/syft/pkg/cataloger/python/parse_poetry_lock.go @@ -4,10 +4,10 @@ import ( "context" "fmt" "sort" - "strings" - "github.com/pelletier/go-toml" + "github.com/BurntSushi/toml" + "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -19,7 +19,9 @@ import ( var _ generic.Parser = parsePoetryLock type poetryPackageSource struct { - URL string `toml:"url"` + URL string `toml:"url"` + Type string `toml:"type"` + Reference string `toml:"reference"` } type poetryPackages struct { @@ -27,14 +29,15 @@ type poetryPackages struct { } type poetryPackage struct { - Name string `toml:"name"` - Version string `toml:"version"` - Category string `toml:"category"` - Description string `toml:"description"` - Optional bool `toml:"optional"` - Source poetryPackageSource `toml:"source"` - Dependencies map[string]poetryPackageDependency `toml:"dependencies"` - Extras map[string][]string `toml:"extras"` + Name string `toml:"name"` + Version string `toml:"version"` + Category string `toml:"category"` + Description string `toml:"description"` + Optional bool `toml:"optional"` + Source poetryPackageSource `toml:"source"` + DependenciesUnmarshal map[string]toml.Primitive `toml:"dependencies"` + Extras map[string][]string `toml:"extras"` + Dependencies map[string][]poetryPackageDependency } type poetryPackageDependency struct { @@ -44,41 +47,6 @@ type poetryPackageDependency struct { Extras []string `toml:"extras"` } -func (d *poetryPackageDependency) UnmarshalText(data []byte) error { - // attempt to parse as a map first - var dep map[string]interface{} - if err := toml.Unmarshal(data, &dep); err == nil { - if extras, ok := dep["extras"]; ok { - if extrasList, ok := extras.([]string); ok { - d.Extras = extrasList - } - } - - if markers, ok := dep["markers"]; ok { - if markersString, ok := markers.(string); ok { - d.Markers = markersString - } - } - - if version, ok := dep["version"]; ok { - if versionString, ok := version.(string); ok { - d.Version = versionString - } - } - return nil - } - - if strings.ContainsAny(string(data), "[]{}") { - // odds are this is really a malformed toml array or object - return fmt.Errorf("unable to parse poetry dependency: version is malformed array/object: %q", string(data)) - } - - // assume this is a simple version string - d.Version = string(data) - - return nil -} - // parsePoetryLock is a parser function for poetry.lock contents, returning all python packages discovered. func parsePoetryLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { pkgs, err := poetryLockPackages(reader) @@ -93,15 +61,33 @@ func parsePoetryLock(_ context.Context, _ file.Resolver, _ *generic.Environment, } func poetryLockPackages(reader file.LocationReadCloser) ([]pkg.Package, error) { - tree, err := toml.LoadReader(reader) + metadata := poetryPackages{} + md, err := toml.NewDecoder(reader).Decode(&metadata) if err != nil { - return nil, fmt.Errorf("unable to load poetry.lock for parsing: %w", err) + return nil, fmt.Errorf("failed to read poetry lock package: %w", err) } - metadata := poetryPackages{} - err = tree.Unmarshal(&metadata) - if err != nil { - return nil, fmt.Errorf("unable to parse poetry.lock: %w", err) + for i, p := range metadata.Packages { + dependencies := make(map[string][]poetryPackageDependency) + for pkgName, du := range p.DependenciesUnmarshal { + var ( + single string + singleObj poetryPackageDependency + multiObj []poetryPackageDependency + ) + + switch { + case md.PrimitiveDecode(du, &single) == nil: + dependencies[pkgName] = append(dependencies[pkgName], poetryPackageDependency{Version: single}) + case md.PrimitiveDecode(du, &singleObj) == nil: + dependencies[pkgName] = append(dependencies[pkgName], singleObj) + case md.PrimitiveDecode(du, &multiObj) == nil: + dependencies[pkgName] = append(dependencies[pkgName], multiObj...) + default: + log.Trace("failed to decode poetry lock package dependencies for %s; skipping", pkgName) + } + } + metadata.Packages[i].Dependencies = dependencies } var pkgs []pkg.Package @@ -137,13 +123,15 @@ func extractIndex(p poetryPackage) string { func extractPoetryDependencies(p poetryPackage) []pkg.PythonPoetryLockDependencyEntry { var deps []pkg.PythonPoetryLockDependencyEntry - for name, dep := range p.Dependencies { - deps = append(deps, pkg.PythonPoetryLockDependencyEntry{ - Name: name, - Version: dep.Version, - Extras: dep.Extras, - Markers: dep.Markers, - }) + for name, dependencies := range p.Dependencies { + for _, d := range dependencies { + deps = append(deps, pkg.PythonPoetryLockDependencyEntry{ + Name: name, + Version: d.Version, + Extras: d.Extras, + Markers: d.Markers, + }) + } } sort.Slice(deps, func(i, j int) bool { return deps[i].Name < deps[j].Name diff --git a/syft/pkg/cataloger/python/parse_poetry_lock_test.go b/syft/pkg/cataloger/python/parse_poetry_lock_test.go index b590be47f..1a6c1beb7 100644 --- a/syft/pkg/cataloger/python/parse_poetry_lock_test.go +++ b/syft/pkg/cataloger/python/parse_poetry_lock_test.go @@ -24,7 +24,11 @@ func TestParsePoetryLock(t *testing.T) { Index: "https://test.pypi.org/simple", Dependencies: []pkg.PythonPoetryLockDependencyEntry{ {Name: "docutils", Version: "*"}, + {Name: "msal", Version: ">=0.4.1,<2.0.0"}, {Name: "natsort", Version: "*"}, + {Name: "packaging", Version: "*"}, + {Name: "portalocker", Version: ">=1.0,<3", Markers: `platform_system != "Windows"`}, + {Name: "portalocker", Version: ">=1.6,<3", Markers: `platform_system == "Windows"`}, {Name: "six", Version: "*"}, {Name: "sphinx", Version: "*"}, }, diff --git a/syft/pkg/cataloger/python/test-fixtures/poetry/dev-deps/poetry.lock b/syft/pkg/cataloger/python/test-fixtures/poetry/dev-deps/poetry.lock index 6d20352ff..3b3f2078d 100644 --- a/syft/pkg/cataloger/python/test-fixtures/poetry/dev-deps/poetry.lock +++ b/syft/pkg/cataloger/python/test-fixtures/poetry/dev-deps/poetry.lock @@ -11,6 +11,13 @@ docutils = "*" natsort = "*" six = "*" sphinx = "*" +packaging = "*" +msal = {version = ">=0.4.1,<2.0.0"} +malformed = [ [ { version = "1.2" } ] ] +portalocker = [ + {version = ">=1.0,<3", markers = "platform_system != \"Windows\""}, + {version = ">=1.6,<3", markers = "platform_system == \"Windows\""}, +] [package.source] type = "legacy" From ed3774afa73a197cc6a244e1488c69cfa77cce77 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jun 2024 08:44:10 -0700 Subject: [PATCH 044/284] chore(deps): bump github.com/spf13/cobra from 1.8.0 to 1.8.1 (#2972) Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.8.0 to 1.8.1. - [Release notes](https://github.com/spf13/cobra/releases) - [Commits](https://github.com/spf13/cobra/compare/v1.8.0...v1.8.1) --- updated-dependencies: - dependency-name: github.com/spf13/cobra dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 07038673d..8267c0443 100644 --- a/go.mod +++ b/go.mod @@ -69,7 +69,7 @@ require ( github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 github.com/spdx/tools-golang v0.5.4 github.com/spf13/afero v1.11.0 - github.com/spf13/cobra v1.8.0 + github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 github.com/vbatts/go-mtree v0.5.4 github.com/vifraa/gopom v1.0.0 diff --git a/go.sum b/go.sum index b97838b46..837505cf5 100644 --- a/go.sum +++ b/go.sum @@ -211,7 +211,7 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= @@ -737,8 +737,8 @@ github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= From 5061b905dc3f8e74dbdb9faf525e50dd0b14db27 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jun 2024 08:44:19 -0700 Subject: [PATCH 045/284] chore(deps): bump github.com/google/go-containerregistry (#2971) Bumps [github.com/google/go-containerregistry](https://github.com/google/go-containerregistry) from 0.19.1 to 0.19.2. - [Release notes](https://github.com/google/go-containerregistry/releases) - [Changelog](https://github.com/google/go-containerregistry/blob/main/.goreleaser.yml) - [Commits](https://github.com/google/go-containerregistry/compare/v0.19.1...v0.19.2) --- updated-dependencies: - dependency-name: github.com/google/go-containerregistry dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8267c0443..8dd9aa23d 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/go-git/go-git/v5 v5.12.0 github.com/go-test/deep v1.1.0 github.com/google/go-cmp v0.6.0 - github.com/google/go-containerregistry v0.19.1 + github.com/google/go-containerregistry v0.19.2 github.com/google/licensecheck v0.3.1 github.com/google/uuid v1.6.0 github.com/gookit/color v1.5.4 diff --git a/go.sum b/go.sum index 837505cf5..fc40beb9d 100644 --- a/go.sum +++ b/go.sum @@ -384,8 +384,8 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.19.1 h1:yMQ62Al6/V0Z7CqIrrS1iYoA5/oQCm88DeNujc7C1KY= -github.com/google/go-containerregistry v0.19.1/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI= +github.com/google/go-containerregistry v0.19.2 h1:TannFKE1QSajsP6hPWb5oJNgKe1IKjHukIKDUmvsV6w= +github.com/google/go-containerregistry v0.19.2/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/licensecheck v0.3.1 h1:QoxgoDkaeC4nFrtGN1jV7IPmDCHFNIVh54e5hSt6sPs= github.com/google/licensecheck v0.3.1/go.mod h1:ORkR35t/JjW+emNKtfJDII0zlciG9JgbT7SmsohlHmY= From 750d37f075a4c047fb155dafa77db54e77207cc8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 09:46:11 -0700 Subject: [PATCH 046/284] chore(deps): bump github.com/github/go-spdx/v2 from 2.2.0 to 2.3.1 (#2973) Bumps [github.com/github/go-spdx/v2](https://github.com/github/go-spdx) from 2.2.0 to 2.3.1. - [Release notes](https://github.com/github/go-spdx/releases) - [Commits](https://github.com/github/go-spdx/compare/v2.2.0...v2.3.1) --- updated-dependencies: - dependency-name: github.com/github/go-spdx/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8dd9aa23d..fdfa76520 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/dustin/go-humanize v1.0.1 github.com/elliotchance/phpserialize v1.4.0 github.com/facebookincubator/nvdtools v0.1.5 - github.com/github/go-spdx/v2 v2.2.0 + github.com/github/go-spdx/v2 v2.3.1 github.com/gkampitakis/go-snaps v0.5.4 github.com/go-git/go-billy/v5 v5.5.0 github.com/go-git/go-git/v5 v5.12.0 diff --git a/go.sum b/go.sum index fc40beb9d..5136e8594 100644 --- a/go.sum +++ b/go.sum @@ -287,8 +287,8 @@ github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyT github.com/gabriel-vasile/mimetype v1.4.0 h1:Cn9dkdYsMIu56tGho+fqzh7XmvY2YyGU0FnbhiOsEro= github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/github/go-spdx/v2 v2.2.0 h1:yBBLMasHA70Ujd35OpL/OjJOWWVNXcJGbars0GinGRI= -github.com/github/go-spdx/v2 v2.2.0/go.mod h1:hMCrsFgT0QnCwn7G8gxy/MxMpy67WgZrwFeISTn0o6w= +github.com/github/go-spdx/v2 v2.3.1 h1:ffGuHTbHuHzWPt53n8f9o8clGutuLPObo3zB4JAjxU8= +github.com/github/go-spdx/v2 v2.3.1/go.mod h1:2ZxKsOhvBp+OYBDlsGnUMcchLeo2mrpEBn2L1C+U3IQ= github.com/gkampitakis/ciinfo v0.3.0 h1:gWZlOC2+RYYttL0hBqcoQhM7h1qNkVqvRCV1fOvpAv8= github.com/gkampitakis/ciinfo v0.3.0/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= From 246df97ae750bb159be10c8c2cb935d844f0e680 Mon Sep 17 00:00:00 2001 From: Weston Steimel Date: Wed, 19 Jun 2024 20:17:11 +0100 Subject: [PATCH 047/284] chore: enable dependabot to keep boostrap action updated (#2976) Signed-off-by: Weston Steimel --- .github/actions/bootstrap/action.yaml | 4 ++-- .github/dependabot.yml | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/actions/bootstrap/action.yaml b/.github/actions/bootstrap/action.yaml index e351c8392..bc771d3b5 100644 --- a/.github/actions/bootstrap/action.yaml +++ b/.github/actions/bootstrap/action.yaml @@ -27,14 +27,14 @@ runs: using: "composite" steps: # note: go mod and build is automatically cached on default with v4+ - - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 #v5.0.1 + - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 if: inputs.go-version != '' with: go-version: ${{ inputs.go-version }} - name: Restore tool cache id: tool-cache - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2 + uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 with: path: ${{ github.workspace }}/.tool key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-tool-${{ hashFiles('.binny.yaml') }} diff --git a/.github/dependabot.yml b/.github/dependabot.yml index bcdb6f8f3..0009183a7 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -17,3 +17,11 @@ updates: open-pull-requests-limit: 10 labels: - "dependencies" + + - package-ecosystem: "github-actions" + directory: "/.github/actions/boostrap" + schedule: + interval: "daily" + open-pull-requests-limit: 10 + labels: + - "dependencies" From 7a35de04ee9537fe4ba6cfc57dc04c68d16a014a Mon Sep 17 00:00:00 2001 From: Laurent Goderre Date: Thu, 20 Jun 2024 11:11:03 -0400 Subject: [PATCH 048/284] fix: detection of arangodb 3.12 (#2979) Signed-off-by: Laurent Goderre --- .../cataloger/binary/classifier_cataloger_test.go | 11 +++++++++++ syft/pkg/cataloger/binary/classifiers.go | 2 +- .../arangodb/3.12.0-2/linux-amd64/arangosh | Bin 0 -> 351 bytes .../cataloger/binary/test-fixtures/config.yaml | 7 +++++++ 4 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/arangodb/3.12.0-2/linux-amd64/arangosh diff --git a/syft/pkg/cataloger/binary/classifier_cataloger_test.go b/syft/pkg/cataloger/binary/classifier_cataloger_test.go index e0f71998d..595bbd0f6 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger_test.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger_test.go @@ -48,6 +48,17 @@ func Test_Cataloger_PositiveCases(t *testing.T) { Metadata: metadata("arangodb-binary"), }, }, + { + logicalFixture: "arangodb/3.12.0-2/linux-amd64", + expected: pkg.Package{ + Name: "arangodb", + Version: "3.12.0-2", + Type: "binary", + PURL: "pkg:generic/arangodb@3.12.0-2", + Locations: locations("arangosh"), + Metadata: metadata("arangodb-binary"), + }, + }, { logicalFixture: "postgres/15beta4/linux-amd64", expected: pkg.Package{ diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index 229c51339..fb17f0ff2 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -272,7 +272,7 @@ func DefaultClassifiers() []Classifier { Class: "arangodb-binary", FileGlob: "**/arangosh", EvidenceMatcher: FileContentsVersionMatcher( - `(?m)ArangoDB\s\x00*(?P[0-9]+\.[0-9]+\.[0-9]+)\s\[linux\]`), + `(?m)\x00*(?P[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?)\s\[linux\]`), Package: "arangodb", PURL: mustPURL("pkg:generic/arangodb@version"), CPEs: singleCPE("cpe:2.3:a:arangodb:arangodb:*:*:*:*:*:*:*:*"), diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/arangodb/3.12.0-2/linux-amd64/arangosh b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/arangodb/3.12.0-2/linux-amd64/arangosh new file mode 100644 index 0000000000000000000000000000000000000000..da68e07d810738691bb737e902a8964cca69a545 GIT binary patch literal 351 zcmXxeyH3O~6a-M$`3g(hK#|CAI}sff9ReW=L~(6jZ;V15CEjKC?+FOnGn&!N@QDM3 z73O2v#-^mSVI8OzTru8EI3MdcP%c=r&3Rd{K93-@8K?u{c<_-a-U|p!D=A;P05sZu+Qb<0^-UoEjFwvwu;s2ObXuMZkI;D+8D}z?D=axtCy+s*4?&y+b zd}oePrzk?OAWW2wrKUL?4%A;O(!ZOu7MjX5l`pzSO~*yYIzfLL!Whtr5&4U)pl?&2 zPnUP{aQ{L{+kU_qwy@@!XsWDA+JOx$0PB1 OhV}Zo=889WTm1%jxn?y0 literal 0 HcmV?d00001 diff --git a/syft/pkg/cataloger/binary/test-fixtures/config.yaml b/syft/pkg/cataloger/binary/test-fixtures/config.yaml index 3930bfe39..559b36e63 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/config.yaml +++ b/syft/pkg/cataloger/binary/test-fixtures/config.yaml @@ -285,6 +285,13 @@ from-images: platform: linux/amd64 paths: - /usr/bin/arangosh + - name: arangodb + version: 3.12.0-2 + images: + - ref: arangodb:3.12.0.2@sha256:6ba2e4284cd0f4835e3ef034be90fb947c3d61225d65d07e3b2d2d893e47de25 + platform: linux/amd64 + paths: + - /usr/bin/arangosh - version: 15.1 images: - ref: postgres:15.1@sha256:b4140dd3a62f364f16a82c1bd88d28b9887ecb47f07dbe2941237d073574d428 From e9477798865e1ad3115255a88270a11ec05ac432 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:12:12 +0000 Subject: [PATCH 049/284] chore(deps): bump peter-evans/create-pull-request from 6.0.5 to 6.1.0 (#2975) --- .github/workflows/update-bootstrap-tools.yml | 2 +- .github/workflows/update-cpe-dictionary-index.yml | 2 +- .github/workflows/update-stereoscope-release.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/update-bootstrap-tools.yml b/.github/workflows/update-bootstrap-tools.yml index a32b5f9ac..9518a233f 100644 --- a/.github/workflows/update-bootstrap-tools.yml +++ b/.github/workflows/update-bootstrap-tools.yml @@ -50,7 +50,7 @@ jobs: app_id: ${{ secrets.TOKEN_APP_ID }} private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e #v6.0.5 + - uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c #v6.1.0 with: signoff: true delete-branch: true diff --git a/.github/workflows/update-cpe-dictionary-index.yml b/.github/workflows/update-cpe-dictionary-index.yml index 5e324ef68..18d3e2d14 100644 --- a/.github/workflows/update-cpe-dictionary-index.yml +++ b/.github/workflows/update-cpe-dictionary-index.yml @@ -33,7 +33,7 @@ jobs: app_id: ${{ secrets.TOKEN_APP_ID }} private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e #v6.0.5 + - uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c #v6.1.0 with: signoff: true delete-branch: true diff --git a/.github/workflows/update-stereoscope-release.yml b/.github/workflows/update-stereoscope-release.yml index feaec61cd..894d04c7f 100644 --- a/.github/workflows/update-stereoscope-release.yml +++ b/.github/workflows/update-stereoscope-release.yml @@ -44,7 +44,7 @@ jobs: app_id: ${{ secrets.TOKEN_APP_ID }} private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e #v6.0.5 + - uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c #v6.1.0 with: signoff: true delete-branch: true From 9b178174a760fbc60f7d9adb7942fa79b95d8670 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Jun 2024 08:46:35 -0700 Subject: [PATCH 050/284] chore(deps): bump github.com/charmbracelet/bubbletea (#2982) Bumps [github.com/charmbracelet/bubbletea](https://github.com/charmbracelet/bubbletea) from 0.26.4 to 0.26.5. - [Release notes](https://github.com/charmbracelet/bubbletea/releases) - [Changelog](https://github.com/charmbracelet/bubbletea/blob/master/.goreleaser.yml) - [Commits](https://github.com/charmbracelet/bubbletea/compare/v0.26.4...v0.26.5) --- updated-dependencies: - dependency-name: github.com/charmbracelet/bubbletea dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index fdfa76520..5d8fe85f4 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 github.com/bmatcuk/doublestar/v4 v4.6.1 github.com/charmbracelet/bubbles v0.18.0 - github.com/charmbracelet/bubbletea v0.26.4 + github.com/charmbracelet/bubbletea v0.26.5 github.com/charmbracelet/lipgloss v0.11.0 github.com/dave/jennifer v1.7.0 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da diff --git a/go.sum b/go.sum index 5136e8594..b567e8140 100644 --- a/go.sum +++ b/go.sum @@ -157,8 +157,8 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0= github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw= -github.com/charmbracelet/bubbletea v0.26.4 h1:2gDkkzLZaTjMl/dQBpNVtnvcCxsh/FCkimep7FC9c40= -github.com/charmbracelet/bubbletea v0.26.4/go.mod h1:P+r+RRA5qtI1DOHNFn0otoNwB4rn+zNAzSj/EXz6xU0= +github.com/charmbracelet/bubbletea v0.26.5 h1:90pqTPElAReb/qQUgSMUresTkfwVr0Wx+zczeHHOgxk= +github.com/charmbracelet/bubbletea v0.26.5/go.mod h1:dz8CWPlfCCGLFbBlTY4N7bjLiyOGDJEnd2Muu7pOWhk= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v0.11.0 h1:UoAcbQ6Qml8hDwSWs0Y1cB5TEQuZkDPH/ZqwWWYTG4g= From ae0683074eae40a8f803152063f4d82c9659ab19 Mon Sep 17 00:00:00 2001 From: Rajan Agaskar Date: Fri, 21 Jun 2024 08:51:27 -0700 Subject: [PATCH 051/284] feat: update syft to generate cyclone-dx 1.6 by default (#2978) - Resolves #2974 - add detailed instructions re: updating schemas (a necessary task when a new CycloneDX spec version becomes available). - The DefaultVersion constant has been updated to "1.6" -- it's not clear to me how this is used at this time (it may be redundant given other code), but effectively unless a specific spec version is configured, `syft` will emit the "most recent" spec version available for cyclonedx. Users who wish to pin back to a "older" specVersion (e.g. to preserve compatibilty with utilities that have not yet bumped to latest) can either set this in a syft config file or pass a name@spec_version pair to the output flag (e.g. `-o cyclonedx-json@1.5=some-1.5-spec-bom.cdx.json`) - Regenerate relevant .golden files (there seems to be a way to do this via flags, but I couldn't quite figure out the right set to pass correctly, esp. since (as a relative go novice) I found it difficult to run just a single test file. I ended up "brute-forcing it" by changing the *updateSnapshot val to "true" and running it in Goland. A brief comment giving an example of regenerating fixtures usage would be helpful. Signed-off-by: Rajan Agaskar --- schema/cyclonedx/README.md | 9 + schema/cyclonedx/cyclonedx.json | 2342 ++++++- schema/cyclonedx/cyclonedx.xsd | 6148 ++++++++++++----- schema/cyclonedx/spdx.xsd | 127 +- .../test-fixtures/identify/1.6.json | 59 + .../test-fixtures/identify/micronaut-1.6.json | 28 + .../TestCycloneDxDirectoryEncoder.golden | 4 +- .../snapshot/TestCycloneDxImageEncoder.golden | 4 +- .../test-fixtures/identify/1.6.xml | 33 + .../TestCycloneDxDirectoryEncoder.golden | 2 +- .../snapshot/TestCycloneDxImageEncoder.golden | 2 +- syft/format/internal/cyclonedxutil/encoder.go | 2 +- .../format/internal/cyclonedxutil/versions.go | 5 + 13 files changed, 6862 insertions(+), 1903 deletions(-) create mode 100644 syft/format/cyclonedxjson/test-fixtures/identify/1.6.json create mode 100644 syft/format/cyclonedxjson/test-fixtures/identify/micronaut-1.6.json create mode 100644 syft/format/cyclonedxxml/test-fixtures/identify/1.6.xml diff --git a/schema/cyclonedx/README.md b/schema/cyclonedx/README.md index 64ae62a52..08f16ad52 100644 --- a/schema/cyclonedx/README.md +++ b/schema/cyclonedx/README.md @@ -7,3 +7,12 @@ For this reason we've included a copy of all schemas needed to validate `syft` o to reference local copies of dependent schemas. You can get the latest schemas from the [CycloneDX specifications repo](https://github.com/CycloneDX/specification/tree/master/schema). + +When the spec version is bumped an approach to determining prior modifications is to compare the +prior spec version (e.g. if updating to 1.7, compare the files in this directory against the 1.6 +equivalents). + +One can also update the schemas and observe the errors in order to make the necessary updates. +At the time of writing, the cyclonedx.xsd needed modifications to link to the local spdx.xsd, +and also to changes the minOccurs for a license tag to 0. (The json schema does not require +modification for the generated file to lint properly, but can simply be copy/pasted). diff --git a/schema/cyclonedx/cyclonedx.json b/schema/cyclonedx/cyclonedx.json index 14ba745f0..e49dc52e6 100644 --- a/schema/cyclonedx/cyclonedx.json +++ b/schema/cyclonedx/cyclonedx.json @@ -1,8 +1,8 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "http://cyclonedx.org/schema/bom-1.5.schema.json", + "$id": "http://cyclonedx.org/schema/bom-1.6.schema.json", "type": "object", - "title": "CycloneDX Software Bill of Materials Standard", + "title": "CycloneDX Bill of Materials Standard", "$comment" : "CycloneDX JSON schema is published under the terms of the Apache License 2.0.", "required": [ "bomFormat", @@ -11,15 +11,12 @@ "additionalProperties": false, "properties": { "$schema": { - "type": "string", - "enum": [ - "http://cyclonedx.org/schema/bom-1.5.schema.json" - ] + "type": "string" }, "bomFormat": { "type": "string", "title": "BOM Format", - "description": "Specifies the format of the BOM. This helps to identify the file as CycloneDX since BOMs do not have a filename convention nor does JSON schema support namespaces. This value MUST be \"CycloneDX\".", + "description": "Specifies the format of the BOM. This helps to identify the file as CycloneDX since BOMs do not have a filename convention, nor does JSON schema support namespaces. This value MUST be \"CycloneDX\".", "enum": [ "CycloneDX" ] @@ -27,13 +24,13 @@ "specVersion": { "type": "string", "title": "CycloneDX Specification Version", - "description": "The version of the CycloneDX specification a BOM conforms to (starting at version 1.2).", - "examples": ["1.5"] + "description": "The version of the CycloneDX specification the BOM conforms to.", + "examples": ["1.6"] }, "serialNumber": { "type": "string", "title": "BOM Serial Number", - "description": "Every BOM generated SHOULD have a unique serial number, even if the contents of the BOM have not changed over time. If specified, the serial number MUST conform to RFC-4122. Use of serial numbers are RECOMMENDED.", + "description": "Every BOM generated SHOULD have a unique serial number, even if the contents of the BOM have not changed over time. If specified, the serial number MUST conform to RFC-4122. Use of serial numbers is RECOMMENDED.", "examples": ["urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79"], "pattern": "^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" }, @@ -68,14 +65,14 @@ "type": "array", "items": {"$ref": "#/definitions/externalReference"}, "title": "External References", - "description": "External references provide a way to document systems, sites, and information that may be relevant, but are not included with the BOM. They may also establish specific relationships within or external to the BOM." + "description": "External references provide a way to document systems, sites, and information that may be relevant but are not included with the BOM. They may also establish specific relationships within or external to the BOM." }, "dependencies": { "type": "array", "items": {"$ref": "#/definitions/dependency"}, "uniqueItems": true, "title": "Dependencies", - "description": "Provides the ability to document dependency relationships." + "description": "Provides the ability to document dependency relationships including provided & implemented components." }, "compositions": { "type": "array", @@ -96,7 +93,7 @@ "items": {"$ref": "#/definitions/annotations"}, "uniqueItems": true, "title": "Annotations", - "description": "Comments made by people, organizations, or tools about any object with a bom-ref, such as components, services, vulnerabilities, or the BOM itself. Unlike inventory information, annotations may contain opinion or commentary from various stakeholders. Annotations may be inline (with inventory) or externalized via BOM-Link, and may optionally be signed." + "description": "Comments made by people, organizations, or tools about any object with a bom-ref, such as components, services, vulnerabilities, or the BOM itself. Unlike inventory information, annotations may contain opinions or commentary from various stakeholders. Annotations may be inline (with inventory) or externalized via BOM-Link and may optionally be signed." }, "formulation": { "type": "array", @@ -105,6 +102,420 @@ "title": "Formulation", "description": "Describes how a component or service was manufactured or deployed. This is achieved through the use of formulas, workflows, tasks, and steps, which declare the precise steps to reproduce along with the observed formulas describing the steps which transpired in the manufacturing process." }, + "declarations": { + "type": "object", + "title": "Declarations", + "description": "The list of declarations which describe the conformance to standards. Each declaration may include attestations, claims, and evidence.", + "additionalProperties": false, + "properties": { + "assessors": { + "type": "array", + "title": "Assessors", + "description": "The list of assessors evaluating claims and determining conformance to requirements and confidence in that assessment.", + "items": { + "type": "object", + "title": "Assessor", + "description": "The assessor who evaluates claims and determines conformance to requirements and confidence in that assessment.", + "additionalProperties": false, + "properties": { + "bom-ref": { + "$ref": "#/definitions/refType", + "title": "BOM Reference", + "description": "An optional identifier which can be used to reference the object elsewhere in the BOM. Every bom-ref MUST be unique within the BOM." + }, + "thirdParty": { + "type": "boolean", + "title": "Third Party", + "description": "The boolean indicating if the assessor is outside the organization generating claims. A value of false indicates a self assessor." + }, + "organization": { + "$ref": "#/definitions/organizationalEntity", + "title": "Organization", + "description": "The entity issuing the assessment." + } + } + } + }, + "attestations": { + "type": "array", + "title": "Attestations", + "description": "The list of attestations asserted by an assessor that maps requirements to claims.", + "items": { + "type": "object", + "title": "Attestation", + "additionalProperties": false, + "properties": { + "summary": { + "type": "string", + "title": "Summary", + "description": "The short description explaining the main points of the attestation." + }, + "assessor": { + "$ref": "#/definitions/refLinkType", + "title": "Assessor", + "description": "The `bom-ref` to the assessor asserting the attestation." + }, + "map": { + "type": "array", + "title": "Map", + "description": "The grouping of requirements to claims and the attestors declared conformance and confidence thereof.", + "items": { + "type": "object", + "title": "Map", + "additionalProperties": false, + "properties": { + "requirement": { + "$ref": "#/definitions/refLinkType", + "title": "Requirement", + "description": "The `bom-ref` to the requirement being attested to." + }, + "claims": { + "type": "array", + "title": "Claims", + "description": "The list of `bom-ref` to the claims being attested to.", + "items": { "$ref": "#/definitions/refLinkType" } + }, + "counterClaims": { + "type": "array", + "title": "Counter Claims", + "description": "The list of `bom-ref` to the counter claims being attested to.", + "items": { "$ref": "#/definitions/refLinkType" } + }, + "conformance": { + "type": "object", + "title": "Conformance", + "description": "The conformance of the claim meeting a requirement.", + "additionalProperties": false, + "properties": { + "score": { + "type": "number", + "minimum": 0, + "maximum": 1, + "title": "Score", + "description": "The conformance of the claim between and inclusive of 0 and 1, where 1 is 100% conformance." + }, + "rationale": { + "type": "string", + "title": "Rationale", + "description": "The rationale for the conformance score." + }, + "mitigationStrategies": { + "type": "array", + "title": "Mitigation Strategies", + "description": "The list of `bom-ref` to the evidence provided describing the mitigation strategies.", + "items": { "$ref": "#/definitions/refLinkType" } + } + } + }, + "confidence": { + "type": "object", + "title": "Confidence", + "description": "The confidence of the claim meeting the requirement.", + "additionalProperties": false, + "properties": { + "score": { + "type": "number", + "minimum": 0, + "maximum": 1, + "title": "Score", + "description": "The confidence of the claim between and inclusive of 0 and 1, where 1 is 100% confidence." + }, + "rationale": { + "type": "string", + "title": "Rationale", + "description": "The rationale for the confidence score." + } + } + } + } + } + }, + "signature": { + "$ref": "#/definitions/signature", + "title": "Signature", + "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)." + } + } + } + }, + "claims": { + "type": "array", + "title": "Claims", + "description": "The list of claims.", + "items": { + "type": "object", + "title": "Claim", + "additionalProperties": false, + "properties": { + "bom-ref": { + "$ref": "#/definitions/refType", + "title": "BOM Reference", + "description": "An optional identifier which can be used to reference the object elsewhere in the BOM. Every bom-ref MUST be unique within the BOM." + }, + "target": { + "$ref": "#/definitions/refLinkType", + "title": "Target", + "description": "The `bom-ref` to a target representing a specific system, application, API, module, team, person, process, business unit, company, etc... that this claim is being applied to." + }, + "predicate": { + "type": "string", + "title": "Predicate", + "description": "The specific statement or assertion about the target." + }, + "mitigationStrategies": { + "type": "array", + "title": "Mitigation Strategies", + "description": "The list of `bom-ref` to the evidence provided describing the mitigation strategies. Each mitigation strategy should include an explanation of how any weaknesses in the evidence will be mitigated.", + "items": { "$ref": "#/definitions/refLinkType" } + }, + "reasoning": { + "type": "string", + "title": "Reasoning", + "description": "The written explanation of why the evidence provided substantiates the claim." + }, + "evidence": { + "type": "array", + "title": "Evidence", + "description": "The list of `bom-ref` to evidence that supports this claim.", + "items": { "$ref": "#/definitions/refLinkType" } + }, + "counterEvidence": { + "type": "array", + "title": "Counter Evidence", + "description": "The list of `bom-ref` to counterEvidence that supports this claim.", + "items": { "$ref": "#/definitions/refLinkType" } + }, + "externalReferences": { + "type": "array", + "items": {"$ref": "#/definitions/externalReference"}, + "title": "External References", + "description": "External references provide a way to document systems, sites, and information that may be relevant but are not included with the BOM. They may also establish specific relationships within or external to the BOM." + }, + "signature": { + "$ref": "#/definitions/signature", + "title": "Signature", + "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)." + } + } + } + }, + "evidence": { + "type": "array", + "title": "Evidence", + "description": "The list of evidence", + "items": { + "type": "object", + "title": "Evidence", + "additionalProperties": false, + "properties": { + "bom-ref": { + "$ref": "#/definitions/refType", + "title": "BOM Reference", + "description": "An optional identifier which can be used to reference the object elsewhere in the BOM. Every bom-ref MUST be unique within the BOM." + }, + "propertyName": { + "type": "string", + "title": "Property Name", + "description": "The reference to the property name as defined in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy/)." + }, + "description": { + "type": "string", + "title": "Description", + "description": "The written description of what this evidence is and how it was created." + }, + "data": { + "type": "array", + "title": "Data", + "description": "The output or analysis that supports claims.", + "items": { + "type": "object", + "title": "Data", + "additionalProperties": false, + "properties": { + "name": { + "title": "Data Name", + "description": "The name of the data.", + "type": "string" + }, + "contents": { + "type": "object", + "title": "Data Contents", + "description": "The contents or references to the contents of the data being described.", + "additionalProperties": false, + "properties": { + "attachment": { + "title": "Data Attachment", + "description": "An optional way to include textual or encoded data.", + "$ref": "#/definitions/attachment" + }, + "url": { + "type": "string", + "title": "Data URL", + "description": "The URL to where the data can be retrieved.", + "format": "iri-reference" + } + } + }, + "classification": { + "$ref": "#/definitions/dataClassification" + }, + "sensitiveData": { + "type": "array", + "title": "Sensitive Data", + "description": "A description of any sensitive data included.", + "items": { + "type": "string" + } + }, + "governance": { + "title": "Data Governance", + "$ref": "#/definitions/dataGovernance" + } + } + } + }, + "created": { + "type": "string", + "format": "date-time", + "title": "Created", + "description": "The date and time (timestamp) when the evidence was created." + }, + "expires": { + "type": "string", + "format": "date-time", + "title": "Expires", + "description": "The optional date and time (timestamp) when the evidence is no longer valid." + }, + "author": { + "$ref": "#/definitions/organizationalContact", + "title": "Author", + "description": "The author of the evidence." + }, + "reviewer": { + "$ref": "#/definitions/organizationalContact", + "title": "Reviewer", + "description": "The reviewer of the evidence." + }, + "signature": { + "$ref": "#/definitions/signature", + "title": "Signature", + "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)." + } + } + } + }, + "targets": { + "type": "object", + "title": "Targets", + "description": "The list of targets which claims are made against.", + "additionalProperties": false, + "properties": { + "organizations": { + "type": "array", + "title": "Organizations", + "description": "The list of organizations which claims are made against.", + "items": {"$ref": "#/definitions/organizationalEntity"} + }, + "components": { + "type": "array", + "title": "Components", + "description": "The list of components which claims are made against.", + "items": {"$ref": "#/definitions/component"} + }, + "services": { + "type": "array", + "title": "Services", + "description": "The list of services which claims are made against.", + "items": {"$ref": "#/definitions/service"} + } + } + }, + "affirmation": { + "type": "object", + "title": "Affirmation", + "additionalProperties": false, + "properties": { + "statement": { + "type": "string", + "title": "Statement", + "description": "The brief statement affirmed by an individual regarding all declarations.\n*- Notes This could be an affirmation of acceptance by a third-party auditor or receiving individual of a file.", + "examples": [ "I certify, to the best of my knowledge, that all information is correct." ] + }, + "signatories": { + "type": "array", + "title": "Signatories", + "description": "The list of signatories authorized on behalf of an organization to assert validity of this document.", + "items": { + "type": "object", + "title": "Signatory", + "additionalProperties": false, + "oneOf": [ + { + "required": ["signature"] + }, + { + "required": ["externalReference", "organization"] + } + ], + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "The signatory's name." + }, + "role": { + "type": "string", + "title": "Role", + "description": "The signatory's role within an organization." + }, + "signature": { + "$ref": "#/definitions/signature", + "title": "Signature", + "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)." + }, + "organization": { + "$ref": "#/definitions/organizationalEntity", + "title": "Organization", + "description": "The signatory's organization." + }, + "externalReference": { + "$ref": "#/definitions/externalReference", + "title": "External Reference", + "description": "External references provide a way to document systems, sites, and information that may be relevant but are not included with the BOM. They may also establish specific relationships within or external to the BOM." + } + } + } + }, + "signature": { + "$ref": "#/definitions/signature", + "title": "Signature", + "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)." + } + } + }, + "signature": { + "$ref": "#/definitions/signature", + "title": "Signature", + "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)." + } + } + }, + "definitions": { + "type": "object", + "title": "Definitions", + "description": "A collection of reusable objects that are defined and may be used elsewhere in the BOM.", + "additionalProperties": false, + "properties": { + "standards": { + "type": "array", + "title": "Standards", + "description": "The list of standards which may consist of regulations, industry or organizational-specific standards, maturity models, best practices, or any other requirements which can be evaluated against or attested to.", + "items": { + "$ref": "#/definitions/standard" + } + } + } + }, "properties": { "type": "array", "title": "Properties", @@ -121,14 +532,14 @@ }, "definitions": { "refType": { - "description": "Identifier for referable and therefore interlink-able elements.", + "description": "Identifier for referable and therefore interlinkable elements.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links.", "type": "string", "minLength": 1, - "$comment": "value SHOULD not start with the BOM-Link intro 'urn:cdx:'" + "$comment": "TODO (breaking change): add a format constraint that prevents the value from staring with 'urn:cdx:'" }, "refLinkType": { "description": "Descriptor for an element identified by the attribute 'bom-ref' in the same BOM document.\nIn contrast to `bomLinkElementType`.", - "allOf": [{"$ref": "#/definitions/refType"}] + "$ref": "#/definitions/refType" }, "bomLinkDocumentType": { "title": "BOM-Link Document", @@ -147,6 +558,7 @@ "$comment": "part of the pattern is based on `bom.serialNumber`'s pattern" }, "bomLink": { + "title": "BOM-Link", "anyOf": [ { "title": "BOM-Link Document", @@ -160,7 +572,7 @@ }, "metadata": { "type": "object", - "title": "BOM Metadata Object", + "title": "BOM Metadata", "additionalProperties": false, "properties": { "timestamp": { @@ -172,20 +584,21 @@ "lifecycles": { "type": "array", "title": "Lifecycles", - "description": "", + "description": "Lifecycles communicate the stage(s) in which data in the BOM was captured. Different types of data may be available at various phases of a lifecycle, such as the Software Development Lifecycle (SDLC), IT Asset Management (ITAM), and Software Asset Management (SAM). Thus, a BOM may include data specific to or only obtainable in a given lifecycle.", "items": { "type": "object", "title": "Lifecycle", "description": "The product lifecycle(s) that this BOM represents.", "oneOf": [ { + "title": "Pre-Defined Phase", "required": ["phase"], "additionalProperties": false, "properties": { "phase": { "type": "string", "title": "Phase", - "description": "A pre-defined phase in the product lifecycle.\n\n* __design__ = BOM produced early in the development lifecycle containing inventory of components and services that are proposed or planned to be used. The inventory may need to be procured, retrieved, or resourced prior to use.\n* __pre-build__ = BOM consisting of information obtained prior to a build process and may contain source files and development artifacts and manifests. The inventory may need to be resolved and retrieved prior to use.\n* __build__ = BOM consisting of information obtained during a build process where component inventory is available for use. The precise versions of resolved components are usually available at this time as well as the provenance of where the components were retrieved from.\n* __post-build__ = BOM consisting of information obtained after a build process has completed and the resulting components(s) are available for further analysis. Built components may exist as the result of a CI/CD process, may have been installed or deployed to a system or device, and may need to be retrieved or extracted from the system or device.\n* __operations__ = BOM produced that represents inventory that is running and operational. This may include staging or production environments and will generally encompass multiple SBOMs describing the applications and operating system, along with HBOMs describing the hardware that makes up the system. Operations Bill of Materials (OBOM) can provide full-stack inventory of runtime environments, configurations, and additional dependencies.\n* __discovery__ = BOM consisting of information observed through network discovery providing point-in-time enumeration of embedded, on-premise, and cloud-native services such as server applications, connected devices, microservices, and serverless functions.\n* __decommission__ = BOM containing inventory that will be, or has been retired from operations.", + "description": "A pre-defined phase in the product lifecycle.", "enum": [ "design", "pre-build", @@ -194,11 +607,21 @@ "operations", "discovery", "decommission" - ] + ], + "meta:enum": { + "design": "BOM produced early in the development lifecycle containing an inventory of components and services that are proposed or planned to be used. The inventory may need to be procured, retrieved, or resourced prior to use.", + "pre-build": "BOM consisting of information obtained prior to a build process and may contain source files and development artifacts and manifests. The inventory may need to be resolved and retrieved prior to use.", + "build": "BOM consisting of information obtained during a build process where component inventory is available for use. The precise versions of resolved components are usually available at this time as well as the provenance of where the components were retrieved from.", + "post-build": "BOM consisting of information obtained after a build process has completed and the resulting components(s) are available for further analysis. Built components may exist as the result of a CI/CD process, may have been installed or deployed to a system or device, and may need to be retrieved or extracted from the system or device.", + "operations": "BOM produced that represents inventory that is running and operational. This may include staging or production environments and will generally encompass multiple SBOMs describing the applications and operating system, along with HBOMs describing the hardware that makes up the system. Operations Bill of Materials (OBOM) can provide full-stack inventory of runtime environments, configurations, and additional dependencies.", + "discovery": "BOM consisting of information observed through network discovery providing point-in-time enumeration of embedded, on-premise, and cloud-native services such as server applications, connected devices, microservices, and serverless functions.", + "decommission": "BOM containing inventory that will be, or has been retired from operations." + } } } }, { + "title": "Custom Phase", "required": ["name"], "additionalProperties": false, "properties": { @@ -216,13 +639,15 @@ } ] } - }, + }, "tools": { + "title": "Tools", + "description": "The tool(s) used in the creation, enrichment, and validation of the BOM.", "oneOf": [ { "type": "object", - "title": "Creation Tools", - "description": "The tool(s) used in the creation of the BOM.", + "title": "Tools", + "description": "The tool(s) used in the creation, enrichment, and validation of the BOM.", "additionalProperties": false, "properties": { "components": { @@ -230,7 +655,7 @@ "items": {"$ref": "#/definitions/component"}, "uniqueItems": true, "title": "Components", - "description": "A list of software and hardware components used as tools" + "description": "A list of software and hardware components used as tools." }, "services": { "type": "array", @@ -243,16 +668,21 @@ }, { "type": "array", - "title": "Creation Tools (legacy)", - "description": "[Deprecated] The tool(s) used in the creation of the BOM.", + "title": "Tools (legacy)", + "description": "[Deprecated] The tool(s) used in the creation, enrichment, and validation of the BOM.", "items": {"$ref": "#/definitions/tool"} } ] }, - "authors" :{ + "manufacturer": { + "title": "BOM Manufacturer", + "description": "The organization that created the BOM.\nManufacturer is common in BOMs created through automated processes. BOMs created through manual means may have `@.authors` instead.", + "$ref": "#/definitions/organizationalEntity" + }, + "authors": { "type": "array", - "title": "Authors", - "description": "The person(s) who created the BOM. Authors are common in BOMs created through manual processes. BOMs created through automated means may not have authors.", + "title": "BOM Authors", + "description": "The person(s) who created the BOM.\nAuthors are common in BOMs created through manual processes. BOMs created through automated means may have `@.manufacturer` instead.", "items": {"$ref": "#/definitions/organizationalContact"} }, "component": { @@ -261,8 +691,9 @@ "$ref": "#/definitions/component" }, "manufacture": { - "title": "Manufacture", - "description": "The organization that manufactured the component that the BOM describes.", + "deprecated": true, + "title": "Component Manufacture (legacy)", + "description": "[Deprecated] This will be removed in a future version. Use the `@.component.manufacturer` instead.\nThe organization that manufactured the component that the BOM describes.", "$ref": "#/definitions/organizationalEntity" }, "supplier": { @@ -272,6 +703,7 @@ }, "licenses": { "title": "BOM License(s)", + "description": "The license information for the BOM document.\nThis may be different from the license(s) of the component(s) that the BOM describes.", "$ref": "#/definitions/licenseChoice" }, "properties": { @@ -285,7 +717,7 @@ "tool": { "type": "object", "title": "Tool", - "description": "[Deprecated] - DO NOT USE. This will be removed in a future version. This will be removed in a future version. Use component or service instead. Information about the automated or manual tool used", + "description": "[Deprecated] This will be removed in a future version. Use component or service instead. Information about the automated or manual tool used", "additionalProperties": false, "properties": { "vendor": { @@ -299,7 +731,7 @@ "description": "The name of the tool" }, "version": { - "type": "string", + "$ref": "#/definitions/version", "title": "Tool Version", "description": "The version of the tool" }, @@ -319,36 +751,41 @@ }, "organizationalEntity": { "type": "object", - "title": "Organizational Entity Object", + "title": "Organizational Entity", "description": "", "additionalProperties": false, "properties": { "bom-ref": { "$ref": "#/definitions/refType", "title": "BOM Reference", - "description": "An optional identifier which can be used to reference the object elsewhere in the BOM. Every bom-ref MUST be unique within the BOM." + "description": "An optional identifier which can be used to reference the object elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links." }, "name": { "type": "string", - "title": "Name", + "title": "Organization Name", "description": "The name of the organization", "examples": [ "Example Inc." ] }, + "address": { + "$ref": "#/definitions/postalAddress", + "title": "Organization Address", + "description": "The physical address (location) of the organization" + }, "url": { "type": "array", "items": { "type": "string", "format": "iri-reference" }, - "title": "URL", + "title": "Organization URL(s)", "description": "The URL of the organization. Multiple URLs are allowed.", "examples": ["https://example.com"] }, "contact": { "type": "array", - "title": "Contact", + "title": "Organizational Contact", "description": "A contact at the organization. Multiple contacts are allowed.", "items": {"$ref": "#/definitions/organizationalContact"} } @@ -356,14 +793,14 @@ }, "organizationalContact": { "type": "object", - "title": "Organizational Contact Object", + "title": "Organizational Contact", "description": "", "additionalProperties": false, "properties": { "bom-ref": { "$ref": "#/definitions/refType", "title": "BOM Reference", - "description": "An optional identifier which can be used to reference the object elsewhere in the BOM. Every bom-ref MUST be unique within the BOM." + "description": "An optional identifier which can be used to reference the object elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links." }, "name": { "type": "string", @@ -388,7 +825,7 @@ }, "component": { "type": "object", - "title": "Component Object", + "title": "Component", "required": [ "type", "name" @@ -409,33 +846,61 @@ "firmware", "file", "machine-learning-model", - "data" + "data", + "cryptographic-asset" ], + "meta:enum": { + "application": "A software application. Refer to [https://en.wikipedia.org/wiki/Application_software](https://en.wikipedia.org/wiki/Application_software) for information about applications.", + "framework": "A software framework. Refer to [https://en.wikipedia.org/wiki/Software_framework](https://en.wikipedia.org/wiki/Software_framework) for information on how frameworks vary slightly from libraries.", + "library": "A software library. Refer to [https://en.wikipedia.org/wiki/Library_(computing)](https://en.wikipedia.org/wiki/Library_(computing)) for information about libraries. All third-party and open source reusable components will likely be a library. If the library also has key features of a framework, then it should be classified as a framework. If not, or is unknown, then specifying library is RECOMMENDED.", + "container": "A packaging and/or runtime format, not specific to any particular technology, which isolates software inside the container from software outside of a container through virtualization technology. Refer to [https://en.wikipedia.org/wiki/OS-level_virtualization](https://en.wikipedia.org/wiki/OS-level_virtualization).", + "platform": "A runtime environment which interprets or executes software. This may include runtimes such as those that execute bytecode or low-code/no-code application platforms.", + "operating-system": "A software operating system without regard to deployment model (i.e. installed on physical hardware, virtual machine, image, etc) Refer to [https://en.wikipedia.org/wiki/Operating_system](https://en.wikipedia.org/wiki/Operating_system).", + "device": "A hardware device such as a processor or chip-set. A hardware device containing firmware SHOULD include a component for the physical hardware itself and another component of type 'firmware' or 'operating-system' (whichever is relevant), describing information about the software running on the device. See also the list of [known device properties](https://github.com/CycloneDX/cyclonedx-property-taxonomy/blob/main/cdx/device.md).", + "device-driver": "A special type of software that operates or controls a particular type of device. Refer to [https://en.wikipedia.org/wiki/Device_driver](https://en.wikipedia.org/wiki/Device_driver).", + "firmware": "A special type of software that provides low-level control over a device's hardware. Refer to [https://en.wikipedia.org/wiki/Firmware](https://en.wikipedia.org/wiki/Firmware).", + "file": "A computer file. Refer to [https://en.wikipedia.org/wiki/Computer_file](https://en.wikipedia.org/wiki/Computer_file) for information about files.", + "machine-learning-model": "A model based on training data that can make predictions or decisions without being explicitly programmed to do so.", + "data": "A collection of discrete values that convey information.", + "cryptographic-asset": "A cryptographic asset including algorithms, protocols, certificates, keys, tokens, and secrets." + }, "title": "Component Type", - "description": "Specifies the type of component. For software components, classify as application if no more specific appropriate classification is available or cannot be determined for the component. Types include:\n\n* __application__ = A software application. Refer to [https://en.wikipedia.org/wiki/Application_software](https://en.wikipedia.org/wiki/Application_software) for information about applications.\n* __framework__ = A software framework. Refer to [https://en.wikipedia.org/wiki/Software_framework](https://en.wikipedia.org/wiki/Software_framework) for information on how frameworks vary slightly from libraries.\n* __library__ = A software library. Refer to [https://en.wikipedia.org/wiki/Library_(computing)](https://en.wikipedia.org/wiki/Library_(computing))\n for information about libraries. All third-party and open source reusable components will likely be a library. If the library also has key features of a framework, then it should be classified as a framework. If not, or is unknown, then specifying library is RECOMMENDED.\n* __container__ = A packaging and/or runtime format, not specific to any particular technology, which isolates software inside the container from software outside of a container through virtualization technology. Refer to [https://en.wikipedia.org/wiki/OS-level_virtualization](https://en.wikipedia.org/wiki/OS-level_virtualization)\n* __platform__ = A runtime environment which interprets or executes software. This may include runtimes such as those that execute bytecode or low-code/no-code application platforms.\n* __operating-system__ = A software operating system without regard to deployment model (i.e. installed on physical hardware, virtual machine, image, etc) Refer to [https://en.wikipedia.org/wiki/Operating_system](https://en.wikipedia.org/wiki/Operating_system)\n* __device__ = A hardware device such as a processor, or chip-set. A hardware device containing firmware SHOULD include a component for the physical hardware itself, and another component of type 'firmware' or 'operating-system' (whichever is relevant), describing information about the software running on the device.\n See also the list of [known device properties](https://github.com/CycloneDX/cyclonedx-property-taxonomy/blob/main/cdx/device.md).\n* __device-driver__ = A special type of software that operates or controls a particular type of device. Refer to [https://en.wikipedia.org/wiki/Device_driver](https://en.wikipedia.org/wiki/Device_driver)\n* __firmware__ = A special type of software that provides low-level control over a devices hardware. Refer to [https://en.wikipedia.org/wiki/Firmware](https://en.wikipedia.org/wiki/Firmware)\n* __file__ = A computer file. Refer to [https://en.wikipedia.org/wiki/Computer_file](https://en.wikipedia.org/wiki/Computer_file) for information about files.\n* __machine-learning-model__ = A model based on training data that can make predictions or decisions without being explicitly programmed to do so.\n* __data__ = A collection of discrete values that convey information.", + "description": "Specifies the type of component. For software components, classify as application if no more specific appropriate classification is available or cannot be determined for the component.", "examples": ["library"] }, "mime-type": { "type": "string", "title": "Mime-Type", - "description": "The optional mime-type of the component. When used on file components, the mime-type can provide additional context about the kind of file being represented such as an image, font, or executable. Some library or framework components may also have an associated mime-type.", + "description": "The optional mime-type of the component. When used on file components, the mime-type can provide additional context about the kind of file being represented, such as an image, font, or executable. Some library or framework components may also have an associated mime-type.", "examples": ["image/jpeg"], "pattern": "^[-+a-z0-9.]+/[-+a-z0-9.]+$" }, "bom-ref": { "$ref": "#/definitions/refType", "title": "BOM Reference", - "description": "An optional identifier which can be used to reference the component elsewhere in the BOM. Every bom-ref MUST be unique within the BOM." + "description": "An optional identifier which can be used to reference the component elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links." }, "supplier": { "title": "Component Supplier", "description": " The organization that supplied the component. The supplier may often be the manufacturer, but may also be a distributor or repackager.", "$ref": "#/definitions/organizationalEntity" }, + "manufacturer": { + "title": "Component Manufacturer", + "description": "The organization that created the component.\nManufacturer is common in components created through automated processes. Components created through manual means may have `@.authors` instead.", + "$ref": "#/definitions/organizationalEntity" + }, + "authors" :{ + "type": "array", + "title": "Component Authors", + "description": "The person(s) who created the component.\nAuthors are common in components created through manual processes. Components created through automated means may have `@.manufacturer` instead.", + "items": {"$ref": "#/definitions/organizationalContact"} + }, "author": { + "deprecated": true, "type": "string", - "title": "Component Author", - "description": "The person(s) or organization(s) that authored the component", + "title": "Component Author (legacy)", + "description": "[Deprecated] This will be removed in a future version. Use `@.authors` or `@.manufacturer` instead.\nThe person(s) or organization(s) that authored the component", "examples": ["Acme Inc"] }, "publisher": { @@ -457,10 +922,9 @@ "examples": ["tomcat-catalina"] }, "version": { - "type": "string", + "$ref": "#/definitions/version", "title": "Component Version", - "description": "The component version. The version should ideally comply with semantic versioning but is not enforced.", - "examples": ["9.0.14"] + "description": "The component version. The version should ideally comply with semantic versioning but is not enforced." }, "description": { "type": "string", @@ -474,6 +938,11 @@ "optional", "excluded" ], + "meta:enum": { + "required": "The component is required for runtime", + "optional": "The component is optional at runtime. Optional components are components that are not capable of being called due to them not being installed or otherwise accessible by any means. Components that are installed but due to configuration or other restrictions are prohibited from being called must be scoped as 'required'.", + "excluded": "Components that are excluded provide the ability to document component usage for test and other non-runtime purposes. Excluded components are not reachable within a call graph at runtime." + }, "title": "Component Scope", "description": "Specifies the scope of the component. If scope is not specified, 'required' scope SHOULD be assumed by the consumer of the BOM.", "default": "required" @@ -481,6 +950,7 @@ "hashes": { "type": "array", "title": "Component Hashes", + "description": "The hashes of the component.", "items": {"$ref": "#/definitions/hash"} }, "licenses": { @@ -495,25 +965,42 @@ }, "cpe": { "type": "string", - "title": "Component Common Platform Enumeration (CPE)", - "description": "Specifies a well-formed CPE name that conforms to the CPE 2.2 or 2.3 specification. See [https://nvd.nist.gov/products/cpe](https://nvd.nist.gov/products/cpe)", + "title": "Common Platform Enumeration (CPE)", + "description": "Asserts the identity of the component using CPE. The CPE must conform to the CPE 2.2 or 2.3 specification. See [https://nvd.nist.gov/products/cpe](https://nvd.nist.gov/products/cpe). Refer to `@.evidence.identity` to optionally provide evidence that substantiates the assertion of the component's identity.", "examples": ["cpe:2.3:a:acme:component_framework:-:*:*:*:*:*:*:*"] }, "purl": { "type": "string", - "title": "Component Package URL (purl)", - "description": "Specifies the package-url (purl). The purl, if specified, MUST be valid and conform to the specification defined at: [https://github.com/package-url/purl-spec](https://github.com/package-url/purl-spec)", + "title": "Package URL (purl)", + "description": "Asserts the identity of the component using package-url (purl). The purl, if specified, MUST be valid and conform to the specification defined at: [https://github.com/package-url/purl-spec](https://github.com/package-url/purl-spec). Refer to `@.evidence.identity` to optionally provide evidence that substantiates the assertion of the component's identity.", "examples": ["pkg:maven/com.acme/tomcat-catalina@9.0.14?packaging=jar"] }, + "omniborId": { + "type": "array", + "title": "OmniBOR Artifact Identifier (gitoid)", + "description": "Asserts the identity of the component using the OmniBOR Artifact ID. The OmniBOR, if specified, MUST be valid and conform to the specification defined at: [https://www.iana.org/assignments/uri-schemes/prov/gitoid](https://www.iana.org/assignments/uri-schemes/prov/gitoid). Refer to `@.evidence.identity` to optionally provide evidence that substantiates the assertion of the component's identity.", + "items": { "type": "string" }, + "examples": [ + "gitoid:blob:sha1:a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", + "gitoid:blob:sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08" + ] + }, + "swhid": { + "type": "array", + "title": "SoftWare Heritage Identifier", + "description": "Asserts the identity of the component using the Software Heritage persistent identifier (SWHID). The SWHID, if specified, MUST be valid and conform to the specification defined at: [https://docs.softwareheritage.org/devel/swh-model/persistent-identifiers.html](https://docs.softwareheritage.org/devel/swh-model/persistent-identifiers.html). Refer to `@.evidence.identity` to optionally provide evidence that substantiates the assertion of the component's identity.", + "items": { "type": "string" }, + "examples": ["swh:1:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2"] + }, "swid": { "$ref": "#/definitions/swid", "title": "SWID Tag", - "description": "Specifies metadata and content for [ISO-IEC 19770-2 Software Identification (SWID) Tags](https://www.iso.org/standard/65666.html)." + "description": "Asserts the identity of the component using [ISO-IEC 19770-2 Software Identification (SWID) Tags](https://www.iso.org/standard/65666.html). Refer to `@.evidence.identity` to optionally provide evidence that substantiates the assertion of the component's identity." }, "modified": { "type": "boolean", "title": "Component Modified From Original", - "description": "[Deprecated] - DO NOT USE. This will be removed in a future version. Use the pedigree element instead to supply information on exactly how the component was modified. A boolean value indicating if the component has been modified from the original. A value of true indicates the component is a derivative of the original. A value of false indicates the component has not been modified from the original." + "description": "[Deprecated] This will be removed in a future version. Use the pedigree element instead to supply information on exactly how the component was modified. A boolean value indicating if the component has been modified from the original. A value of true indicates the component is a derivative of the original. A value of false indicates the component has not been modified from the original." }, "pedigree": { "type": "object", @@ -536,7 +1023,7 @@ "variants": { "type": "array", "title": "Variants", - "description": "Variants describe relations where the relationship between the components are not known. For example, if Component A contains nearly identical code to Component B. They are both related, but it is unclear if one is derived from the other, or if they share a common ancestor.", + "description": "Variants describe relations where the relationship between the components is not known. For example, if Component A contains nearly identical code to Component B. They are both related, but it is unclear if one is derived from the other, or if they share a common ancestor.", "items": {"$ref": "#/definitions/component"} }, "commits": { @@ -548,7 +1035,7 @@ "patches": { "type": "array", "title": "Patches", - "description": ">A list of zero or more patches describing how the component deviates from an ancestor, descendant, or variant. Patches may be complimentary to commits or may be used in place of commits.", + "description": ">A list of zero or more patches describing how the component deviates from an ancestor, descendant, or variant. Patches may be complementary to commits or may be used in place of commits.", "items": {"$ref": "#/definitions/patch"} }, "notes": { @@ -562,7 +1049,7 @@ "type": "array", "items": {"$ref": "#/definitions/externalReference"}, "title": "External References", - "description": "External references provide a way to document systems, sites, and information that may be relevant, but are not included with the BOM. They may also establish specific relationships within or external to the BOM." + "description": "External references provide a way to document systems, sites, and information that may be relevant but are not included with the BOM. They may also establish specific relationships within or external to the BOM." }, "components": { "type": "array", @@ -581,9 +1068,9 @@ "title": "Release notes", "description": "Specifies optional release notes." }, - "modelCard": { + "modelCard": { "$ref": "#/definitions/modelCard", - "title": "Machine Learning Model Card" + "title": "AI/ML Model Card" }, "data": { "type": "array", @@ -591,12 +1078,20 @@ "title": "Data", "description": "This object SHOULD be specified for any component of type `data` and MUST NOT be specified for other component types." }, + "cryptoProperties": { + "$ref": "#/definitions/cryptoProperties", + "title": "Cryptographic Properties" + }, "properties": { "type": "array", "title": "Properties", "description": "Provides the ability to document properties in a name-value store. This provides flexibility to include data not officially supported in the standard without having to use additional namespaces or create extensions. Unlike key-value stores, properties support duplicate names, each potentially having different values. Property names of interest to the general public are encouraged to be registered in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy). Formal registration is OPTIONAL.", "items": {"$ref": "#/definitions/property"} }, + "tags": { + "$ref": "#/definitions/tags", + "title": "Tags" + }, "signature": { "$ref": "#/definitions/signature", "title": "Signature", @@ -676,7 +1171,10 @@ "description": "Specifies the optional encoding the text is represented in.", "enum": [ "base64" - ] + ], + "meta:enum": { + "base64": "Base64 is a binary-to-text encoding scheme that represents binary data in an ASCII string." + } }, "content": { "type": "string", @@ -687,7 +1185,7 @@ }, "hash": { "type": "object", - "title": "Hash Objects", + "title": "Hash", "required": [ "alg", "content" @@ -704,6 +1202,8 @@ }, "hash-alg": { "type": "string", + "title": "Hash Algorithm", + "description": "The algorithm that generated the hash value.", "enum": [ "MD5", "SHA-1", @@ -717,18 +1217,18 @@ "BLAKE2b-384", "BLAKE2b-512", "BLAKE3" - ], - "title": "Hash Algorithm" + ] }, "hash-content": { "type": "string", - "title": "Hash Content (value)", + "title": "Hash Value", + "description": "The value of the hash.", "examples": ["3942447fac867ae5cdb3229b658f4d48"], "pattern": "^([a-fA-F0-9]{32}|[a-fA-F0-9]{40}|[a-fA-F0-9]{64}|[a-fA-F0-9]{96}|[a-fA-F0-9]{128})$" }, "license": { "type": "object", - "title": "License Object", + "title": "License", "oneOf": [ { "required": ["id"] @@ -742,7 +1242,7 @@ "bom-ref": { "$ref": "#/definitions/refType", "title": "BOM Reference", - "description": "An optional identifier which can be used to reference the license elsewhere in the BOM. Every bom-ref MUST be unique within the BOM." + "description": "An optional identifier which can be used to reference the license elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links." }, "id": { "$ref": "spdx.schema.json", @@ -756,6 +1256,9 @@ "description": "If SPDX does not define the license used, this field may be used to provide the license name", "examples": ["Acme Software License"] }, + "acknowledgement": { + "$ref": "#/definitions/licenseAcknowledgementEnumeration" + }, "text": { "title": "License text", "description": "An optional way to include the textual content of a license.", @@ -868,7 +1371,7 @@ "licenseTypes": { "type": "array", "title": "License Type", - "description": "The type of license(s) that was granted to the licensee\n\n* __academic__ = A license that grants use of software solely for the purpose of education or research.\n* __appliance__ = A license covering use of software embedded in a specific piece of hardware.\n* __client-access__ = A Client Access License (CAL) allows client computers to access services provided by server software.\n* __concurrent-user__ = A Concurrent User license (aka floating license) limits the number of licenses for a software application and licenses are shared among a larger number of users.\n* __core-points__ = A license where the core of a computer's processor is assigned a specific number of points.\n* __custom-metric__ = A license for which consumption is measured by non-standard metrics.\n* __device__ = A license that covers a defined number of installations on computers and other types of devices.\n* __evaluation__ = A license that grants permission to install and use software for trial purposes.\n* __named-user__ = A license that grants access to the software to one or more pre-defined users.\n* __node-locked__ = A license that grants access to the software on one or more pre-defined computers or devices.\n* __oem__ = An Original Equipment Manufacturer license that is delivered with hardware, cannot be transferred to other hardware, and is valid for the life of the hardware.\n* __perpetual__ = A license where the software is sold on a one-time basis and the licensee can use a copy of the software indefinitely.\n* __processor-points__ = A license where each installation consumes points per processor.\n* __subscription__ = A license where the licensee pays a fee to use the software or service.\n* __user__ = A license that grants access to the software or service by a specified number of users.\n* __other__ = Another license type.\n", + "description": "The type of license(s) that was granted to the licensee.", "items": { "type": "string", "enum": [ @@ -888,7 +1391,25 @@ "subscription", "user", "other" - ] + ], + "meta:enum": { + "academic": "A license that grants use of software solely for the purpose of education or research.", + "appliance": "A license covering use of software embedded in a specific piece of hardware.", + "client-access": "A Client Access License (CAL) allows client computers to access services provided by server software.", + "concurrent-user": "A Concurrent User license (aka floating license) limits the number of licenses for a software application and licenses are shared among a larger number of users.", + "core-points": "A license where the core of a computer's processor is assigned a specific number of points.", + "custom-metric": "A license for which consumption is measured by non-standard metrics.", + "device": "A license that covers a defined number of installations on computers and other types of devices.", + "evaluation": "A license that grants permission to install and use software for trial purposes.", + "named-user": "A license that grants access to the software to one or more pre-defined users.", + "node-locked": "A license that grants access to the software on one or more pre-defined computers or devices.", + "oem": "An Original Equipment Manufacturer license that is delivered with hardware, cannot be transferred to other hardware, and is valid for the life of the hardware.", + "perpetual": "A license where the software is sold on a one-time basis and the licensee can use a copy of the software indefinitely.", + "processor-points": "A license where each installation consumes points per processor.", + "subscription": "A license where the licensee pays a fee to use the software or service.", + "user": "A license that grants access to the software or service by a specified number of users.", + "other": "Another license type." + } } }, "lastRenewal": { @@ -913,6 +1434,19 @@ } } }, + "licenseAcknowledgementEnumeration": { + "title": "License Acknowledgement", + "description": "Declared licenses and concluded licenses represent two different stages in the licensing process within software development. Declared licenses refer to the initial intention of the software authors regarding the licensing terms under which their code is released. On the other hand, concluded licenses are the result of a comprehensive analysis of the project's codebase to identify and confirm the actual licenses of the components used, which may differ from the initially declared licenses. While declared licenses provide an upfront indication of the licensing intentions, concluded licenses offer a more thorough understanding of the actual licensing within a project, facilitating proper compliance and risk management. Observed licenses are defined in `@.evidence.licenses`. Observed licenses form the evidence necessary to substantiate a concluded license.", + "type": "string", + "enum": [ + "declared", + "concluded" + ], + "meta:enum": { + "declared": "Declared licenses represent the initial intentions of authors regarding the licensing terms of their code.", + "concluded": "Concluded licenses are verified and confirmed." + } + }, "licenseChoice": { "title": "License Choice", "description": "EITHER (list of SPDX licenses and/or named licenses) OR (tuple of one SPDX License Expression)", @@ -924,6 +1458,7 @@ "type": "array", "items": { "type": "object", + "title": "License", "required": ["license"], "additionalProperties": false, "properties": { @@ -946,15 +1481,19 @@ "expression": { "type": "string", "title": "SPDX License Expression", + "description": "A valid SPDX license expression.\nRefer to https://spdx.org/specifications for syntax requirements", "examples": [ "Apache-2.0 AND (MIT OR GPL-2.0-only)", "GPL-3.0-only WITH Classpath-exception-2.0" ] }, + "acknowledgement": { + "$ref": "#/definitions/licenseAcknowledgementEnumeration" + }, "bom-ref": { "$ref": "#/definitions/refType", "title": "BOM Reference", - "description": "An optional identifier which can be used to reference the license elsewhere in the BOM. Every bom-ref MUST be unique within the BOM." + "description": "An optional identifier which can be used to reference the license elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links." } } }] @@ -1012,12 +1551,18 @@ "backport", "cherry-pick" ], - "title": "Type", - "description": "Specifies the purpose for the patch including the resolution of defects, security issues, or new behavior or functionality.\n\n* __unofficial__ = A patch which is not developed by the creators or maintainers of the software being patched. Refer to [https://en.wikipedia.org/wiki/Unofficial_patch](https://en.wikipedia.org/wiki/Unofficial_patch)\n* __monkey__ = A patch which dynamically modifies runtime behavior. Refer to [https://en.wikipedia.org/wiki/Monkey_patch](https://en.wikipedia.org/wiki/Monkey_patch)\n* __backport__ = A patch which takes code from a newer version of software and applies it to older versions of the same software. Refer to [https://en.wikipedia.org/wiki/Backporting](https://en.wikipedia.org/wiki/Backporting)\n* __cherry-pick__ = A patch created by selectively applying commits from other versions or branches of the same software." + "meta:enum": { + "unofficial": "A patch which is not developed by the creators or maintainers of the software being patched. Refer to [https://en.wikipedia.org/wiki/Unofficial_patch](https://en.wikipedia.org/wiki/Unofficial_patch).", + "monkey": "A patch which dynamically modifies runtime behavior. Refer to [https://en.wikipedia.org/wiki/Monkey_patch](https://en.wikipedia.org/wiki/Monkey_patch).", + "backport": "A patch which takes code from a newer version of the software and applies it to older versions of the same software. Refer to [https://en.wikipedia.org/wiki/Backporting](https://en.wikipedia.org/wiki/Backporting).", + "cherry-pick": "A patch created by selectively applying commits from other versions or branches of the same software." + }, + "title": "Patch Type", + "description": "Specifies the purpose for the patch including the resolution of defects, security issues, or new behavior or functionality." }, "diff": { "title": "Diff", - "description": "The patch file (or diff) that show changes. Refer to [https://en.wikipedia.org/wiki/Diff](https://en.wikipedia.org/wiki/Diff)", + "description": "The patch file (or diff) that shows changes. Refer to [https://en.wikipedia.org/wiki/Diff](https://en.wikipedia.org/wiki/Diff)", "$ref": "#/definitions/diff" }, "resolves": { @@ -1031,7 +1576,7 @@ "diff": { "type": "object", "title": "Diff", - "description": "The patch file (or diff) that show changes. Refer to https://en.wikipedia.org/wiki/Diff", + "description": "The patch file (or diff) that shows changes. Refer to https://en.wikipedia.org/wiki/Diff", "additionalProperties": false, "properties": { "text": { @@ -1049,7 +1594,7 @@ }, "issue": { "type": "object", - "title": "Diff", + "title": "Issue", "description": "An individual issue that has been resolved.", "required": [ "type" @@ -1063,22 +1608,27 @@ "enhancement", "security" ], - "title": "Type", + "meta:enum": { + "defect": "A fault, flaw, or bug in software.", + "enhancement": "A new feature or behavior in software.", + "security": "A special type of defect which impacts security." + }, + "title": "Issue Type", "description": "Specifies the type of issue" }, "id": { "type": "string", - "title": "ID", + "title": "Issue ID", "description": "The identifier of the issue assigned by the source of the issue" }, "name": { "type": "string", - "title": "Name", + "title": "Issue Name", "description": "The name of the issue" }, "description": { "type": "string", - "title": "Description", + "title": "Issue Description", "description": "A description of the issue" }, "source": { @@ -1090,7 +1640,12 @@ "name": { "type": "string", "title": "Name", - "description": "The name of the source. For example 'National Vulnerability Database', 'NVD', and 'Apache'" + "description": "The name of the source.", + "examples": [ + "National Vulnerability Database", + "NVD", + "Apache" + ] }, "url": { "type": "string", @@ -1140,7 +1695,7 @@ "externalReference": { "type": "object", "title": "External Reference", - "description": "External references provide a way to document systems, sites, and information that may be relevant, but are not included with the BOM. They may also establish specific relationships within or external to the BOM.", + "description": "External references provide a way to document systems, sites, and information that may be relevant but are not included with the BOM. They may also establish specific relationships within or external to the BOM.", "required": [ "url", "type" @@ -1170,7 +1725,7 @@ "type": { "type": "string", "title": "Type", - "description": "Specifies the type of external reference.\n\n* __vcs__ = Version Control System\n* __issue-tracker__ = Issue or defect tracking system, or an Application Lifecycle Management (ALM) system\n* __website__ = Website\n* __advisories__ = Security advisories\n* __bom__ = Bill of Materials (SBOM, OBOM, HBOM, SaaSBOM, etc)\n* __mailing-list__ = Mailing list or discussion group\n* __social__ = Social media account\n* __chat__ = Real-time chat platform\n* __documentation__ = Documentation, guides, or how-to instructions\n* __support__ = Community or commercial support\n* __distribution__ = Direct or repository download location\n* __distribution-intake__ = The location where a component was published to. This is often the same as \"distribution\" but may also include specialized publishing processes that act as an intermediary\n* __license__ = The URL to the license file. If a license URL has been defined in the license node, it should also be defined as an external reference for completeness\n* __build-meta__ = Build-system specific meta file (i.e. pom.xml, package.json, .nuspec, etc)\n* __build-system__ = URL to an automated build system\n* __release-notes__ = URL to release notes\n* __security-contact__ = Specifies a way to contact the maintainer, supplier, or provider in the event of a security incident. Common URIs include links to a disclosure procedure, a mailto (RFC-2368) that specifies an email address, a tel (RFC-3966) that specifies a phone number, or dns (RFC-4501) that specifies the records containing DNS Security TXT\n* __model-card__ = A model card describes the intended uses of a machine learning model, potential limitations, biases, ethical considerations, training parameters, datasets used to train the model, performance metrics, and other relevant data useful for ML transparency\n* __log__ = A record of events that occurred in a computer system or application, such as problems, errors, or information on current operations\n* __configuration__ = Parameters or settings that may be used by other components or services\n* __evidence__ = Information used to substantiate a claim\n* __formulation__ = Describes how a component or service was manufactured or deployed\n* __attestation__ = Human or machine-readable statements containing facts, evidence, or testimony\n* __threat-model__ = An enumeration of identified weaknesses, threats, and countermeasures, dataflow diagram (DFD), attack tree, and other supporting documentation in human-readable or machine-readable format\n* __adversary-model__ = The defined assumptions, goals, and capabilities of an adversary.\n* __risk-assessment__ = Identifies and analyzes the potential of future events that may negatively impact individuals, assets, and/or the environment. Risk assessments may also include judgments on the tolerability of each risk.\n* __vulnerability-assertion__ = A Vulnerability Disclosure Report (VDR) which asserts the known and previously unknown vulnerabilities that affect a component, service, or product including the analysis and findings describing the impact (or lack of impact) that the reported vulnerability has on a component, service, or product.\n* __exploitability-statement__ = A Vulnerability Exploitability eXchange (VEX) which asserts the known vulnerabilities that do not affect a product, product family, or organization, and optionally the ones that do. The VEX should include the analysis and findings describing the impact (or lack of impact) that the reported vulnerability has on the product, product family, or organization.\n* __pentest-report__ = Results from an authorized simulated cyberattack on a component or service, otherwise known as a penetration test\n* __static-analysis-report__ = SARIF or proprietary machine or human-readable report for which static analysis has identified code quality, security, and other potential issues with the source code\n* __dynamic-analysis-report__ = Dynamic analysis report that has identified issues such as vulnerabilities and misconfigurations\n* __runtime-analysis-report__ = Report generated by analyzing the call stack of a running application\n* __component-analysis-report__ = Report generated by Software Composition Analysis (SCA), container analysis, or other forms of component analysis\n* __maturity-report__ = Report containing a formal assessment of an organization, business unit, or team against a maturity model\n* __certification-report__ = Industry, regulatory, or other certification from an accredited (if applicable) certification body\n* __quality-metrics__ = Report or system in which quality metrics can be obtained\n* __codified-infrastructure__ = Code or configuration that defines and provisions virtualized infrastructure, commonly referred to as Infrastructure as Code (IaC)\n* __poam__ = Plans of Action and Milestones (POAM) compliment an \"attestation\" external reference. POAM is defined by NIST as a \"document that identifies tasks needing to be accomplished. It details resources required to accomplish the elements of the plan, any milestones in meeting the tasks and scheduled completion dates for the milestones\".\n* __other__ = Use this if no other types accurately describe the purpose of the external reference", + "description": "Specifies the type of external reference.", "enum": [ "vcs", "issue-tracker", @@ -1182,6 +1737,7 @@ "chat", "documentation", "support", + "source-distribution", "distribution", "distribution-intake", "license", @@ -1210,8 +1766,56 @@ "codified-infrastructure", "quality-metrics", "poam", + "electronic-signature", + "digital-signature", + "rfc-9116", "other" - ] + ], + "meta:enum": { + "vcs": "Version Control System", + "issue-tracker": "Issue or defect tracking system, or an Application Lifecycle Management (ALM) system", + "website": "Website", + "advisories": "Security advisories", + "bom": "Bill of Materials (SBOM, OBOM, HBOM, SaaSBOM, etc)", + "mailing-list": "Mailing list or discussion group", + "social": "Social media account", + "chat": "Real-time chat platform", + "documentation": "Documentation, guides, or how-to instructions", + "support": "Community or commercial support", + "source-distribution": "The location where the source code distributable can be obtained. This is often an archive format such as zip or tgz. The source-distribution type complements use of the version control (vcs) type.", + "distribution": "Direct or repository download location", + "distribution-intake": "The location where a component was published to. This is often the same as \"distribution\" but may also include specialized publishing processes that act as an intermediary.", + "license": "The reference to the license file. If a license URL has been defined in the license node, it should also be defined as an external reference for completeness.", + "build-meta": "Build-system specific meta file (i.e. pom.xml, package.json, .nuspec, etc)", + "build-system": "Reference to an automated build system", + "release-notes": "Reference to release notes", + "security-contact": "Specifies a way to contact the maintainer, supplier, or provider in the event of a security incident. Common URIs include links to a disclosure procedure, a mailto (RFC-2368) that specifies an email address, a tel (RFC-3966) that specifies a phone number, or dns (RFC-4501) that specifies the records containing DNS Security TXT.", + "model-card": "A model card describes the intended uses of a machine learning model, potential limitations, biases, ethical considerations, training parameters, datasets used to train the model, performance metrics, and other relevant data useful for ML transparency.", + "log": "A record of events that occurred in a computer system or application, such as problems, errors, or information on current operations.", + "configuration": "Parameters or settings that may be used by other components or services.", + "evidence": "Information used to substantiate a claim.", + "formulation": "Describes how a component or service was manufactured or deployed.", + "attestation": "Human or machine-readable statements containing facts, evidence, or testimony.", + "threat-model": "An enumeration of identified weaknesses, threats, and countermeasures, dataflow diagram (DFD), attack tree, and other supporting documentation in human-readable or machine-readable format.", + "adversary-model": "The defined assumptions, goals, and capabilities of an adversary.", + "risk-assessment": "Identifies and analyzes the potential of future events that may negatively impact individuals, assets, and/or the environment. Risk assessments may also include judgments on the tolerability of each risk.", + "vulnerability-assertion": "A Vulnerability Disclosure Report (VDR) which asserts the known and previously unknown vulnerabilities that affect a component, service, or product including the analysis and findings describing the impact (or lack of impact) that the reported vulnerability has on a component, service, or product.", + "exploitability-statement": "A Vulnerability Exploitability eXchange (VEX) which asserts the known vulnerabilities that do not affect a product, product family, or organization, and optionally the ones that do. The VEX should include the analysis and findings describing the impact (or lack of impact) that the reported vulnerability has on the product, product family, or organization.", + "pentest-report": "Results from an authorized simulated cyberattack on a component or service, otherwise known as a penetration test.", + "static-analysis-report": "SARIF or proprietary machine or human-readable report for which static analysis has identified code quality, security, and other potential issues with the source code.", + "dynamic-analysis-report": "Dynamic analysis report that has identified issues such as vulnerabilities and misconfigurations.", + "runtime-analysis-report": "Report generated by analyzing the call stack of a running application.", + "component-analysis-report": "Report generated by Software Composition Analysis (SCA), container analysis, or other forms of component analysis.", + "maturity-report": "Report containing a formal assessment of an organization, business unit, or team against a maturity model.", + "certification-report": "Industry, regulatory, or other certification from an accredited (if applicable) certification body.", + "codified-infrastructure": "Code or configuration that defines and provisions virtualized infrastructure, commonly referred to as Infrastructure as Code (IaC).", + "quality-metrics": "Report or system in which quality metrics can be obtained.", + "poam": "Plans of Action and Milestones (POAM) complement an \"attestation\" external reference. POAM is defined by NIST as a \"document that identifies tasks needing to be accomplished. It details resources required to accomplish the elements of the plan, any milestones in meeting the tasks and scheduled completion dates for the milestones\".", + "electronic-signature": "An e-signature is commonly a scanned representation of a written signature or a stylized script of the person's name.", + "digital-signature": "A signature that leverages cryptography, typically public/private key pairs, which provides strong authenticity verification.", + "rfc-9116": "Document that complies with RFC-9116 (A File Format to Aid in Security Vulnerability Disclosure)", + "other": "Use this if no other types accurately describe the purpose of the external reference." + } }, "hashes": { "type": "array", @@ -1224,7 +1828,7 @@ "dependency": { "type": "object", "title": "Dependency", - "description": "Defines the direct dependencies of a component or service. Components or services that do not have their own dependencies MUST be declared as empty elements within the graph. Components or services that are not represented in the dependency graph MAY have unknown dependencies. It is RECOMMENDED that implementations assume this to be opaque and not an indicator of a object being dependency-free. It is RECOMMENDED to leverage compositions to indicate unknown dependency graphs.", + "description": "Defines the direct dependencies of a component, service, or the components provided/implemented by a given component. Components or services that do not have their own dependencies MUST be declared as empty elements within the graph. Components or services that are not represented in the dependency graph MAY have unknown dependencies. It is RECOMMENDED that implementations assume this to be opaque and not an indicator of an object being dependency-free. It is RECOMMENDED to leverage compositions to indicate unknown dependency graphs.", "required": [ "ref" ], @@ -1243,12 +1847,21 @@ }, "title": "Depends On", "description": "The bom-ref identifiers of the components or services that are dependencies of this dependency object." + }, + "provides": { + "type": "array", + "uniqueItems": true, + "items": { + "$ref": "#/definitions/refLinkType" + }, + "title": "Provides", + "description": "The bom-ref identifiers of the components or services that define a given specification or standard, which are provided or implemented by this dependency object.\nFor example, a cryptographic library which implements a cryptographic algorithm. A component which implements another component does not imply that the implementation is in use." } } }, "service": { "type": "object", - "title": "Service Object", + "title": "Service", "required": [ "name" ], @@ -1257,7 +1870,7 @@ "bom-ref": { "$ref": "#/definitions/refType", "title": "BOM Reference", - "description": "An optional identifier which can be used to reference the service elsewhere in the BOM. Every bom-ref MUST be unique within the BOM." + "description": "An optional identifier which can be used to reference the service elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links." }, "provider": { "title": "Provider", @@ -1277,10 +1890,9 @@ "examples": ["ticker-service"] }, "version": { - "type": "string", + "$ref": "#/definitions/version", "title": "Service Version", - "description": "The service version.", - "examples": ["1.0.0"] + "description": "The service version." }, "description": { "type": "string", @@ -1326,7 +1938,7 @@ "type": "array", "items": {"$ref": "#/definitions/externalReference"}, "title": "External References", - "description": "External references provide a way to document systems, sites, and information that may be relevant, but are not included with the BOM. They may also establish specific relationships within or external to the BOM." + "description": "External references provide a way to document systems, sites, and information that may be relevant but are not included with the BOM. They may also establish specific relationships within or external to the BOM." }, "services": { "type": "array", @@ -1346,6 +1958,10 @@ "description": "Provides the ability to document properties in a name-value store. This provides flexibility to include data not officially supported in the standard without having to use additional namespaces or create extensions. Unlike key-value stores, properties support duplicate names, each potentially having different values. Property names of interest to the general public are encouraged to be registered in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy). Formal registration is OPTIONAL.", "items": {"$ref": "#/definitions/property"} }, + "tags": { + "$ref": "#/definitions/tags", + "title": "Tags" + }, "signature": { "$ref": "#/definitions/signature", "title": "Signature", @@ -1365,7 +1981,7 @@ "flow": { "$ref": "#/definitions/dataFlowDirection", "title": "Directional Flow", - "description": "Specifies the flow direction of the data. Direction is relative to the service. Inbound flow states that data enters the service. Outbound flow states that data leaves the service. Bi-directional states that data flows both ways, and unknown states that the direction is not known." + "description": "Specifies the flow direction of the data. Direction is relative to the service. Inbound flow states that data enters the service. Outbound flow states that data leaves the service. Bi-directional states that data flows both ways and unknown states that the direction is not known." }, "classification": { "$ref": "#/definitions/dataClassification" @@ -1387,7 +2003,6 @@ ] }, "governance": { - "type": "object", "title": "Data Governance", "$ref": "#/definitions/dataGovernance" }, @@ -1437,10 +2052,15 @@ "bi-directional", "unknown" ], + "meta:enum": { + "inbound": "Data that enters a service.", + "outbound": "Data that exits a service.", + "bi-directional": "Data flows in and out of the service.", + "unknown": "The directional flow of data is not known." + }, "title": "Data flow direction", - "description": "Specifies the flow direction of the data. Direction is relative to the service. Inbound flow states that data enters the service. Outbound flow states that data leaves the service. Bi-directional states that data flows both ways, and unknown states that the direction is not known." + "description": "Specifies the flow direction of the data. Direction is relative to the service." }, - "copyright": { "type": "object", "title": "Copyright", @@ -1462,89 +2082,21 @@ "additionalProperties": false, "properties": { "identity": { - "type": "object", - "description": "Evidence that substantiates the identity of a component.", - "required": [ "field" ], - "additionalProperties": false, - "properties": { - "field": { - "type": "string", - "enum": [ - "group", "name", "version", "purl", "cpe", "swid", "hash" - ], - "title": "Field", - "description": "The identity field of the component which the evidence describes." - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "title": "Confidence", - "description": "The overall confidence of the evidence from 0 - 1, where 1 is 100% confidence." - }, - "methods": { + "title": "Identity Evidence", + "description": "Evidence that substantiates the identity of a component. The identity may be an object or an array of identity objects. Support for specifying identity as a single object was introduced in CycloneDX v1.5. Arrays were introduced in v1.6. It is RECOMMENDED that all implementations use arrays, even if only one identity object is specified.", + "oneOf" : [ + { "type": "array", - "title": "Methods", - "description": "The methods used to extract and/or analyze the evidence.", - "items": { - "type": "object", - "required": [ - "technique" , - "confidence" - ], - "additionalProperties": false, - "properties": { - "technique": { - "title": "Technique", - "description": "The technique used in this method of analysis.", - "type": "string", - "enum": [ - "source-code-analysis", - "binary-analysis", - "manifest-analysis", - "ast-fingerprint", - "hash-comparison", - "instrumentation", - "dynamic-analysis", - "filename", - "attestation", - "other" - ] - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "title": "Confidence", - "description": "The confidence of the evidence from 0 - 1, where 1 is 100% confidence. Confidence is specific to the technique used. Each technique of analysis can have independent confidence." - }, - "value": { - "type": "string", - "title": "Value", - "description": "The value or contents of the evidence." - } - } - } + "title": "Array of Identity Objects", + "items": { "$ref": "#/definitions/componentIdentityEvidence" } }, - "tools": { - "type": "array", - "uniqueItems": true, - "items": { - "anyOf": [ - { - "title": "Ref", - "$ref": "#/definitions/refLinkType" - }, - { - "title": "BOM-Link Element", - "$ref": "#/definitions/bomLinkElementType" - } - ] - }, - "title": "BOM References", - "description": "The object in the BOM identified by its bom-ref. This is often a component or service, but may be any object type supporting bom-refs. Tools used for analysis should already be defined in the BOM, either in the metadata/tools, components, or formulation." + { + "title": "A Single Identity Object", + "description": "[Deprecated]", + "$ref": "#/definitions/componentIdentityEvidence", + "deprecated": true } - } + ] }, "occurrences": { "type": "array", @@ -1558,24 +2110,48 @@ "bom-ref": { "$ref": "#/definitions/refType", "title": "BOM Reference", - "description": "An optional identifier which can be used to reference the occurrence elsewhere in the BOM. Every bom-ref MUST be unique within the BOM." + "description": "An optional identifier which can be used to reference the occurrence elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links." }, "location": { "type": "string", "title": "Location", "description": "The location or path to where the component was found." + }, + "line": { + "type": "integer", + "minimum": 0, + "title": "Line Number", + "description": "The line number where the component was found." + }, + "offset": { + "type": "integer", + "minimum": 0, + "title": "Offset", + "description": "The offset where the component was found." + }, + "symbol": { + "type": "string", + "title": "Symbol", + "description": "The symbol name that was found associated with the component." + }, + "additionalContext": { + "type": "string", + "title": "Additional Context", + "description": "Any additional context of the detected component (e.g. a code snippet)." } } } }, "callstack": { "type": "object", + "title": "Call Stack", "description": "Evidence of the components use through the callstack.", "additionalProperties": false, "properties": { "frames": { "type": "array", - "title": "Methods", + "title": "Frames", + "description": "Within a call stack, a frame is a discrete unit that encapsulates an execution context, including local variables, parameters, and the return address. As function calls are made, frames are pushed onto the stack, forming an array-like structure that orchestrates the flow of program execution and manages the sequence of function invocations.", "items": { "type": "object", "required": [ @@ -1628,12 +2204,13 @@ }, "licenses": { "$ref": "#/definitions/licenseChoice", - "title": "Component License(s)" + "title": "License Evidence" }, "copyright": { "type": "array", "items": {"$ref": "#/definitions/copyright"}, - "title": "Copyright" + "title": "Copyright Evidence", + "description": "Copyright evidence captures intellectual property assertions, providing evidence of possible ownership and legal protection." } } }, @@ -1648,12 +2225,12 @@ "bom-ref": { "$ref": "#/definitions/refType", "title": "BOM Reference", - "description": "An optional identifier which can be used to reference the composition elsewhere in the BOM. Every bom-ref MUST be unique within the BOM." + "description": "An optional identifier which can be used to reference the composition elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links." }, "aggregate": { "$ref": "#/definitions/aggregateType", "title": "Aggregate", - "description": "Specifies an aggregate type that describe how complete a relationship is.\n\n* __complete__ = The relationship is complete. No further relationships including constituent components, services, or dependencies are known to exist.\n* __incomplete__ = The relationship is incomplete. Additional relationships exist and may include constituent components, services, or dependencies.\n* __incomplete_first_party_only__ = The relationship is incomplete. Only relationships for first-party components, services, or their dependencies are represented.\n* __incomplete_first_party_proprietary_only__ = The relationship is incomplete. Only relationships for first-party components, services, or their dependencies are represented, limited specifically to those that are proprietary.\n* __incomplete_first_party_opensource_only__ = The relationship is incomplete. Only relationships for first-party components, services, or their dependencies are represented, limited specifically to those that are opensource.\n* __incomplete_third_party_only__ = The relationship is incomplete. Only relationships for third-party components, services, or their dependencies are represented.\n* __incomplete_third_party_proprietary_only__ = The relationship is incomplete. Only relationships for third-party components, services, or their dependencies are represented, limited specifically to those that are proprietary.\n* __incomplete_third_party_opensource_only__ = The relationship is incomplete. Only relationships for third-party components, services, or their dependencies are represented, limited specifically to those that are opensource.\n* __unknown__ = The relationship may be complete or incomplete. This usually signifies a 'best-effort' to obtain constituent components, services, or dependencies but the completeness is inconclusive.\n* __not_specified__ = The relationship completeness is not specified.\n" + "description": "Specifies an aggregate type that describe how complete a relationship is." }, "assemblies": { "type": "array", @@ -1712,12 +2289,27 @@ "incomplete_third_party_opensource_only", "unknown", "not_specified" - ] + ], + "meta:enum": { + "complete": "The relationship is complete. No further relationships including constituent components, services, or dependencies are known to exist.", + "incomplete": "The relationship is incomplete. Additional relationships exist and may include constituent components, services, or dependencies.", + "incomplete_first_party_only": "The relationship is incomplete. Only relationships for first-party components, services, or their dependencies are represented.", + "incomplete_first_party_proprietary_only": "The relationship is incomplete. Only relationships for first-party components, services, or their dependencies are represented, limited specifically to those that are proprietary.", + "incomplete_first_party_opensource_only": "The relationship is incomplete. Only relationships for first-party components, services, or their dependencies are represented, limited specifically to those that are opensource.", + "incomplete_third_party_only": "The relationship is incomplete. Only relationships for third-party components, services, or their dependencies are represented.", + "incomplete_third_party_proprietary_only": "The relationship is incomplete. Only relationships for third-party components, services, or their dependencies are represented, limited specifically to those that are proprietary.", + "incomplete_third_party_opensource_only": "The relationship is incomplete. Only relationships for third-party components, services, or their dependencies are represented, limited specifically to those that are opensource.", + "unknown": "The relationship may be complete or incomplete. This usually signifies a 'best-effort' to obtain constituent components, services, or dependencies but the completeness is inconclusive.", + "not_specified": "The relationship completeness is not specified." + } }, "property": { "type": "object", "title": "Lightweight name-value pair", "description": "Provides the ability to document properties in a name-value store. This provides flexibility to include data not officially supported in the standard without having to use additional namespaces or create extensions. Unlike key-value stores, properties support duplicate names, each potentially having different values. Property names of interest to the general public are encouraged to be registered in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy). Formal registration is OPTIONAL.", + "required": [ + "name" + ], "properties": { "name": { "type": "string", @@ -1729,7 +2321,8 @@ "title": "Value", "description": "The value of the property." } - } + }, + "additionalProperties": false }, "localeType": { "type": "string", @@ -1819,12 +2412,8 @@ "description": "One or more alternate names the release may be referred to. This may include unofficial terms used by development and marketing teams (e.g. code names)." }, "tags": { - "type": "array", - "items": { - "type": "string" - }, - "title": "Tags", - "description": "One or more tags that may aid in search or retrieval of the release note." + "$ref": "#/definitions/tags", + "title": "Tags" }, "resolves": { "type": "array", @@ -1884,12 +2473,21 @@ "info", "none", "unknown" - ] + ], + "meta:enum": { + "critical": "Critical severity", + "high": "High severity", + "medium": "Medium severity", + "low": "Low severity", + "info": "Informational warning.", + "none": "None", + "unknown": "The severity is not known" + } }, "scoreMethod": { "type": "string", "title": "Method", - "description": "Specifies the severity or risk scoring methodology or standard used.\n\n* CVSSv2 - [Common Vulnerability Scoring System v2](https://www.first.org/cvss/v2/)\n* CVSSv3 - [Common Vulnerability Scoring System v3](https://www.first.org/cvss/v3-0/)\n* CVSSv31 - [Common Vulnerability Scoring System v3.1](https://www.first.org/cvss/v3-1/)\n* CVSSv4 - [Common Vulnerability Scoring System v4](https://www.first.org/cvss/v4-0/)\n* OWASP - [OWASP Risk Rating Methodology](https://owasp.org/www-community/OWASP_Risk_Rating_Methodology)\n* SSVC - [Stakeholder Specific Vulnerability Categorization](https://github.com/CERTCC/SSVC) (all versions)", + "description": "Specifies the severity or risk scoring methodology or standard used.", "enum": [ "CVSSv2", "CVSSv3", @@ -1898,12 +2496,21 @@ "OWASP", "SSVC", "other" - ] + ], + "meta:enum": { + "CVSSv2": "Common Vulnerability Scoring System v2.0", + "CVSSv3": "Common Vulnerability Scoring System v3.0", + "CVSSv31": "Common Vulnerability Scoring System v3.1", + "CVSSv4": "Common Vulnerability Scoring System v4.0", + "OWASP": "OWASP Risk Rating Methodology", + "SSVC": "Stakeholder Specific Vulnerability Categorization", + "other": "Another severity or risk scoring methodology" + } }, "impactAnalysisState": { "type": "string", "title": "Impact Analysis State", - "description": "Declares the current state of an occurrence of a vulnerability, after automated or manual analysis. \n\n* __resolved__ = the vulnerability has been remediated. \n* __resolved\\_with\\_pedigree__ = the vulnerability has been remediated and evidence of the changes are provided in the affected components pedigree containing verifiable commit history and/or diff(s). \n* __exploitable__ = the vulnerability may be directly or indirectly exploitable. \n* __in\\_triage__ = the vulnerability is being investigated. \n* __false\\_positive__ = the vulnerability is not specific to the component or service and was falsely identified or associated. \n* __not\\_affected__ = the component or service is not affected by the vulnerability. Justification should be specified for all not_affected cases.", + "description": "Declares the current state of an occurrence of a vulnerability, after automated or manual analysis.", "enum": [ "resolved", "resolved_with_pedigree", @@ -1911,12 +2518,20 @@ "in_triage", "false_positive", "not_affected" - ] + ], + "meta:enum": { + "resolved": "The vulnerability has been remediated.", + "resolved_with_pedigree": "The vulnerability has been remediated and evidence of the changes are provided in the affected components pedigree containing verifiable commit history and/or diff(s).", + "exploitable": "The vulnerability may be directly or indirectly exploitable.", + "in_triage": "The vulnerability is being investigated.", + "false_positive": "The vulnerability is not specific to the component or service and was falsely identified or associated.", + "not_affected": "The component or service is not affected by the vulnerability. Justification should be specified for all not_affected cases." + } }, "impactAnalysisJustification": { "type": "string", "title": "Impact Analysis Justification", - "description": "The rationale of why the impact analysis state was asserted. \n\n* __code\\_not\\_present__ = the code has been removed or tree-shaked. \n* __code\\_not\\_reachable__ = the vulnerable code is not invoked at runtime. \n* __requires\\_configuration__ = exploitability requires a configurable option to be set/unset. \n* __requires\\_dependency__ = exploitability requires a dependency that is not present. \n* __requires\\_environment__ = exploitability requires a certain environment which is not present. \n* __protected\\_by\\_compiler__ = exploitability requires a compiler flag to be set/unset. \n* __protected\\_at\\_runtime__ = exploits are prevented at runtime. \n* __protected\\_at\\_perimeter__ = attacks are blocked at physical, logical, or network perimeter. \n* __protected\\_by\\_mitigating\\_control__ = preventative measures have been implemented that reduce the likelihood and/or impact of the vulnerability.", + "description": "The rationale of why the impact analysis state was asserted.", "enum": [ "code_not_present", "code_not_reachable", @@ -1927,7 +2542,18 @@ "protected_at_runtime", "protected_at_perimeter", "protected_by_mitigating_control" - ] + ], + "meta:enum": { + "code_not_present": "The code has been removed or tree-shaked.", + "code_not_reachable": "The vulnerable code is not invoked at runtime.", + "requires_configuration": "Exploitability requires a configurable option to be set/unset.", + "requires_dependency": "Exploitability requires a dependency that is not present.", + "requires_environment": "Exploitability requires a certain environment which is not present.", + "protected_by_compiler": "Exploitability requires a compiler flag to be set/unset.", + "protected_at_runtime": "Exploits are prevented at runtime.", + "protected_at_perimeter": "Attacks are blocked at physical, logical, or network perimeter.", + "protected_by_mitigating_control": "Preventative measures have been implemented that reduce the likelihood and/or impact of the vulnerability." + } }, "rating": { "type": "object", @@ -2000,7 +2626,7 @@ "bom-ref": { "$ref": "#/definitions/refType", "title": "BOM Reference", - "description": "An optional identifier which can be used to reference the vulnerability elsewhere in the BOM. Every bom-ref MUST be unique within the BOM." + "description": "An optional identifier which can be used to reference the vulnerability elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links." }, "id": { "type": "string", @@ -2056,7 +2682,7 @@ "cwes": { "type": "array", "title": "CWEs", - "description": "List of Common Weaknesses Enumerations (CWEs) codes that describes this vulnerability. For example 399 (of https://cwe.mitre.org/data/definitions/399.html)", + "description": "List of Common Weaknesses Enumerations (CWEs) codes that describes this vulnerability.", "examples": [399], "items": { "$ref": "#/definitions/cwe" @@ -2162,6 +2788,8 @@ } }, "tools": { + "title": "Tools", + "description": "The tool(s) used to identify, confirm, or score the vulnerability.", "oneOf": [ { "type": "object", @@ -2174,7 +2802,7 @@ "items": {"$ref": "#/definitions/component"}, "uniqueItems": true, "title": "Components", - "description": "A list of software and hardware components used as tools" + "description": "A list of software and hardware components used as tools." }, "services": { "type": "array", @@ -2217,7 +2845,14 @@ "update", "rollback", "workaround_available" - ] + ], + "meta:enum": { + "can_not_fix": "Can not fix", + "will_not_fix": "Will not fix", + "update": "Update to a different revision or release", + "rollback": "Revert to a previous revision or release", + "workaround_available": "There is a workaround available" + } } }, "detail": { @@ -2280,14 +2915,17 @@ "additionalProperties": false, "properties": { "version": { + "title": "Version", "description": "A single version of a component or service.", "$ref": "#/definitions/version" }, "range": { + "title": "Version Range", "description": "A version range specified in Package URL Version Range syntax (vers) which is defined at https://github.com/package-url/purl-spec/VERSION-RANGE-SPEC.rst", - "$ref": "#/definitions/range" + "$ref": "#/definitions/versionRange" }, "status": { + "title": "Status", "description": "The vulnerability status for the version or range of versions.", "$ref": "#/definitions/affectedStatus", "default": "affected" @@ -2317,19 +2955,43 @@ "affected", "unaffected", "unknown" - ] + ], + "meta:enum": { + "affected": "The version is affected by the vulnerability.", + "unaffected": "The version is not affected by the vulnerability.", + "unknown": "It is unknown (or unspecified) whether the given version is affected." + } }, "version": { - "description": "A single version of a component or service.", + "description": "A single disjunctive version identifier, for a component or service.", "type": "string", - "minLength": 1, - "maxLength": 1024 + "maxLength": 1024, + "examples": [ + "9.0.14", + "v1.33.7", + "7.0.0-M1", + "2.0pre1", + "1.0.0-beta1", + "0.8.15" + ] }, - "range": { + "versionRange": { "description": "A version range specified in Package URL Version Range syntax (vers) which is defined at https://github.com/package-url/purl-spec/VERSION-RANGE-SPEC.rst", "type": "string", "minLength": 1, - "maxLength": 1024 + "maxLength": 4096, + "examples": [ + "vers:cargo/9.0.14", + "vers:npm/1.2.3|>=2.0.0|<5.0.0", + "vers:pypi/0.0.0|0.0.1|0.0.2|0.0.3|1.0|2.0pre1", + "vers:tomee/>=1.0.0-beta1|<=1.7.5|>=7.0.0-M1|<=7.0.7|>=7.1.0|<=7.1.2|>=8.0.0-M1|<=8.0.1", + "vers:gem/>=2.2.0|!= 2.2.1|<2.3.0" + ] + }, + "range": { + "deprecated": true, + "description": "Deprecated definition. use definition `versionRange` instead.", + "$ref": "#/definitions/versionRange" }, "annotations": { "type": "object", @@ -2346,7 +3008,7 @@ "bom-ref": { "$ref": "#/definitions/refType", "title": "BOM Reference", - "description": "An optional identifier which can be used to reference the annotation elsewhere in the BOM. Every bom-ref MUST be unique within the BOM." + "description": "An optional identifier which can be used to reference the annotation elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links." }, "subjects": { "type": "array", @@ -2363,7 +3025,7 @@ } ] }, - "title": "BOM References", + "title": "Subjects", "description": "The object in the BOM identified by its bom-ref. This is often a component or service, but may be any object type supporting bom-refs." }, "annotator": { @@ -2440,7 +3102,7 @@ "bom-ref": { "$ref": "#/definitions/refType", "title": "BOM Reference", - "description": "An optional identifier which can be used to reference the model card elsewhere in the BOM. Every bom-ref MUST be unique within the BOM." + "description": "An optional identifier which can be used to reference the model card elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links." }, "modelParameters": { "type": "object", @@ -2464,7 +3126,14 @@ "reinforcement-learning", "semi-supervised", "self-supervised" - ] + ], + "meta:enum": { + "supervised": "Supervised machine learning involves training an algorithm on labeled data to predict or classify new data based on the patterns learned from the labeled examples.", + "unsupervised": "Unsupervised machine learning involves training algorithms on unlabeled data to discover patterns, structures, or relationships without explicit guidance, allowing the model to identify inherent structures or clusters within the data.", + "reinforcement-learning": "Reinforcement learning is a type of machine learning where an agent learns to make decisions by interacting with an environment to maximize cumulative rewards, through trial and error.", + "semi-supervised": "Semi-supervised machine learning utilizes a combination of labeled and unlabeled data during training to improve model performance, leveraging the benefits of both supervised and unsupervised learning techniques.", + "self-supervised": "Self-supervised machine learning involves training models to predict parts of the input data from other parts of the same data, without requiring external labels, enabling learning from large amounts of unlabeled data." + } } } }, @@ -2490,12 +3159,12 @@ "items" : { "oneOf" : [ { - "title": "Inline Component Data", + "title": "Inline Data Information", "$ref": "#/definitions/componentData" }, { "type": "object", - "title": "Data Component Reference", + "title": "Data Reference", "additionalProperties": false, "properties": { "ref": { @@ -2587,9 +3256,14 @@ "ethicalConsiderations": { "type": "array", "title": "Ethical Considerations", - "description": "What are the ethical (or environmental) risks involved in the application of this model?", + "description": "What are the ethical risks involved in the application of this model?", "items": { "$ref": "#/definitions/risk" } }, + "environmentalConsiderations":{ + "$ref": "#/definitions/environmentalConsiderations", + "title": "Environmental Considerations", + "description": "What are the various environmental impacts the corresponding machine learning model has exhibited across its lifecycle?" + }, "fairnessAssessments": { "type": "array", "title": "Fairness Assessments", @@ -2614,8 +3288,10 @@ "additionalProperties": false, "properties": { "format": { - "description": "The data format for input/output to the model. Example formats include string, image, time-series", - "type": "string" + "title": "Input/Output Format", + "description": "The data format for input/output to the model.", + "type": "string", + "examples": [ "string", "image", "time-series"] } } }, @@ -2629,21 +3305,29 @@ "bom-ref": { "$ref": "#/definitions/refType", "title": "BOM Reference", - "description": "An optional identifier which can be used to reference the dataset elsewhere in the BOM. Every bom-ref MUST be unique within the BOM." + "description": "An optional identifier which can be used to reference the dataset elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links." }, "type": { "type": "string", "title": "Type of Data", - "description": "The general theme or subject matter of the data being specified.\n\n* __source-code__ = Any type of code, code snippet, or data-as-code.\n* __configuration__ = Parameters or settings that may be used by other components.\n* __dataset__ = A collection of data.\n* __definition__ = Data that can be used to create new instances of what the definition defines.\n* __other__ = Any other type of data that does not fit into existing definitions.", + "description": "The general theme or subject matter of the data being specified.", "enum": [ "source-code", "configuration", "dataset", "definition", "other" - ] + ], + "meta:enum": { + "source-code": "Any type of code, code snippet, or data-as-code.", + "configuration": "Parameters or settings that may be used by other components.", + "dataset": "A collection of data.", + "definition": "Data that can be used to create new instances of what the definition defines.", + "other": "Any other type of data that does not fit into existing definitions." + } }, "name": { + "title": "Dataset Name", "description": "The name of the dataset.", "type": "string" }, @@ -2679,6 +3363,7 @@ }, "sensitiveData": { "type": "array", + "title": "Sensitive Data", "description": "A description of any sensitive data in a dataset.", "items": { "type": "string" @@ -2686,11 +3371,11 @@ }, "graphics": { "$ref": "#/definitions/graphicsCollection" }, "description": { + "title": "Dataset Description", "description": "A description of the dataset. Can describe size of dataset, whether it's used for source code, training, testing, or validation, etc.", "type": "string" }, "governance": { - "type": "object", "title": "Data Governance", "$ref": "#/definitions/dataGovernance" } @@ -2699,6 +3384,7 @@ "dataGovernance": { "type": "object", "title": "Data Governance", + "description": "Data governance captures information regarding data ownership, stewardship, and custodianship, providing insights into the individuals or entities responsible for managing, overseeing, and safeguarding the data throughout its lifecycle.", "additionalProperties": false, "properties": { "custodians": { @@ -2750,10 +3436,12 @@ "additionalProperties": false, "properties": { "description": { + "title": "Description", "description": "A description of this collection of graphics.", "type": "string" }, "collection": { + "title": "Collection", "description": "A collection of graphics.", "type": "array", "items": { "$ref": "#/definitions/graphic" } @@ -2762,9 +3450,11 @@ }, "graphic": { "type": "object", + "title": "Graphic", "additionalProperties": false, "properties": { "name": { + "title": "Name", "description": "The name of the graphic.", "type": "string" }, @@ -2777,30 +3467,37 @@ }, "performanceMetric": { "type": "object", + "title": "Performance Metric", "additionalProperties": false, "properties": { "type": { + "title": "Type", "description": "The type of performance metric.", "type": "string" }, "value": { + "title": "Value", "description": "The value of the performance metric.", "type": "string" }, "slice": { + "title": "Slice", "description": "The name of the slice this metric was computed on. By default, assume this metric is not sliced.", "type": "string" }, "confidenceInterval": { + "title": "Confidence Interval", "description": "The confidence interval of the metric.", "type": "object", "additionalProperties": false, "properties": { "lowerBound": { + "title": "Lower Bound", "description": "The lower bound of the confidence interval.", "type": "string" }, "upperBound": { + "title": "Upper Bound", "description": "The upper bound of the confidence interval.", "type": "string" } @@ -2810,13 +3507,16 @@ }, "risk": { "type": "object", + "title": "Risk", "additionalProperties": false, "properties": { "name": { + "title": "Name", "description": "The name of the risk.", "type": "string" }, "mitigationStrategy": { + "title": "Mitigation Strategy", "description": "Strategy used to address this risk.", "type": "string" } @@ -2830,18 +3530,22 @@ "properties": { "groupAtRisk": { "type": "string", + "title": "Group at Risk", "description": "The groups or individuals at risk of being systematically disadvantaged by the model." }, "benefits": { "type": "string", + "title": "Benefits", "description": "Expected benefits to the identified groups." }, "harms": { "type": "string", + "title": "Harms", "description": "Expected harms to the identified groups." }, "mitigationStrategy": { "type": "string", + "title": "Mitigation Strategy", "description": "With respect to the benefits and harms outlined, please describe any mitigation strategy implemented." } } @@ -2851,6 +3555,267 @@ "title": "Data Classification", "description": "Data classification tags data according to its type, sensitivity, and value if altered, stolen, or destroyed." }, + "environmentalConsiderations": { + "type": "object", + "title": "Environmental Considerations", + "description": "Describes various environmental impact metrics.", + "additionalProperties": false, + "properties": { + "energyConsumptions": { + "title": "Energy Consumptions", + "description": "Describes energy consumption information incurred for one or more component lifecycle activities.", + "type": "array", + "items": { + "$ref": "#/definitions/energyConsumption" + } + }, + "properties": { + "type": "array", + "title": "Properties", + "items": { + "$ref": "#/definitions/property" + } + } + } + }, + "energyConsumption": { + "title": "Energy consumption", + "description": "Describes energy consumption information incurred for the specified lifecycle activity.", + "type": "object", + "required": [ + "activity", + "energyProviders", + "activityEnergyCost" + ], + "additionalProperties": false, + "properties": { + "activity": { + "type": "string", + "title": "Activity", + "description": "The type of activity that is part of a machine learning model development or operational lifecycle.", + "enum": [ + "design", + "data-collection", + "data-preparation", + "training", + "fine-tuning", + "validation", + "deployment", + "inference", + "other" + ], + "meta:enum": { + "design": "A model design including problem framing, goal definition and algorithm selection.", + "data-collection": "Model data acquisition including search, selection and transfer.", + "data-preparation": "Model data preparation including data cleaning, labeling and conversion.", + "training": "Model building, training and generalized tuning.", + "fine-tuning": "Refining a trained model to produce desired outputs for a given problem space.", + "validation": "Model validation including model output evaluation and testing.", + "deployment": "Explicit model deployment to a target hosting infrastructure.", + "inference": "Generating an output response from a hosted model from a set of inputs.", + "other": "A lifecycle activity type whose description does not match currently defined values." + } + }, + "energyProviders": { + "title": "Energy Providers", + "description": "The provider(s) of the energy consumed by the associated model development lifecycle activity.", + "type": "array", + "items": { "$ref": "#/definitions/energyProvider" } + }, + "activityEnergyCost": { + "title": "Activity Energy Cost", + "description": "The total energy cost associated with the model lifecycle activity.", + "$ref": "#/definitions/energyMeasure" + }, + "co2CostEquivalent": { + "title": "CO2 Equivalent Cost", + "description": "The CO2 cost (debit) equivalent to the total energy cost.", + "$ref": "#/definitions/co2Measure" + }, + "co2CostOffset": { + "title": "CO2 Cost Offset", + "description": "The CO2 offset (credit) for the CO2 equivalent cost.", + "$ref": "#/definitions/co2Measure" + }, + "properties": { + "type": "array", + "title": "Properties", + "items": { + "$ref": "#/definitions/property" + } + } + } + }, + "energyMeasure": { + "type": "object", + "title": "Energy Measure", + "description": "A measure of energy.", + "required": [ + "value", + "unit" + ], + "additionalProperties": false, + "properties": { + "value": { + "type": "number", + "title": "Value", + "description": "Quantity of energy." + }, + "unit": { + "type": "string", + "enum": [ "kWh" ], + "title": "Unit", + "description": "Unit of energy.", + "meta:enum": { + "kWh": "Kilowatt-hour (kWh) is the energy delivered by one kilowatt (kW) of power for one hour (h)." + } + } + } + }, + "co2Measure": { + "type": "object", + "title": "CO2 Measure", + "description": "A measure of carbon dioxide (CO2).", + "required": [ + "value", + "unit" + ], + "additionalProperties": false, + "properties": { + "value": { + "type": "number", + "title": "Value", + "description": "Quantity of carbon dioxide (CO2)." + }, + "unit": { + "type": "string", + "enum": [ "tCO2eq" ], + "title": "Unit", + "description": "Unit of carbon dioxide (CO2).", + "meta:enum": { + "tCO2eq": "Tonnes (t) of carbon dioxide (CO2) equivalent (eq)." + } + } + } + }, + "energyProvider": { + "type": "object", + "title": "Energy Provider", + "description": "Describes the physical provider of energy used for model development or operations.", + "required": [ + "organization", + "energySource", + "energyProvided" + ], + "additionalProperties": false, + "properties": { + "bom-ref": { + "title": "BOM Reference", + "description": "An optional identifier which can be used to reference the energy provider elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links.", + "$ref": "#/definitions/refType" + }, + "description": { + "type": "string", + "title": "Description", + "description": "A description of the energy provider." + }, + "organization": { + "type": "object", + "title": "Organization", + "$ref": "#/definitions/organizationalEntity" + }, + "energySource": { + "type": "string", + "enum": [ + "coal", + "oil", + "natural-gas", + "nuclear", + "wind", + "solar", + "geothermal", + "hydropower", + "biofuel", + "unknown", + "other" + ], + "meta:enum": { + "coal": "Energy produced by types of coal.", + "oil": "Petroleum products (primarily crude oil and its derivative fuel oils).", + "natural-gas": "Hydrocarbon gas liquids (HGL) that occur as gases at atmospheric pressure and as liquids under higher pressures including Natural gas (C5H12 and heavier), Ethane (C2H6), Propane (C3H8), etc.", + "nuclear": "Energy produced from the cores of atoms (i.e., through nuclear fission or fusion).", + "wind": "Energy produced from moving air.", + "solar": "Energy produced from the sun (i.e., solar radiation).", + "geothermal": "Energy produced from heat within the earth.", + "hydropower": "Energy produced from flowing water.", + "biofuel": "Liquid fuels produced from biomass feedstocks (i.e., organic materials such as plants or animals).", + "unknown": "The energy source is unknown.", + "other": "An energy source that is not listed." + }, + "title": "Energy Source", + "description": "The energy source for the energy provider." + }, + "energyProvided": { + "$ref": "#/definitions/energyMeasure", + "title": "Energy Provided", + "description": "The energy provided by the energy source for an associated activity." + }, + "externalReferences": { + "type": "array", + "items": {"$ref": "#/definitions/externalReference"}, + "title": "External References", + "description": "External references provide a way to document systems, sites, and information that may be relevant but are not included with the BOM. They may also establish specific relationships within or external to the BOM." + } + } + }, + "postalAddress": { + "type": "object", + "title": "Postal address", + "description": "An address used to identify a contactable location.", + "additionalProperties": false, + "properties": { + "bom-ref": { + "title": "BOM Reference", + "description": "An optional identifier which can be used to reference the address elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links.", + "$ref": "#/definitions/refType" + }, + "country": { + "type": "string", + "title": "Country", + "description": "The country name or the two-letter ISO 3166-1 country code." + }, + "region": { + "type": "string", + "title": "Region", + "description": "The region or state in the country.", + "examples": [ "Texas" ] + }, + "locality": { + "type": "string", + "title": "Locality", + "description": "The locality or city within the country.", + "examples": [ "Austin" ] + }, + "postOfficeBoxNumber": { + "type": "string", + "title": "Post Office Box Number", + "description": "The post office box number.", + "examples": [ "901" ] + }, + "postalCode": { + "type": "string", + "title": "Postal Code", + "description": "The postal code.", + "examples": [ "78758" ] + }, + "streetAddress": { + "type": "string", + "title": "Street Address", + "description": "The street address.", + "examples": [ "100 Main Street" ] + } + } + }, "formula": { "title": "Formula", "description": "Describes workflows and resources that captures rules and other aspects of how the associated BOM component or service was formed.", @@ -2859,7 +3824,7 @@ "properties": { "bom-ref": { "title": "BOM Reference", - "description": "An optional identifier which can be used to reference the formula elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.", + "description": "An optional identifier which can be used to reference the formula elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links.", "$ref": "#/definitions/refType" }, "components": { @@ -2913,7 +3878,7 @@ "properties": { "bom-ref": { "title": "BOM Reference", - "description": "An optional identifier which can be used to reference the workflow elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.", + "description": "An optional identifier which can be used to reference the workflow elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links.", "$ref": "#/definitions/refType" }, "uid": { @@ -3056,7 +4021,7 @@ "properties": { "bom-ref": { "title": "BOM Reference", - "description": "An optional identifier which can be used to reference the task elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.", + "description": "An optional identifier which can be used to reference the task elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links.", "$ref": "#/definitions/refType" }, "uid": { @@ -3228,7 +4193,7 @@ "properties": { "bom-ref": { "title": "BOM Reference", - "description": "An optional identifier which can be used to reference the workspace elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.", + "description": "An optional identifier which can be used to reference the workspace elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links.", "$ref": "#/definitions/refType" }, "uid": { @@ -3375,7 +4340,7 @@ "properties": { "bom-ref": { "title": "BOM Reference", - "description": "An optional identifier which can be used to reference the trigger elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.", + "description": "An optional identifier which can be used to reference the trigger elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links.", "$ref": "#/definitions/refType" }, "uid": { @@ -3420,6 +4385,7 @@ }, "conditions": { "type": "array", + "title": "Conditions", "uniqueItems": true, "items": { "$ref": "#/definitions/condition" @@ -3536,7 +4502,7 @@ "properties": { "source": { "title": "Source", - "description": "A references to the component or service that provided the input to the task (e.g., reference to a service with data flow value of `inbound`)", + "description": "A reference to the component or service that provided the input to the task (e.g., reference to a service with data flow value of `inbound`)", "examples": [ "source code repository", "database" @@ -3556,8 +4522,8 @@ "title": "Resource", "description": "A reference to an independent resource provided as an input to a task by the workflow runtime.", "examples": [ - "reference to a configuration file in a repository (i.e., a bom-ref)", - "reference to a scanning service used in a task (i.e., a bom-ref)" + "a reference to a configuration file in a repository (i.e., a bom-ref)", + "a reference to a scanning service used in a task (i.e., a bom-ref)" ], "$ref": "#/definitions/resourceReferenceChoice" }, @@ -3765,7 +4731,21 @@ "release", "clean", "other" - ] + ], + "meta:enum": { + "copy": "A task that copies software or data used to accomplish other tasks in the workflow.", + "clone": "A task that clones a software repository into the workflow in order to retrieve its source code or data for use in a build step.", + "lint": "A task that checks source code for programmatic and stylistic errors.", + "scan": "A task that performs a scan against source code, or built or deployed components and services. Scans are typically run to gather or test for security vulnerabilities or policy compliance.", + "merge": "A task that merges changes or fixes into source code prior to a build step in the workflow.", + "build": "A task that builds the source code, dependencies and/or data into an artifact that can be deployed to and executed on target systems.", + "test": "A task that verifies the functionality of a component or service.", + "deliver": "A task that delivers a built artifact to one or more target repositories or storage systems.", + "deploy": "A task that deploys a built artifact for execution on one or more target systems.", + "release": "A task that releases a built, versioned artifact to a target repository or distribution system.", + "clean": "A task that cleans unnecessary tools, build artifacts and/or data from workflow storage.", + "other": "A workflow task that does not match current task type definitions." + } }, "parameter": { "title": "Parameter", @@ -3790,10 +4770,904 @@ } } }, - "signature": { - "$ref": "jsf-0.82.schema.json#/definitions/signature", - "title": "Signature", - "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)." + "componentIdentityEvidence": { + "type": "object", + "title": "Identity Evidence", + "description": "Evidence that substantiates the identity of a component.", + "required": [ "field" ], + "additionalProperties": false, + "properties": { + "field": { + "type": "string", + "enum": [ + "group", "name", "version", "purl", "cpe", "omniborId", "swhid", "swid", "hash" + ], + "title": "Field", + "description": "The identity field of the component which the evidence describes." + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "title": "Confidence", + "description": "The overall confidence of the evidence from 0 - 1, where 1 is 100% confidence." + }, + "concludedValue": { + "type": "string", + "title": "Concluded Value", + "description": "The value of the field (cpe, purl, etc) that has been concluded based on the aggregate of all methods (if available)." + }, + "methods": { + "type": "array", + "title": "Methods", + "description": "The methods used to extract and/or analyze the evidence.", + "items": { + "type": "object", + "required": [ + "technique" , + "confidence" + ], + "additionalProperties": false, + "properties": { + "technique": { + "title": "Technique", + "description": "The technique used in this method of analysis.", + "type": "string", + "enum": [ + "source-code-analysis", + "binary-analysis", + "manifest-analysis", + "ast-fingerprint", + "hash-comparison", + "instrumentation", + "dynamic-analysis", + "filename", + "attestation", + "other" + ] + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "title": "Confidence", + "description": "The confidence of the evidence from 0 - 1, where 1 is 100% confidence. Confidence is specific to the technique used. Each technique of analysis can have independent confidence." + }, + "value": { + "type": "string", + "title": "Value", + "description": "The value or contents of the evidence." + } + } + } + }, + "tools": { + "type": "array", + "uniqueItems": true, + "items": { + "anyOf": [ + { + "title": "Ref", + "$ref": "#/definitions/refLinkType" + }, + { + "title": "BOM-Link Element", + "$ref": "#/definitions/bomLinkElementType" + } + ] + }, + "title": "BOM References", + "description": "The object in the BOM identified by its bom-ref. This is often a component or service but may be any object type supporting bom-refs. Tools used for analysis should already be defined in the BOM, either in the metadata/tools, components, or formulation." + } + } + }, + "standard": { + "type": "object", + "title": "Standard", + "description": "A standard may consist of regulations, industry or organizational-specific standards, maturity models, best practices, or any other requirements which can be evaluated against or attested to.", + "additionalProperties": false, + "properties": { + "bom-ref": { + "$ref": "#/definitions/refType", + "title": "BOM Reference", + "description": "An optional identifier which can be used to reference the object elsewhere in the BOM. Every bom-ref MUST be unique within the BOM." + }, + "name": { + "type": "string", + "title": "Name", + "description": "The name of the standard. This will often be a shortened, single name of the standard." + }, + "version": { + "type": "string", + "title": "Version", + "description": "The version of the standard." + }, + "description": { + "type": "string", + "title": "Description", + "description": "The description of the standard." + }, + "owner": { + "type": "string", + "title": "Owner", + "description": "The owner of the standard, often the entity responsible for its release." + }, + "requirements": { + "type": "array", + "title": "Requirements", + "description": "The list of requirements comprising the standard.", + "items": { + "type": "object", + "title": "Requirement", + "additionalProperties": false, + "properties": { + "bom-ref": { + "$ref": "#/definitions/refType", + "title": "BOM Reference", + "description": "An optional identifier which can be used to reference the object elsewhere in the BOM. Every bom-ref MUST be unique within the BOM." + }, + "identifier": { + "type": "string", + "title": "Identifier", + "description": "The unique identifier used in the standard to identify a specific requirement. This should match what is in the standard and should not be the requirements bom-ref." + }, + "title": { + "type": "string", + "title": "Title", + "description": "The title of the requirement." + }, + "text": { + "type": "string", + "title": "Text", + "description": "The textual content of the requirement." + }, + "descriptions": { + "type": "array", + "title": "Descriptions", + "description": "The supplemental text that provides additional guidance or context to the requirement, but is not directly part of the requirement.", + "items": { "type": "string" } + }, + "openCre": { + "type": "array", + "title": "OWASP OpenCRE Identifier(s)", + "description": "The Common Requirements Enumeration (CRE) identifier(s). CRE is a structured and standardized framework for uniting security standards and guidelines. CRE links each section of a resource to a shared topic identifier (a Common Requirement). Through this shared topic link, all resources map to each other. Use of CRE promotes clear and unambiguous communication among stakeholders.", + "items": { + "type": "string", + "pattern": "^CRE:[0-9]+-[0-9]+$", + "examples": [ "CRE:764-507" ] + } + }, + "parent": { + "$ref": "#/definitions/refLinkType", + "title": "Parent BOM Reference", + "description": "The optional `bom-ref` to a parent requirement. This establishes a hierarchy of requirements. Top-level requirements must not define a parent. Only child requirements should define parents." + }, + "properties": { + "type": "array", + "title": "Properties", + "description": "Provides the ability to document properties in a name-value store. This provides flexibility to include data not officially supported in the standard without having to use additional namespaces or create extensions. Unlike key-value stores, properties support duplicate names, each potentially having different values. Property names of interest to the general public are encouraged to be registered in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy). Formal registration is OPTIONAL.", + "items": { + "$ref": "#/definitions/property" + } + }, + "externalReferences": { + "type": "array", + "items": {"$ref": "#/definitions/externalReference"}, + "title": "External References", + "description": "External references provide a way to document systems, sites, and information that may be relevant, but are not included with the BOM. They may also establish specific relationships within or external to the BOM." + } + } + } + }, + "levels": { + "type": "array", + "title": "Levels", + "description": "The list of levels associated with the standard. Some standards have different levels of compliance.", + "items": { + "type": "object", + "title": "Level", + "additionalProperties": false, + "properties": { + "bom-ref": { + "$ref": "#/definitions/refType", + "title": "BOM Reference", + "description": "An optional identifier which can be used to reference the object elsewhere in the BOM. Every bom-ref MUST be unique within the BOM." + }, + "identifier": { + "type": "string", + "title": "Identifier", + "description": "The identifier used in the standard to identify a specific level." + }, + "title": { + "type": "string", + "title": "Title", + "description": "The title of the level." + }, + "description": { + "type": "string", + "title": "Description", + "description": "The description of the level." + }, + "requirements": { + "type": "array", + "title": "Requirements", + "description": "The list of requirement `bom-ref`s that comprise the level.", + "items": { "$ref": "#/definitions/refLinkType" } + } + } + } + }, + "externalReferences": { + "type": "array", + "items": {"$ref": "#/definitions/externalReference"}, + "title": "External References", + "description": "External references provide a way to document systems, sites, and information that may be relevant but are not included with the BOM. They may also establish specific relationships within or external to the BOM." + }, + "signature": { + "$ref": "#/definitions/signature", + "title": "Signature", + "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)." + } + } + }, + "signature": { + "$ref": "jsf-0.82.schema.json#/definitions/signature", + "title": "Signature", + "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)." + }, + "cryptoProperties": { + "type": "object", + "title": "Cryptographic Properties", + "description": "Cryptographic assets have properties that uniquely define them and that make them actionable for further reasoning. As an example, it makes a difference if one knows the algorithm family (e.g. AES) or the specific variant or instantiation (e.g. AES-128-GCM). This is because the security level and the algorithm primitive (authenticated encryption) are only defined by the definition of the algorithm variant. The presence of a weak cryptographic algorithm like SHA1 vs. HMAC-SHA1 also makes a difference.", + "additionalProperties": false, + "required": [ + "assetType" + ], + "properties": { + "assetType": { + "type": "string", + "title": "Asset Type", + "description": "Cryptographic assets occur in several forms. Algorithms and protocols are most commonly implemented in specialized cryptographic libraries. They may, however, also be 'hardcoded' in software components. Certificates and related cryptographic material like keys, tokens, secrets or passwords are other cryptographic assets to be modelled.", + "enum": [ + "algorithm", + "certificate", + "protocol", + "related-crypto-material" + ], + "meta:enum": { + "algorithm": "Mathematical function commonly used for data encryption, authentication, and digital signatures.", + "certificate": "An electronic document that is used to provide the identity or validate a public key.", + "protocol": "A set of rules and guidelines that govern the behavior and communication with each other.", + "related-crypto-material": "Other cryptographic assets related to algorithms, certificates, and protocols such as keys and tokens." + } + }, + "algorithmProperties": { + "type": "object", + "title": "Algorithm Properties", + "description": "Additional properties specific to a cryptographic algorithm.", + "additionalProperties": false, + "properties": { + "primitive": { + "type": "string", + "title": "primitive", + "description": "Cryptographic building blocks used in higher-level cryptographic systems and protocols. Primitives represent different cryptographic routines: deterministic random bit generators (drbg, e.g. CTR_DRBG from NIST SP800-90A-r1), message authentication codes (mac, e.g. HMAC-SHA-256), blockciphers (e.g. AES), streamciphers (e.g. Salsa20), signatures (e.g. ECDSA), hash functions (e.g. SHA-256), public-key encryption schemes (pke, e.g. RSA), extended output functions (xof, e.g. SHAKE256), key derivation functions (e.g. pbkdf2), key agreement algorithms (e.g. ECDH), key encapsulation mechanisms (e.g. ML-KEM), authenticated encryption (ae, e.g. AES-GCM) and the combination of multiple algorithms (combiner, e.g. SP800-56Cr2).", + "enum": [ + "drbg", + "mac", + "block-cipher", + "stream-cipher", + "signature", + "hash", + "pke", + "xof", + "kdf", + "key-agree", + "kem", + "ae", + "combiner", + "other", + "unknown" + ], + "meta:enum": { + "drbg": "Deterministic Random Bit Generator (DRBG) is a type of pseudorandom number generator designed to produce a sequence of bits from an initial seed value. DRBGs are commonly used in cryptographic applications where reproducibility of random values is important.", + "mac": "In cryptography, a Message Authentication Code (MAC) is information used for authenticating and integrity-checking a message.", + "block-cipher": "A block cipher is a symmetric key algorithm that operates on fixed-size blocks of data. It encrypts or decrypts the data in block units, providing confidentiality. Block ciphers are widely used in various cryptographic modes and protocols for secure data transmission.", + "stream-cipher": "A stream cipher is a symmetric key cipher where plaintext digits are combined with a pseudorandom cipher digit stream (keystream).", + "signature": "In cryptography, a signature is a digital representation of a message or data that proves its origin, identity, and integrity. Digital signatures are generated using cryptographic algorithms and are widely used for authentication and verification in secure communication.", + "hash": "A hash function is a mathematical algorithm that takes an input (or 'message') and produces a fixed-size string of characters, which is typically a hash value. Hash functions are commonly used in various cryptographic applications, including data integrity verification and password hashing.", + "pke": "Public Key Encryption (PKE) is a type of encryption that uses a pair of public and private keys for secure communication. The public key is used for encryption, while the private key is used for decryption. PKE is a fundamental component of public-key cryptography.", + "xof": "An XOF is an extendable output function that can take arbitrary input and creates a stream of output, up to a limit determined by the size of the internal state of the hash function that underlies the XOF.", + "kdf": "A Key Derivation Function (KDF) derives key material from another source of entropy while preserving the entropy of the input.", + "key-agree": "In cryptography, a key-agreement is a protocol whereby two or more parties agree on a cryptographic key in such a way that both influence the outcome.", + "kem": "A Key Encapsulation Mechanism (KEM) algorithm is a mechanism for transporting random keying material to a recipient using the recipient's public key.", + "ae": "Authenticated Encryption (AE) is a cryptographic process that provides both confidentiality and data integrity. It ensures that the encrypted data has not been tampered with and comes from a legitimate source. AE is commonly used in secure communication protocols.", + "combiner": "A combiner aggregates many candidates for a cryptographic primitive and generates a new candidate for the same primitive.", + "other": "Another primitive type.", + "unknown": "The primitive is not known." + } + }, + "parameterSetIdentifier": { + "type": "string", + "title": "Parameter Set Identifier", + "description": "An identifier for the parameter set of the cryptographic algorithm. Examples: in AES128, '128' identifies the key length in bits, in SHA256, '256' identifies the digest length, '128' in SHAKE128 identifies its maximum security level in bits, and 'SHA2-128s' identifies a parameter set used in SLH-DSA (FIPS205)." + }, + "curve": { + "type": "string", + "title": "Elliptic Curve", + "description": "The specific underlying Elliptic Curve (EC) definition employed which is an indicator of the level of security strength, performance and complexity. Absent an authoritative source of curve names, CycloneDX recommends using curve names as defined at [https://neuromancer.sk/std/](https://neuromancer.sk/std/), the source of which can be found at [https://github.com/J08nY/std-curves](https://github.com/J08nY/std-curves)." + }, + "executionEnvironment": { + "type": "string", + "title": "Execution Environment", + "description": "The target and execution environment in which the algorithm is implemented in.", + "enum": [ + "software-plain-ram", + "software-encrypted-ram", + "software-tee", + "hardware", + "other", + "unknown" + ], + "meta:enum": { + "software-plain-ram": "A software implementation running in plain unencrypted RAM.", + "software-encrypted-ram": "A software implementation running in encrypted RAM.", + "software-tee": "A software implementation running in a trusted execution environment.", + "hardware": "A hardware implementation.", + "other": "Another implementation environment.", + "unknown": "The execution environment is not known." + } + }, + "implementationPlatform": { + "type": "string", + "title": "implementation platform", + "description": "The target platform for which the algorithm is implemented. The implementation can be 'generic', running on any platform or for a specific platform.", + "enum": [ + "generic", + "x86_32", + "x86_64", + "armv7-a", + "armv7-m", + "armv8-a", + "armv8-m", + "armv9-a", + "armv9-m", + "s390x", + "ppc64", + "ppc64le", + "other", + "unknown" + ] + }, + "certificationLevel": { + "type": "array", + "title": "Certification Level", + "description": "The certification that the implementation of the cryptographic algorithm has received, if any. Certifications include revisions and levels of FIPS 140 or Common Criteria of different Extended Assurance Levels (CC-EAL).", + "items": { + "type": "string", + "enum": [ + "none", + "fips140-1-l1", + "fips140-1-l2", + "fips140-1-l3", + "fips140-1-l4", + "fips140-2-l1", + "fips140-2-l2", + "fips140-2-l3", + "fips140-2-l4", + "fips140-3-l1", + "fips140-3-l2", + "fips140-3-l3", + "fips140-3-l4", + "cc-eal1", + "cc-eal1+", + "cc-eal2", + "cc-eal2+", + "cc-eal3", + "cc-eal3+", + "cc-eal4", + "cc-eal4+", + "cc-eal5", + "cc-eal5+", + "cc-eal6", + "cc-eal6+", + "cc-eal7", + "cc-eal7+", + "other", + "unknown" + ], + "meta:enum": { + "none": "No certification obtained", + "fips140-1-l1": "FIPS 140-1 Level 1", + "fips140-1-l2": "FIPS 140-1 Level 2", + "fips140-1-l3": "FIPS 140-1 Level 3", + "fips140-1-l4": "FIPS 140-1 Level 4", + "fips140-2-l1": "FIPS 140-2 Level 1", + "fips140-2-l2": "FIPS 140-2 Level 2", + "fips140-2-l3": "FIPS 140-2 Level 3", + "fips140-2-l4": "FIPS 140-2 Level 4", + "fips140-3-l1": "FIPS 140-3 Level 1", + "fips140-3-l2": "FIPS 140-3 Level 2", + "fips140-3-l3": "FIPS 140-3 Level 3", + "fips140-3-l4": "FIPS 140-3 Level 4", + "cc-eal1": "Common Criteria - Evaluation Assurance Level 1", + "cc-eal1+": "Common Criteria - Evaluation Assurance Level 1 (Augmented)", + "cc-eal2": "Common Criteria - Evaluation Assurance Level 2", + "cc-eal2+": "Common Criteria - Evaluation Assurance Level 2 (Augmented)", + "cc-eal3": "Common Criteria - Evaluation Assurance Level 3", + "cc-eal3+": "Common Criteria - Evaluation Assurance Level 3 (Augmented)", + "cc-eal4": "Common Criteria - Evaluation Assurance Level 4", + "cc-eal4+": "Common Criteria - Evaluation Assurance Level 4 (Augmented)", + "cc-eal5": "Common Criteria - Evaluation Assurance Level 5", + "cc-eal5+": "Common Criteria - Evaluation Assurance Level 5 (Augmented)", + "cc-eal6": "Common Criteria - Evaluation Assurance Level 6", + "cc-eal6+": "Common Criteria - Evaluation Assurance Level 6 (Augmented)", + "cc-eal7": "Common Criteria - Evaluation Assurance Level 7", + "cc-eal7+": "Common Criteria - Evaluation Assurance Level 7 (Augmented)", + "other": "Another certification", + "unknown": "The certification level is not known" + } + } + }, + "mode": { + "type": "string", + "title": "Mode", + "description": "The mode of operation in which the cryptographic algorithm (block cipher) is used.", + "enum": [ + "cbc", + "ecb", + "ccm", + "gcm", + "cfb", + "ofb", + "ctr", + "other", + "unknown" + ], + "meta:enum": { + "cbc": "Cipher block chaining", + "ecb": "Electronic codebook", + "ccm": "Counter with cipher block chaining message authentication code", + "gcm": "Galois/counter", + "cfb": "Cipher feedback", + "ofb": "Output feedback", + "ctr": "Counter", + "other": "Another mode of operation", + "unknown": "The mode of operation is not known" + } + }, + "padding": { + "type": "string", + "title": "Padding", + "description": "The padding scheme that is used for the cryptographic algorithm.", + "enum": [ + "pkcs5", + "pkcs7", + "pkcs1v15", + "oaep", + "raw", + "other", + "unknown" + ], + "meta:enum": { + "pkcs5": "Public Key Cryptography Standard: Password-Based Cryptography", + "pkcs7": "Public Key Cryptography Standard: Cryptographic Message Syntax", + "pkcs1v15": "Public Key Cryptography Standard: RSA Cryptography v1.5", + "oaep": "Optimal asymmetric encryption padding", + "raw": "Raw", + "other": "Another padding scheme", + "unknown": "The padding scheme is not known" + } + }, + "cryptoFunctions": { + "type": "array", + "title": "Cryptographic functions", + "description": "The cryptographic functions implemented by the cryptographic algorithm.", + "items": { + "type": "string", + "enum": [ + "generate", + "keygen", + "encrypt", + "decrypt", + "digest", + "tag", + "keyderive", + "sign", + "verify", + "encapsulate", + "decapsulate", + "other", + "unknown" + ] + } + }, + "classicalSecurityLevel": { + "type": "integer", + "title": "classical security level", + "description": "The classical security level that a cryptographic algorithm provides (in bits).", + "minimum": 0 + }, + "nistQuantumSecurityLevel": { + "type": "integer", + "title": "NIST security strength category", + "description": "The NIST security strength category as defined in https://csrc.nist.gov/projects/post-quantum-cryptography/post-quantum-cryptography-standardization/evaluation-criteria/security-(evaluation-criteria). A value of 0 indicates that none of the categories are met.", + "minimum": 0, + "maximum": 6 + } + } + }, + "certificateProperties": { + "type": "object", + "title": "Certificate Properties", + "description": "Properties for cryptographic assets of asset type 'certificate'", + "additionalProperties": false, + "properties": { + "subjectName": { + "type": "string", + "title": "Subject Name", + "description": "The subject name for the certificate" + }, + "issuerName": { + "type": "string", + "title": "Issuer Name", + "description": "The issuer name for the certificate" + }, + "notValidBefore": { + "type": "string", + "format": "date-time", + "title": "Not Valid Before", + "description": "The date and time according to ISO-8601 standard from which the certificate is valid" + }, + "notValidAfter": { + "type": "string", + "format": "date-time", + "title": "Not Valid After", + "description": "The date and time according to ISO-8601 standard from which the certificate is not valid anymore" + }, + "signatureAlgorithmRef": { + "$ref": "#/definitions/refType", + "title": "Algorithm Reference", + "description": "The bom-ref to signature algorithm used by the certificate" + }, + "subjectPublicKeyRef": { + "$ref": "#/definitions/refType", + "title": "Key reference", + "description": "The bom-ref to the public key of the subject" + }, + "certificateFormat": { + "type": "string", + "title": "Certificate Format", + "description": "The format of the certificate", + "examples": [ + "X.509", + "PEM", + "DER", + "CVC" + ] + }, + "certificateExtension": { + "type": "string", + "title": "Certificate File Extension", + "description": "The file extension of the certificate", + "examples": [ + "crt", + "pem", + "cer", + "der", + "p12" + ] + } + } + }, + "relatedCryptoMaterialProperties": { + "type": "object", + "title": "Related Cryptographic Material Properties", + "description": "Properties for cryptographic assets of asset type: `related-crypto-material`", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "title": "relatedCryptoMaterialType", + "description": "The type for the related cryptographic material", + "enum": [ + "private-key", + "public-key", + "secret-key", + "key", + "ciphertext", + "signature", + "digest", + "initialization-vector", + "nonce", + "seed", + "salt", + "shared-secret", + "tag", + "additional-data", + "password", + "credential", + "token", + "other", + "unknown" + ], + "meta:enum": { + "private-key": "The confidential key of a key pair used in asymmetric cryptography.", + "public-key": "The non-confidential key of a key pair used in asymmetric cryptography.", + "secret-key": "A key used to encrypt and decrypt messages in symmetric cryptography.", + "key": "A piece of information, usually an octet string, which, when processed through a cryptographic algorithm, processes cryptographic data.", + "ciphertext": "The result of encryption performed on plaintext using an algorithm (or cipher).", + "signature": "A cryptographic value that is calculated from the data and a key known only by the signer.", + "digest": "The output of the hash function.", + "initialization-vector": "A fixed-size random or pseudo-random value used as an input parameter for cryptographic algorithms.", + "nonce": "A random or pseudo-random number that can only be used once in a cryptographic communication.", + "seed": "The input to a pseudo-random number generator. Different seeds generate different pseudo-random sequences.", + "salt": "A value used in a cryptographic process, usually to ensure that the results of computations for one instance cannot be reused by an attacker.", + "shared-secret": "A piece of data known only to the parties involved, in a secure communication.", + "tag": "A message authentication code (MAC), sometimes known as an authentication tag, is a short piece of information used for authenticating and integrity-checking a message.", + "additional-data": "An unspecified collection of data with relevance to cryptographic activity.", + "password": "A secret word, phrase, or sequence of characters used during authentication or authorization.", + "credential": "Establishes the identity of a party to communication, usually in the form of cryptographic keys or passwords.", + "token": "An object encapsulating a security identity.", + "other": "Another type of cryptographic asset.", + "unknown": "The type of cryptographic asset is not known." + } + }, + "id": { + "type": "string", + "title": "ID", + "description": "The optional unique identifier for the related cryptographic material." + }, + "state": { + "type": "string", + "title": "State", + "description": "The key state as defined by NIST SP 800-57.", + "enum": [ + "pre-activation", + "active", + "suspended", + "deactivated", + "compromised", + "destroyed" + ] + }, + "algorithmRef": { + "$ref": "#/definitions/refType", + "title": "Algorithm Reference", + "description": "The bom-ref to the algorithm used to generate the related cryptographic material." + }, + "creationDate": { + "type": "string", + "format": "date-time", + "title": "Creation Date", + "description": "The date and time (timestamp) when the related cryptographic material was created." + }, + "activationDate": { + "type": "string", + "format": "date-time", + "title": "Activation Date", + "description": "The date and time (timestamp) when the related cryptographic material was activated." + }, + "updateDate": { + "type": "string", + "format": "date-time", + "title": "Update Date", + "description": "The date and time (timestamp) when the related cryptographic material was updated." + }, + "expirationDate": { + "type": "string", + "format": "date-time", + "title": "Expiration Date", + "description": "The date and time (timestamp) when the related cryptographic material expires." + }, + "value": { + "type": "string", + "title": "Value", + "description": "The associated value of the cryptographic material." + }, + "size": { + "type": "integer", + "title":"Size", + "description": "The size of the cryptographic asset (in bits)." + }, + "format": { + "type": "string", + "title": "Format", + "description": "The format of the related cryptographic material (e.g. P8, PEM, DER)." + }, + "securedBy": { + "$ref": "#/definitions/securedBy", + "title": "Secured By", + "description": "The mechanism by which the cryptographic asset is secured by." + } + } + }, + "protocolProperties": { + "type": "object", + "title": "Protocol Properties", + "description": "Properties specific to cryptographic assets of type: `protocol`.", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "title": "Type", + "description": "The concrete protocol type.", + "enum": [ + "tls", + "ssh", + "ipsec", + "ike", + "sstp", + "wpa", + "other", + "unknown" + ], + "meta:enum": { + "tls": "Transport Layer Security", + "ssh": "Secure Shell", + "ipsec": "Internet Protocol Security", + "ike": "Internet Key Exchange", + "sstp": "Secure Socket Tunneling Protocol", + "wpa": "Wi-Fi Protected Access", + "other": "Another protocol type", + "unknown": "The protocol type is not known" + } + }, + "version": { + "type": "string", + "title": "Protocol Version", + "description": "The version of the protocol.", + "examples": [ + "1.0", + "1.2", + "1.99" + ] + }, + "cipherSuites": { + "type": "array", + "title": "Cipher Suites", + "description": "A list of cipher suites related to the protocol.", + "items": { + "$ref": "#/definitions/cipherSuite", + "title": "Cipher Suite" + } + }, + "ikev2TransformTypes": { + "type": "object", + "title": "IKEv2 Transform Types", + "description": "The IKEv2 transform types supported (types 1-4), defined in RFC7296 section 3.3.2, and additional properties.", + "additionalProperties": false, + "properties": { + "encr": { + "$ref": "#/definitions/cryptoRefArray", + "title": "Encryption Algorithm (ENCR)", + "description": "Transform Type 1: encryption algorithms" + }, + "prf": { + "$ref": "#/definitions/cryptoRefArray", + "title": "Pseudorandom Function (PRF)", + "description": "Transform Type 2: pseudorandom functions" + }, + "integ": { + "$ref": "#/definitions/cryptoRefArray", + "title": "Integrity Algorithm (INTEG)", + "description": "Transform Type 3: integrity algorithms" + }, + "ke": { + "$ref": "#/definitions/cryptoRefArray", + "title": "Key Exchange Method (KE)", + "description": "Transform Type 4: Key Exchange Method (KE) per RFC9370, formerly called Diffie-Hellman Group (D-H)" + }, + "esn": { + "type": "boolean", + "title": "Extended Sequence Numbers (ESN)", + "description": "Specifies if an Extended Sequence Number (ESN) is used." + }, + "auth": { + "$ref": "#/definitions/cryptoRefArray", + "title": "IKEv2 Authentication method", + "description": "IKEv2 Authentication method" + } + } + }, + "cryptoRefArray": { + "$ref": "#/definitions/cryptoRefArray", + "title": "Cryptographic References", + "description": "A list of protocol-related cryptographic assets" + } + } + }, + "oid": { + "type": "string", + "title": "OID", + "description": "The object identifier (OID) of the cryptographic asset." + } + } + }, + "cipherSuite": { + "type": "object", + "title": "Cipher Suite", + "description": "Object representing a cipher suite", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "title": "Common Name", + "description": "A common name for the cipher suite.", + "examples": [ + "TLS_DHE_RSA_WITH_AES_128_CCM" + ] + }, + "algorithms": { + "type": "array", + "title": "Related Algorithms", + "description": "A list of algorithms related to the cipher suite.", + "items": { + "$ref": "#/definitions/refType", + "title": "Algorithm reference", + "description": "The bom-ref to algorithm cryptographic asset." + } + }, + "identifiers": { + "type": "array", + "title": "Cipher Suite Identifiers", + "description": "A list of common identifiers for the cipher suite.", + "items": { + "type": "string", + "title": "identifier", + "description": "Cipher suite identifier", + "examples": [ + "0xC0", + "0x9E" + ] + } + } + } + }, + "cryptoRefArray" : { + "type": "array", + "items": { + "$ref": "#/definitions/refType" + } + }, + "securedBy": { + "type": "object", + "title": "Secured By", + "description": "Specifies the mechanism by which the cryptographic asset is secured by", + "additionalProperties": false, + "properties": { + "mechanism": { + "type": "string", + "title": "Mechanism", + "description": "Specifies the mechanism by which the cryptographic asset is secured by.", + "examples": [ + "HSM", + "TPM", + "SGX", + "Software", + "None" + ] + }, + "algorithmRef": { + "$ref": "#/definitions/refType", + "title": "Algorithm Reference", + "description": "The bom-ref to the algorithm." + } + } + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Tags", + "description": "Textual strings that aid in discovery, search, and retrieval of the associated object. Tags often serve as a way to group or categorize similar or related objects by various attributes.", + "examples": [ + "json-parser", + "object-persistence", + "text-to-image", + "translation", + "object-detection" + ] } } -} +} \ No newline at end of file diff --git a/schema/cyclonedx/cyclonedx.xsd b/schema/cyclonedx/cyclonedx.xsd index eeb64a6ac..f90bb8e43 100644 --- a/schema/cyclonedx/cyclonedx.xsd +++ b/schema/cyclonedx/cyclonedx.xsd @@ -1,6 +1,6 @@ + version="1.6.0"> - + - CycloneDX Software Bill of Materials Standard + CycloneDX Bill of Materials Standard https://cyclonedx.org/ Apache License, Version 2.0 @@ -54,6 +54,45 @@ limitations under the License. + + + + + + + + + + + + =2.0.0|<5.0.0" + - "vers:pypi/0.0.0|0.0.1|0.0.2|0.0.3|1.0|2.0pre1" + - "vers:tomee/>=1.0.0-beta1|<=1.7.5|>=7.0.0-M1|<=7.0.7|>=7.1.0|<=7.1.2|>=8.0.0-M1|<=8.0.1" + - "vers:gem/>=2.2.0|!= 2.2.1|<2.3.0" + ]]> + + + + + + + + @@ -92,7 +131,7 @@ limitations under the License. - The product lifecycle(s) that this BOM represents. + Lifecycles communicate the stage(s) in which data in the BOM was captured. Different types of data may be available at various phases of a lifecycle, such as the Software Development Lifecycle (SDLC), IT Asset Management (ITAM), and Software Asset Management (SAM). Thus, a BOM may include data specific to or only obtainable in a given lifecycle. @@ -161,8 +200,10 @@ limitations under the License. - The person(s) who created the BOM. Authors are common in BOMs created through - manual processes. BOMs created through automated means may not have authors. + + The person(s) who created the BOM. + Authors are common in BOMs created through manual processes. BOMs created through automated means may have './manufacturer' instead. + @@ -175,9 +216,20 @@ limitations under the License. The component that the BOM describes. + + + + The organization that created the BOM. + Manufacturer is common in BOMs created through automated processes. BOMs created through manual means may have './authors' instead. + + + - The organization that manufactured the component that the BOM describes. + + DEPRECATED - DO NOT USE. This will be removed in a future version. Use the `./component/manufacturer` instead. + The organization that manufactured the component that the BOM describes. + @@ -186,7 +238,14 @@ limitations under the License. supplier may often be the manufacturer, but may also be a distributor or repackager. - + + + + The license information for the BOM document. + This may be different from the license(s) of the component(s) that the BOM describes. + + + Provides the ability to document properties in a name/value store. @@ -289,6 +348,11 @@ limitations under the License. The name of the organization + + + The physical address (location) of the organization. + + The URL of the organization. Multiple URLs are allowed. @@ -338,7 +402,7 @@ limitations under the License. The name of the tool - + The version of the tool @@ -439,9 +503,33 @@ limitations under the License. be the manufacturer, but may also be a distributor or repackager. + + + + The organization that created the component. + Manufacturer is common in components created through automated processes. Components created through manual means may have './authors' instead. + + + + + + + The person(s) who created the component. + Authors are common in components created through manual processes. Components created through automated means may have `./manufacturer` instead. + + + + + + + + - The person(s) or organization(s) that authored the component + + DEPRECATED - DO NOT USE. This will be removed in a future version. Use `./authors` or `./manufacturer` instead. + The person(s) or organization(s) that authored the component. + @@ -463,7 +551,7 @@ limitations under the License. of the component. Examples: commons-lang3 and jquery - + The component version. The version should ideally comply with semantic versioning but is not enforced. @@ -509,6 +597,23 @@ limitations under the License. + + + + Specifies the OmniBOR Artifact ID. The OmniBOR, if specified, MUST be valid and conform + to the specification defined at: https://www.iana.org/assignments/uri-schemes/prov/gitoid + + + + + + + Specifies the Software Heritage persistent identifier (SWHID). The SWHID, if specified, MUST + be valid and conform to the specification defined at: + https://docs.softwareheritage.org/devel/swh-model/persistent-identifiers.html + + + @@ -597,6 +702,19 @@ limitations under the License. specified for other component types. + + + + Cryptographic assets have properties that uniquely define them and that make them actionable + for further reasoning. As an example, it makes a difference if one knows the algorithm family + (e.g. AES) or the specific variant or instantiation (e.g. AES-128-GCM). This is because the + security level and the algorithm primitive (authenticated encryption) is only defined by the + definition of the algorithm variant. The presence of a weak cryptographic algorithm like SHA1 + vs. HMAC-SHA1 also makes a difference. + + + + @@ -646,7 +764,7 @@ limitations under the License. A valid SPDX license ID - + If SPDX does not define the license used, this field may be used to provide the license name @@ -814,6 +932,23 @@ limitations under the License. + + + + Declared licenses and concluded licenses represent two different stages in the + licensing process within software development. Declared licenses refer to the + initial intention of the software authors regarding the licensing terms under + which their code is released. On the other hand, concluded licenses are the + result of a comprehensive analysis of the project's codebase to identify and + confirm the actual licenses of the components used, which may differ from the + initially declared licenses. While declared licenses provide an upfront indication + of the licensing intentions, concluded licenses offer a more thorough understanding + of the actual licensing within a project, facilitating proper compliance and risk + management. Observed licenses are defined in `evidence.licenses`. Observed licenses + form the evidence necessary to substantiate a concluded license. + + + @@ -960,6 +1095,11 @@ limitations under the License. A collection of discrete values that convey information. + + + A cryptographic asset including algorithms, protocols, certificates, keys, tokens, and secrets. + + @@ -1222,6 +1362,11 @@ limitations under the License. Community or commercial support + + + The location where the source code distributable can be obtained. This is often an archive format such as zip or tgz. The source-distribution type complements use of the version control (vcs) type. + + Direct or repository download location @@ -1255,7 +1400,7 @@ limitations under the License. - Specifies a way to contact the maintainer, supplier, or provider in the event of a security incident. Common URIs include links to a disclosure procedure, a mailto (RFC-2368) that specifies an email address, a tel (RFC-3966) that specifies a phone number, or dns (RFC-4501]) that specifies the records containing DNS Security TXT. + Specifies a way to contact the maintainer, supplier, or provider in the event of a security incident. Common URIs include links to a disclosure procedure, a mailto (RFC-2368) that specifies an email address, a tel (RFC-3966) that specifies a phone number, or dns (RFC-4501) that specifies the records containing DNS Security TXT. @@ -1362,7 +1507,22 @@ limitations under the License. - Plans of Action and Milestones (POAM) compliment an "attestation" external reference. POAM is defined by NIST as a "document that identifies tasks needing to be accomplished. It details resources required to accomplish the elements of the plan, any milestones in meeting the tasks and scheduled completion dates for the milestones". + Plans of Action and Milestones (POAM) complement an "attestation" external reference. POAM is defined by NIST as a "document that identifies tasks needing to be accomplished. It details resources required to accomplish the elements of the plan, any milestones in meeting the tasks and scheduled completion dates for the milestones". + + + + + An e-signature is commonly a scanned representation of a written signature or a stylized script of the persons name. + + + + + A signature that leverages cryptography, typically public/private key pairs, which provides strong authenticity verification. + + + + + Document that complies with RFC-9116 (A File Format to Aid in Security Vulnerability Disclosure) @@ -1759,7 +1919,7 @@ limitations under the License. A list of zero or more patches describing how the component - deviates from an ancestor, descendant, or variant. Patches may be complimentary to commits + deviates from an ancestor, descendant, or variant. Patches may be complementary to commits or may be used in place of commits. @@ -1782,7 +1942,26 @@ limitations under the License. - + + + The component or service that is a dependency of this dependency object. + + + + + + The component or service that define a given specification or standard, which is provided or implemented by this dependency object. + For example, a cryptographic library which implements a cryptographic algorithm. A component which implements another component does not imply that the implementation is in use. + + + + + + References a component or service by its bom-ref attribute + + + + @@ -1851,7 +2030,7 @@ limitations under the License. of the service. - + The service version. @@ -2008,6 +2187,7 @@ limitations under the License. Specifies optional release notes. + @@ -2069,7 +2249,12 @@ limitations under the License. A valid SPDX license expression. - Refer to https://spdx.org/specifications for syntax requirements + Refer to https://spdx.org/specifications for syntax requirements + + Example values: + - Apache-2.0 AND (MIT OR GPL-2.0-only) + - GPL-3.0-only WITH Classpath-exception-2.0 + @@ -2082,6 +2267,23 @@ limitations under the License. + + + + Declared licenses and concluded licenses represent two different stages in the + licensing process within software development. Declared licenses refer to the + initial intention of the software authors regarding the licensing terms under + which their code is released. On the other hand, concluded licenses are the + result of a comprehensive analysis of the project's codebase to identify and + confirm the actual licenses of the components used, which may differ from the + initially declared licenses. While declared licenses provide an upfront indication + of the licensing intentions, concluded licenses offer a more thorough understanding + of the actual licensing within a project, facilitating proper compliance and risk + management. Observed licenses are defined in `evidence.licenses`. Observed licenses + form the evidence necessary to substantiate a concluded license. + + + @@ -2089,6 +2291,26 @@ limitations under the License. + + + + + + Declared licenses represent the initial intentions of authors regarding + the licensing terms of their code. + + + + + + + Concluded licenses are verified and confirmed. + + + + + + @@ -2102,6 +2324,8 @@ limitations under the License. + + @@ -2116,24 +2340,87 @@ limitations under the License. - - - - - - - - - - + + + + Examines the source code without executing it. + + + + + + + Examines a compiled binary through reverse engineering, typically via disassembly or bytecode reversal. + + + + + + + Examines a package management system such as those used for building software or installing software. + + + + + + + Examines the Abstract Syntax Tree (AST) of source code or a compiled binary. + + + + + + + Evaluates the cryptographic hash of a component against a set of pre-computed hashes of identified software. + + + + + + + Examines the call stack of running applications by intercepting and monitoring application logic without the need to modify the application. + + + + + + + Evaluates a running application. + + + + + + + Evaluates file name of a component against a set of known file names of identified software. + + + + + + + A testimony to the accuracy of the identify of a component made by an individual or entity. + + + + + + + Any other technique. + + + - + - Evidence that substantiates the identity of a component. + Evidence that substantiates the identity of a component. The identify may be an + object or an array of identity objects. Support for specifying identity as a single object was + introduced in CycloneDX v1.5. "unbounded" was introduced in v1.6. It is RECOMMENDED that all + implementations are aware of "unbounded". @@ -2147,6 +2434,11 @@ limitations under the License. The overall confidence of the evidence from 0 - 1, where 1 is 100% confidence. + + + The value of the field (cpe, purl, etc) that has been concluded based on the aggregate of all methods (if available). + + The methods used to extract and/or analyze the evidence. @@ -2203,11 +2495,32 @@ limitations under the License. - + The location or path to where the component was found. + + + The line number where the component was found. + + + + + The offset where the component was found. + + + + + The symbol name that was found associated with the component. + + + + + Any additional context of the detected component (e.g. a code snippet). + + + @@ -2495,9 +2808,9 @@ limitations under the License. * minor = A minor release, also known as an update, may contain a smaller number of changes than major releases. * patch = Patch releases are typically unplanned and may resolve defects or important security issues. * pre-release = A pre-release may include alpha, beta, or release candidates and typically have - limited support. They provide the ability to preview a release prior to its general availability. + limited support. They provide the ability to preview a release prior to its general availability. * internal = Internal releases are not for public consumption and are intended to be used exclusively - by the project or manufacturer that produced it. + by the project or manufacturer that produced it. @@ -2532,23 +2845,13 @@ limitations under the License. One or more alternate names the release may be referred to. This may - include unofficial terms used by development and marketing teams (e.g. code names). - - - - - - - - - - - One or more tags that may aid in search or retrieval of the release note. + include unofficial terms used by development and marketing teams (e.g. code names). + A collection of issues that have been resolved. @@ -2565,7 +2868,7 @@ limitations under the License. Zero or more release notes containing the locale and content. Multiple - note elements may be specified to support release notes in a wide variety of languages. + note elements may be specified to support release notes in a wide variety of languages. @@ -2612,12 +2915,12 @@ limitations under the License. - + @@ -2930,7 +3233,7 @@ limitations under the License. - What are the ethical (or environmental) risks involved in the application of this model? + What are the ethical risks involved in the application of this model? @@ -2958,6 +3261,13 @@ limitations under the License. + + + + What are the various environmental impacts the corresponding machine learning model has exhibited across its lifecycle? + + + @@ -3019,647 +3329,658 @@ limitations under the License. - - - - - TODO - - - - - TODO - - - - - TODO - - - - - TODO - - - - - TODO - - - - - - + + + + Describes various environmental impact metrics. + + - + - The general theme or subject matter of the data being specified. + Describes energy consumption information incurred for one or more component lifecycle activities. - + - - The name of the dataset. + Provides the ability to document properties in a name/value store. + This provides flexibility to include data not officially supported in the standard + without having to use additional namespaces or create extensions. Property names + of interest to the general public are encouraged to be registered in the + CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. + Formal registration is OPTIONAL. - + + + + + + + - The contents or references to the contents of the data being described. + Allows any undeclared elements as long as the elements are placed in a different namespace. - - - - - An optional way to include textual or encoded data. - - - - - The URL to where the data can be retrieved. + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + + + + + Describes energy consumption information incurred for the specified lifecycle activity. + + + + + + + The type of activity that is part of a machine learning model development or operational lifecycle. + + + + + + + + model design including problem framing, goal definition and algorithm selection. + - - + + - Provides the ability to document name-value parameters used for configuration. + + model data acquisition including search, selection and transfer. + - - - + + + + + model data preparation including data cleaning, labeling and conversion. + + + + + + + model building, training and generalized tuning. + + + + + + + refining a trained model to produce desired outputs for a given problem space. + + + + + + + model validation including model output evaluation and testing. + + + + + + + explicit model deployment to a target hosting infrastructure. + + + + + + + generating an output response from a hosted model from a set of inputs. + + + + + + + a lifecycle activity type whose description does not match currently defined values. + + + + + - + - Data classification tags data according to its type, sensitivity, and value if altered, stolen, or destroyed. + The provider(s) of the energy consumed by the associated model development lifecycle activity. - + - A description of any sensitive data in a dataset. + The total energy cost associated with the model lifecycle activity. - + - A collection of graphics that represent various measurements. + The CO2 cost (debit) equivalent to the total energy cost. - + - A description of the dataset. Can describe size of dataset, whether it's used for source code, - training, testing, or validation, etc. + The CO2 offset (credit) for the CO2 equivalent cost. - - - - - - An optional identifier which can be used to reference the dataset elsewhere in the BOM. - Every bom-ref MUST be unique within the BOM. - - - - - - - - + - - Data custodians are responsible for the safe custody, transport, and storage of data. + Provides the ability to document properties in a name/value store. + This provides flexibility to include data not officially supported in the standard + without having to use additional namespaces or create extensions. Property names + of interest to the general public are encouraged to be registered in the + CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. + Formal registration is OPTIONAL. - - - - - - + + + + + + + A measure of energy. + + + + - Data stewards are responsible for data content, context, and associated business rules. + Quantity of energy. - - - - - - + - Data owners are concerned with risk and appropriate access to data. + Unit of energy. - - - - - + + + + + + kilowatt-hour (kWh) is the energy delivered by one kilowatt (kW) of power for one hour (h). + + + + + - - - - - - - - + - A collection of graphics that represent various measurements. + A measure of carbon dioxide (CO2). - + - A description of this collection of graphics. + Quantity of carbon dioxide (CO2). - + - A collection of graphics. + Unit of carbon dioxide (CO2). - - - - - - - - - The name of the graphic. - - - - - - - The graphic (vector or raster). Base64 encoding MUST be specified for binary images. - - - - - - - - + + + + + + Tonnes (t) of carbon dioxide (CO2) equivalent (eq). + + + + + - - - + + + + Describes the physical provider of energy used for model development or operations. + + + + - Any type of code, code snippet, or data-as-code. + + A description of the energy provider. + - - + + - Parameters or settings that may be used by other components. + + The organization of the energy provider. + - - + + - A collection of data. + + The energy source for the energy provider. + - - + + + + + + Energy produced by types of coal. + + + + + + + Petroleum products (primarily crude oil and its derivative fuel oils). + + + + + + + Hydrocarbon gas liquids (HGL) that occur as gases at atmospheric pressure and as liquids under higher pressures including Natural gas (C5H12 and heavier), Ethane (C2H6), Propane (C3H8), etc. + + + + + + + Energy produced from the cores of atoms (i.e., through nuclear fission or fusion). + + + + + + + Energy produced from moving air. + + + + + + + Energy produced from the sun (i.e., solar radiation). + + + + + + + Energy produced from heat within the earth. + + + + + + + Energy produced from flowing water. + + + + + + + Liquid fuels produced from biomass feedstocks (i.e., organic materials such as plants or animals). + + + + + + + The energy source is unknown. + + + + + + + An energy source that is not listed. + + + + + + + - Data that can be used to create new instances of what the definition defines. + + The energy provided by the energy source for an associated activity. + - - + + - Any other type of data that does not fit into existing definitions. + External references provide a way to document systems, sites, and information that may be relevant but are not included with the BOM. They may also establish specific relationships within or external to the BOM. - - - - - - - - References a component or service by its bom-ref attribute - - - - - - + + + - User-defined attributes may be used on this element as long as they - do not have the same name as an existing attribute used by the schema. + + An optional identifier which can be used to reference the energy provider elsewhere in the BOM. + Uniqueness is enforced within all elements and children of the root-level bom element. + - + - - - - + + + + An address used to identify a contactable location. + + + + - Allows any undeclared elements as long as the elements are placed in a different namespace. + The country name or the two-letter ISO 3166-1 country code. - - - - - User-defined attributes may be used on this element as long as they - do not have the same name as an existing attribute used by the schema. - - - - - - - Specifies an individual property with a name and value. - - - - - - The name of the property. Duplicate names are allowed, each potentially having a different value. - - - - - - - - - + + - Defines a weakness in a component or service that could be exploited or triggered by a threat source. + + The region or state in the country. For example, Texas. + - + - Allows any undeclared elements as long as the elements are placed in a different namespace. + The locality or city within the country. For example, Austin. - + + + + + The post office box number. For example, 901. + + + + + + + The postal code. For example, 78758. + + + + + + + The street address. For example, 100 Main Street. + + + - + - User-defined attributes may be used on this element as long as they - do not have the same name as an existing attribute used by the schema. + + An optional identifier which can be used to reference the address elsewhere in the BOM. + Uniqueness is enforced within all elements and children of the root-level bom element. + - + - - - + + + - The identifier that uniquely identifies the vulnerability. For example: - CVE-2021-39182, GHSA-35m5-8cvj-8783, and SNYK-PYTHON-ENROCRYPT-1912876. + + Supervised machine learning involves training an algorithm on labeled + data to predict or classify new data based on the patterns learned from + the labeled examples. + - - + + - The source that published the vulnerability. + + Unsupervised machine learning involves training algorithms on unlabeled + data to discover patterns, structures, or relationships without explicit + guidance, allowing the model to identify inherent structures or clusters + within the data. + - - + + - Zero or more pointers to vulnerabilities that are the equivalent of the - vulnerability specified. Often times, the same vulnerability may exist in multiple sources of - vulnerability intelligence, but have different identifiers. References provide a way to - correlate vulnerabilities across multiple sources of vulnerability intelligence. + + Reinforcement learning is a type of machine learning where an agent learns + to make decisions by interacting with an environment to maximize cumulative + rewards, through trial and error. + - - - - - A pointer to a vulnerability that is the equivalent of the - vulnerability specified. - - - - - - The identifier that uniquely identifies the vulnerability. For example: - CVE-2021-39182, GHSA-35m5-8cvj-8783, and SNYK-PYTHON-ENROCRYPT-1912876. - - - - - The source that published the vulnerability. - - - - - - - - - Allows any undeclared elements as long as the elements are placed in a different namespace. - - - - - - - + + - List of vulnerability ratings. + + Semi-supervised machine learning utilizes a combination of labeled and + unlabeled data during training to improve model performance, leveraging + the benefits of both supervised and unsupervised learning techniques. + - - - - - - - - - - - List of Common Weaknesses Enumerations (CWEs) codes that describes this vulnerability. - For example 399 (of https://cwe.mitre.org/data/definitions/399.html) - - - - - - - - + + - A description of the vulnerability as provided by the source. + + Self-supervised machine learning involves training models to predict parts + of the input data from other parts of the same data, without requiring + external labels, enabling learning from large amounts of unlabeled data. + - - + + + + + + + - If available, an in-depth description of the vulnerability as provided by the - source organization. Details often include information useful in understanding root cause. + + The general theme or subject matter of the data being specified. + - + - Recommendations of how the vulnerability can be remediated or mitigated. + + The name of the dataset. + - + - A bypass, usually temporary, of the vulnerability that reduces its likelihood and/or impact. Workarounds often involve changes to configuration or deployments. + + The contents or references to the contents of the data being described. + - - - - - Evidence used to reproduce the vulnerability. - - - + - Precise steps to reproduce the vulnerability. + An optional way to include textual or encoded data. - + - A description of the environment in which reproduction was possible. + The URL to where the data can be retrieved. - + - Supporting material that helps in reproducing or understanding how reproduction is possible. This may include screenshots, payloads, and PoC exploit code. + Provides the ability to document name-value parameters used for configuration. - - - - - - - - - - Published advisories of the vulnerability if provided. - - - - - - - - + - The date and time (timestamp) when the vulnerability record was created in the vulnerability database. + + Data classification tags data according to its type, sensitivity, and value if altered, stolen, or destroyed. + - + - The date and time (timestamp) when the vulnerability record was first published. + + A description of any sensitive data in a dataset. + - + - The date and time (timestamp) when the vulnerability record was last updated. - - - + + A collection of graphics that represent various measurements. + + + + - The date and time (timestamp) when the vulnerability record was rejected (if applicable). + + A description of the dataset. Can describe size of dataset, whether it's used for source code, + training, testing, or validation, etc. + - + + + + + + An optional identifier which can be used to reference the dataset elsewhere in the BOM. + Every bom-ref MUST be unique within the BOM. + + + + + + + + - Individuals or organizations credited with the discovery of the vulnerability. + + Data custodians are responsible for the safe custody, transport, and storage of data. + - - - The organizations credited with vulnerability discovery. - - - - - - - - - - The individuals, not associated with organizations, that are credited with vulnerability discovery. - - - - - - - + - + - The tool(s) used to identify, confirm, or score the vulnerability. + + Data stewards are responsible for data content, context, and associated business rules. + - - - - - DEPRECATED. Use tools\components or tools\services instead. - - - - - - - A list of software and hardware components used as tools. - - - - - A list of services used as tools. - - - - + + + - + + + + Data owners are concerned with risk and appropriate access to data. + + - - - An assessment of the impact and exploitability of the vulnerability. - - - - - - - Declares the current state of an occurrence of a vulnerability, after automated or manual analysis. - - - - - - - The rationale of why the impact analysis state was asserted. - - - - - - A response to the vulnerability by the manufacturer, supplier, or - project responsible for the affected component or service. More than one response - is allowed. Responses are strongly encouraged for vulnerabilities where the analysis - state is exploitable. - - - - - - - - - - - Detailed description of the impact including methods used during assessment. - If a vulnerability is not exploitable, this field should include specific details - on why the component or service is not impacted by this vulnerability. - - - - - - - The date and time (timestamp) when the analysis was first issued. - - - - - - - The date and time (timestamp) when the analysis was last updated. - - - + + - + + + + + + + + + + + + + + A collection of graphics that represent various measurements. + + + + - The components or services that are affected by the vulnerability. + + A description of this collection of graphics. + + + + + + + A collection of graphics. + - - + + - - + + - References a component or service by the objects bom-ref. + + The name of the graphic. + - - - - + - Zero or more individual versions or range of versions. + + The graphic (vector or raster). Base64 encoding MUST be specified for binary images. + - - - - - - - - - A single version of a component or service. - - - - - A version range specified in Package URL Version Range syntax (vers) which is defined at https://github.com/package-url/purl-spec/VERSION-RANGE-SPEC.rst - - - - - - - The vulnerability status for the version or range of versions. - - - - - - - - @@ -3667,98 +3988,59 @@ limitations under the License. - - - Provides the ability to document properties in a name/value store. - This provides flexibility to include data not officially supported in the standard - without having to use additional namespaces or create extensions. Property names - of interest to the general public are encouraged to be registered in the - CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. - Formal registration is OPTIONAL. - - - - - - An optional identifier which can be used to reference the vulnerability elsewhere in the BOM. - Uniqueness is enforced within all elements and children of the root-level bom element. - - - - - - + + + - The name of the source. - For example: NVD, National Vulnerability Database, OSS Index, VulnDB, and GitHub Advisories - + Any type of code, code snippet, or data-as-code. - - - - The url of the vulnerability documentation as provided by the source. - For example: https://nvd.nist.gov/vuln/detail/CVE-2021-39182 - - - - - - - - - - The source that calculated the severity or risk rating of the vulnerability. - - - - - The numerical score of the rating. - - - + + - Textual representation of the severity that corresponds to the numerical score of the rating. + Parameters or settings that may be used by other components. - - + + - The risk scoring methodology/standard used. + A collection of data. - - + + - Textual representation of the metric values used to score the vulnerability. + Data that can be used to create new instances of what the definition defines. - - + + - An optional reason for rating the vulnerability as it was. + Any other type of data that does not fit into existing definitions. - - - + + + - - - - - An optional name of the advisory. - - - - - Location where the advisory can be obtained. - - - + + + + References a component or service by its bom-ref attribute + + + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + - + - + @@ -3775,42 +4057,87 @@ limitations under the License. - - - + + + Specifies an individual property with a name and value. + + + + + + The name of the property. Duplicate names are allowed, each potentially having a different value. + + + + + + + + + - The organization that created the annotation + Defines a weakness in a component or service that could be exploited or triggered by a threat source. - + - The person that created the annotation + + Allows any undeclared elements as long as the elements are placed in a different namespace. + - - + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + + + + - The tool or component that created the annotation + The identifier that uniquely identifies the vulnerability. For example: + CVE-2021-39182, GHSA-35m5-8cvj-8783, and SNYK-PYTHON-ENROCRYPT-1912876. - + - The service that created the annotation + The source that published the vulnerability. - - - - - - + - - The objects in the BOM identified by their bom-ref's. This is often components or services, but may be any object type supporting bom-refs. - + Zero or more pointers to vulnerabilities that are the equivalent of the + vulnerability specified. Often times, the same vulnerability may exist in multiple sources of + vulnerability intelligence, but have different identifiers. References provide a way to + correlate vulnerabilities across multiple sources of vulnerability intelligence. - + + + A pointer to a vulnerability that is the equivalent of the + vulnerability specified. + + + + + + The identifier that uniquely identifies the vulnerability. For example: + CVE-2021-39182, GHSA-35m5-8cvj-8783, and SNYK-PYTHON-ENROCRYPT-1912876. + + + + + The source that published the vulnerability. + + + + + @@ -3821,370 +4148,380 @@ limitations under the License. - + - The organization, individual, component, or service which created the textual content - of the annotation. + List of vulnerability ratings. + + + + + - + + + + + List of Common Weaknesses Enumerations (CWEs) codes that describes this vulnerability. + For example 399 (of https://cwe.mitre.org/data/definitions/399.html) + + + + + + + + - The date and time (timestamp) when the annotation was created. + A description of the vulnerability as provided by the source. - + - The textual content of the annotation. + If available, an in-depth description of the vulnerability as provided by the + source organization. Details often include information useful in understanding root cause. - + - - Allows any undeclared elements as long as the elements are placed in a different namespace. - + Recommendations of how the vulnerability can be remediated or mitigated. - - - - - - An optional identifier which can be used to reference the annotation elsewhere in the BOM. - Uniqueness is enforced within all elements and children of the root-level bom element. - - - - - - User-defined attributes may be used on this element as long as they - do not have the same name as an existing attribute used by the schema. - - - - - - - - Textual representation of the severity of the vulnerability adopted by the analysis method. If the - analysis method uses values other than what is provided, the user is expected to translate appropriately. - - - - - - - - - - - - - - - - - Declares the current state of an occurrence of a vulnerability, after automated or manual analysis. - - - - + + - - The vulnerability has been remediated. - + A bypass, usually temporary, of the vulnerability that reduces its likelihood and/or impact. Workarounds often involve changes to configuration or deployments. - - - - - The vulnerability has been remediated and evidence of the changes are provided in the affected - components pedigree containing verifiable commit history and/or diff(s). - - - - - - - The vulnerability may be directly or indirectly exploitable. - - - - - - - The vulnerability is being investigated. - - - - - - - The vulnerability is not specific to the component or service and was falsely identified or associated. - - - - - - - The component or service is not affected by the vulnerability. Justification should be specified - for all not_affected cases. - - - - - - - - - - The rationale of why the impact analysis state was asserted. - - - - + + + + + + Evidence used to reproduce the vulnerability. + + + + + + Precise steps to reproduce the vulnerability. + + + + + A description of the environment in which reproduction was possible. + + + + + Supporting material that helps in reproducing or understanding how reproduction is possible. This may include screenshots, payloads, and PoC exploit code. + + + + + + + + + + + + + + + Published advisories of the vulnerability if provided. + + + + + + + + - - The code has been removed or tree-shaked. - + The date and time (timestamp) when the vulnerability record was created in the vulnerability database. - - + + - - The vulnerable code is not invoked at runtime. - + The date and time (timestamp) when the vulnerability record was first published. - - + + - - Exploitability requires a configurable option to be set/unset. - + The date and time (timestamp) when the vulnerability record was last updated. - - + + - - Exploitability requires a dependency that is not present. - + The date and time (timestamp) when the vulnerability record was rejected (if applicable). - - + + - - Exploitability requires a certain environment which is not present. - + Individuals or organizations credited with the discovery of the vulnerability. - - + + + + + The organizations credited with vulnerability discovery. + + + + + + + + + + The individuals, not associated with organizations, that are credited with vulnerability discovery. + + + + + + + + + + + - - Exploitability requires a compiler flag to be set/unset. - + The tool(s) used to identify, confirm, or score the vulnerability. - - + + + + + + DEPRECATED. Use tools\components or tools\services instead. + + + + + + + A list of software and hardware components used as tools. + + + + + A list of services used as tools. + + + + + + + + + + + An assessment of the impact and exploitability of the vulnerability. + + + + + + + Declares the current state of an occurrence of a vulnerability, after automated or manual analysis. + + + + + + + The rationale of why the impact analysis state was asserted. + + + + + + A response to the vulnerability by the manufacturer, supplier, or + project responsible for the affected component or service. More than one response + is allowed. Responses are strongly encouraged for vulnerabilities where the analysis + state is exploitable. + + + + + + + + + + + Detailed description of the impact including methods used during assessment. + If a vulnerability is not exploitable, this field should include specific details + on why the component or service is not impacted by this vulnerability. + + + + + + + The date and time (timestamp) when the analysis was first issued. + + + + + + + The date and time (timestamp) when the analysis was last updated. + + + + + + + - - Exploits are prevented at runtime. - + The components or services that are affected by the vulnerability. - - - - - Attacks are blocked at physical, logical, or network perimeter. - - - - + + + + + + + + References a component or service by the objects bom-ref. + + + + + + + + Zero or more individual versions or range of versions. + + + + + + + + + + A single version of a component or service. + + + + + A version range specified in Package URL Version Range syntax (vers) which is defined at https://github.com/package-url/purl-spec/VERSION-RANGE-SPEC.rst + + + + + + + The vulnerability status for the version or range of versions. + + + + + + + + + + + + + + + + - - Preventative measures have been implemented that reduce the likelihood and/or impact of the vulnerability. - + Provides the ability to document properties in a name/value store. + This provides flexibility to include data not officially supported in the standard + without having to use additional namespaces or create extensions. Property names + of interest to the general public are encouraged to be registered in the + CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. + Formal registration is OPTIONAL. - - - + + + + + + An optional identifier which can be used to reference the vulnerability elsewhere in the BOM. + Uniqueness is enforced within all elements and children of the root-level bom element. + + + + - - - - Specifies the severity or risk scoring methodology or standard used. - - - - + + + - - The rating is based on CVSS v2 standard - https://www.first.org/cvss/v2/ + The name of the source. + For example: NVD, National Vulnerability Database, OSS Index, VulnDB, and GitHub Advisories - - + + - - The rating is based on CVSS v3.0 standard - https://www.first.org/cvss/v3-0/ - + The url of the vulnerability documentation as provided by the source. + For example: https://nvd.nist.gov/vuln/detail/CVE-2021-39182 - - + + + + + + + - - The rating is based on CVSS v3.1 standard - https://www.first.org/cvss/v3-1/ - + The source that calculated the severity or risk rating of the vulnerability. - - + + - - The rating is based on CVSS v4.0 standard - https://www.first.org/cvss/v4-0/ - + The numerical score of the rating. - - + + - - The rating is based on OWASP Risk Rating - https://owasp.org/www-community/OWASP_Risk_Rating_Methodology - + Textual representation of the severity that corresponds to the numerical score of the rating. - - + + - - The rating is based on Stakeholder Specific Vulnerability Categorization (all versions) - https://github.com/CERTCC/SSVC - + The risk scoring methodology/standard used. - - + + - - Use this if the risk scoring methodology is not based on any of the options above - + Textual representation of the metric values used to score the vulnerability. - - - - - - - - The rationale of why the impact analysis state was asserted. - - - - - - - - - - - - - - - The vulnerability status of a given version or range of versions of a product. The statuses - 'affected' and 'unaffected' indicate that the version is affected or unaffected by the vulnerability. - The status 'unknown' indicates that it is unknown or unspecified whether the given version is affected. - There can be many reasons for an 'unknown' status, including that an investigation has not been - undertaken or that a vendor has not disclosed the status. - - - - - - - - - - - - - Describes how a component or service was manufactured or deployed. This is achieved through the use - of formulas, workflows, tasks, and steps, which declare the precise steps to reproduce along with the - observed formulas describing the steps which transpired in the manufacturing process. - - - - - + + - - Allows any undeclared elements as long as the elements are placed in a different namespace. - + An optional reason for rating the vulnerability as it was. - + - - - User-defined attributes may be used on this element as long as they - do not have the same name as an existing attribute used by the schema. - - - - - - Describes workflows and resources that captures rules and other aspects of how the associated - BOM component or service was formed. - - + - - - Transient components that are used in tasks that constitute one or more of - this formula's workflows - - - - - Transient services that are used in tasks that constitute one or more of - this formula's workflows - - - + - List of workflows that can be declared to accomplish specific orchestrated goals - and independently triggered. + An optional name of the advisory. - + - Provides the ability to document properties in a name/value store. - This provides flexibility to include data not officially supported in the standard - without having to use additional namespaces or create extensions. Property names - of interest to the general public are encouraged to be registered in the - CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. - Formal registration is OPTIONAL. + Location where the advisory can be obtained. - - - - An optional identifier which can be used to reference the formula elsewhere in the BOM. - Uniqueness is enforced within all elements and children of the root-level bom element. - - - - - - User-defined attributes may be used on this element as long as they - do not have the same name as an existing attribute used by the schema. - - - - - + + + @@ -4201,129 +4538,66 @@ limitations under the License. - - - - - - The unique identifier for the resource instance within its deployment context. - - - - - - - The name of the resource instance. - - - - - - - The description of the resource instance. - - - - - - References to component or service resources that are used to realize - the resource instance. - - - + + + - The tasks that comprise the workflow. + The organization that created the annotation - + - The graph of dependencies between tasks within the workflow. + The person that created the annotation - + - Indicates the types of activities performed by the set of workflow tasks. + The tool or component that created the annotation - - - - - - + - The trigger that initiated the task. + The service that created the annotation - + + + + + + - The sequence of steps for the task. + The objects in the BOM identified by their bom-ref's. This is often components or services, but may be any object type supporting bom-refs. - - - - - - - - Represents resources and data brought into a task at runtime by executor - or task commands - - - - - - - - - - Represents resources and data output from a task at runtime by executor - or task commands - - - - + + + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + - - - - The date and time (timestamp) when the task started. - - - - - - - The date and time (timestamp) when the task ended. - - - - + - A set of named filesystem or data resource shareable by workflow tasks. + The organization, individual, component, or service which created the textual content + of the annotation. - + - A graph of the component runtime topology for workflow's instance. - A description of the runtime component and service topology. This can describe a partial or - complete topology used to host and execute the task (e.g., hardware, operating systems, - configurations, etc.) + The date and time (timestamp) when the annotation was created. - + - Provides the ability to document properties in a name/value store. - This provides flexibility to include data not officially supported in the standard - without having to use additional namespaces or create extensions. Property names - of interest to the general public are encouraged to be registered in the - CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. - Formal registration is OPTIONAL. + The textual content of the annotation. @@ -4334,10 +4608,10 @@ limitations under the License. - + - An optional identifier which can be used to reference the workflow elsewhere in the BOM. + An optional identifier which can be used to reference the annotation elsewhere in the BOM. Uniqueness is enforced within all elements and children of the root-level bom element. @@ -4350,193 +4624,293 @@ limitations under the License. - - - - - - - Allows any undeclared elements as long as the elements are placed in a different namespace. - - - - - - - User-defined attributes may be used on this element as long as they - do not have the same name as an existing attribute used by the schema. - - - + + + + Textual representation of the severity of the vulnerability adopted by the analysis method. If the + analysis method uses values other than what is provided, the user is expected to translate appropriately. + + + + + + + + + + + + - - - - - - - References an object by its bom-ref attribute - - - - - - - - - - Reference to an externally accessible resource. - - - - - + + + + Declares the current state of an occurrence of a vulnerability, after automated or manual analysis. + + + + - Allows any undeclared elements as long as the elements are placed in a different namespace. + The vulnerability has been remediated. - - - - - User-defined attributes may be used on this element as long as they - do not have the same name as an existing attribute used by the schema. - - - - - - - - + + - Allows any undeclared elements as long as the elements are placed in a different namespace. + The vulnerability has been remediated and evidence of the changes are provided in the affected + components pedigree containing verifiable commit history and/or diff(s). - - - - - User-defined attributes may be used on this element as long as they - do not have the same name as an existing attribute used by the schema. - - - - - - - + + - The unique identifier for the resource instance within its deployment context. + The vulnerability may be directly or indirectly exploitable. - - + + - The name of the resource instance. + The vulnerability is being investigated. - - + + - The description of the resource instance. + The vulnerability is not specific to the component or service and was falsely identified or associated. - - + + - References to component or service resources that are used to realize the resource instance. + The component or service is not affected by the vulnerability. Justification should be specified + for all not_affected cases. - - + + + + + + + + The rationale of why the impact analysis state was asserted. + + + + - Indicates the types of activities performed by the set of workflow tasks. + The code has been removed or tree-shaked. - - - - - - - + + - The trigger that initiated the task. + The vulnerable code is not invoked at runtime. - - + + - The sequence of steps for the task. + Exploitability requires a configurable option to be set/unset. - - - - - - - + + - Represents resources and data brought into a task at runtime by executor or task commands. + Exploitability requires a dependency that is not present. - - - - - - - + + - Represents resources and data output from a task at runtime by executor or task commands + Exploitability requires a certain environment which is not present. - - - - - - - + + - The date and time (timestamp) when the task started. + Exploitability requires a compiler flag to be set/unset. - - + + - The date and time (timestamp) when the task ended. + Exploits are prevented at runtime. - - + + - A set of named filesystem or data resource shareable by workflow tasks. + Attacks are blocked at physical, logical, or network perimeter. - - + + - A graph of the component runtime topology for task's instance. + Preventative measures have been implemented that reduce the likelihood and/or impact of the vulnerability. + + + + + + + + + + Specifies the severity or risk scoring methodology or standard used. + + + + + + + Common Vulnerability Scoring System v2.0 standard as defined at https://www.first.org/cvss/v2/ + + + + + + + Common Vulnerability Scoring System v3.0 standard as defined at https://www.first.org/cvss/v3-0/ + + + + + + + Common Vulnerability Scoring System v3.1 standard as defined at https://www.first.org/cvss/v3-1/ + + + + + + + Common Vulnerability Scoring System v4.0 standard as defined at https://www.first.org/cvss/v4-0/ + + + + + + + OWASP Risk Rating as defined at https://owasp.org/www-community/OWASP_Risk_Rating_Methodology + + + + + + + Stakeholder Specific Vulnerability Categorization as defined at https://github.com/CERTCC/SSVC + + + + + + + Another severity or risk scoring methodology + + + + + + + + + + The rationale of why the impact analysis state was asserted. + + + + + + + + + + + + + + + The vulnerability status of a given version or range of versions of a product. The statuses + 'affected' and 'unaffected' indicate that the version is affected or unaffected by the vulnerability. + The status 'unknown' indicates that it is unknown or unspecified whether the given version is affected. + There can be many reasons for an 'unknown' status, including that an investigation has not been + undertaken or that a vendor has not disclosed the status. + + + + + + + + + + + + + Describes how a component or service was manufactured or deployed. This is achieved through the use + of formulas, workflows, tasks, and steps, which declare the precise steps to reproduce along with the + observed formulas describing the steps which transpired in the manufacturing process. + + + + + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + + + + + Describes workflows and resources that captures rules and other aspects of how the associated + BOM component or service was formed. + + + + + + Transient components that are used in tasks that constitute one or more of + this formula's workflows + + + + + Transient services that are used in tasks that constitute one or more of + this formula's workflows + + + + + List of workflows that can be declared to accomplish specific orchestrated goals + and independently triggered. + @@ -4548,18 +4922,11 @@ limitations under the License. Formal registration is OPTIONAL. - - - - Allows any undeclared elements as long as the elements are placed in a different namespace. - - - - + - An optional identifier which can be used to reference the task elsewhere in the BOM. + An optional identifier which can be used to reference the formula elsewhere in the BOM. Uniqueness is enforced within all elements and children of the root-level bom element. @@ -4572,26 +4939,9 @@ limitations under the License. - - - - - - - - - - - - - - - - - - + - + @@ -4608,13 +4958,8 @@ limitations under the License. - - - - A named filesystem or data resource shareable by workflow tasks. - - - + + @@ -4629,68 +4974,103 @@ limitations under the License. - + - The names for the workspace as referenced by other workflow tasks. Effectively, a name mapping - so other tasks can use their own local name in their steps. + The description of the resource instance. + + + + References to component or service resources that are used to realize + the resource instance. + + + + + The tasks that comprise the workflow. + + + + + The graph of dependencies between tasks within the workflow. + + + + + Indicates the types of activities performed by the set of workflow tasks. + - + - + - - The description of the resource instance. - + The trigger that initiated the task. - + - References to component or service resources that are used to realize the resource instance. + The sequence of steps for the task. + + + + + - + - - Describes the read-write access control for the workspace relative to the owning resource instance. - + Represents resources and data brought into a task at runtime by executor + or task commands + + + + + - + - - A path to a location on disk where the workspace will be available to the associated task's steps. - + Represents resources and data output from a task at runtime by executor + or task commands + + + + + - + - The name of a domain-specific data type the workspace represents. This property is for CI/CD - frameworks that are able to provide access to structured, managed data at a more granular level - than a filesystem. + The date and time (timestamp) when the task started. - + - Identifies the reference to the request for a specific volume type and parameters. + The date and time (timestamp) when the task ended. - + - - Information about the actual volume instance allocated to the workspace. - + A set of named filesystem or data resource shareable by workflow tasks. + + + + + A graph of the component runtime topology for workflow's instance. + A description of the runtime component and service topology. This can describe a partial or + complete topology used to host and execute the task (e.g., hardware, operating systems, + configurations, etc.) @@ -4727,387 +5107,2781 @@ limitations under the License. - - - - - - - - - + + + + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + - - - - An identifiable, logical unit of data storage tied to a physical device. - - + - + + + + + References an object by its bom-ref attribute + + + + + + + + + + Reference to an externally accessible resource. + + + + + - The unique identifier for the volume instance within its deployment context. + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + + + + + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + + + + + + + The unique identifier for the resource instance within its deployment context. - The name of the volume instance + The name of the resource instance. - + - The mode for the volume instance. + The description of the resource instance. + + + + + + + References to component or service resources that are used to realize the resource instance. + + + + + + + Indicates the types of activities performed by the set of workflow tasks. + + + + + + + + + + + + The trigger that initiated the task. + + + + + + + The sequence of steps for the task. + + + + + + + + + + + + Represents resources and data brought into a task at runtime by executor or task commands. + + + + + + + + + + + + Represents resources and data output from a task at runtime by executor or task commands + + + + + + + + + + + + The date and time (timestamp) when the task started. - + + + + The date and time (timestamp) when the task ended. + + + + + + + A set of named filesystem or data resource shareable by workflow tasks. + + + + + + + A graph of the component runtime topology for task's instance. + + + + + + Provides the ability to document properties in a name/value store. + This provides flexibility to include data not officially supported in the standard + without having to use additional namespaces or create extensions. Property names + of interest to the general public are encouraged to be registered in the + CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. + Formal registration is OPTIONAL. + + + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + + + + + + An optional identifier which can be used to reference the task elsewhere in the BOM. + Uniqueness is enforced within all elements and children of the root-level bom element. + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + + + + + + A task that copies software or data used to accomplish other tasks in the workflow. + + + + + A task that clones a software repository into the workflow in order to retrieve its source code or data for use in a build step. + + + + + A task that checks source code for programmatic and stylistic errors. + + + + + A task that performs a scan against source code, or built or deployed components and services. Scans are typically run to gather or test for security vulnerabilities or policy compliance. + + + + + A task that merges changes or fixes into source code prior to a build step in the workflow. + + + + + A task that builds the source code, dependencies and/or data into an artifact that can be deployed to and executed on target systems. + + + + + A task that verifies the functionality of a component or service. + + + + + A task that delivers a built artifact to one or more target repositories or storage systems. + + + + + A task that deploys a built artifact for execution on one or more target systems. + + + + + A task that releases a built, versioned artifact to a target repository or distribution system. + + + + + A task that cleans unnecessary tools, build artifacts and/or data from workflow storage. + + + + + A workflow task that does not match current task type definitions. + + + + + + + + + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + + + + + A named filesystem or data resource shareable by workflow tasks. + + + + + + + The unique identifier for the resource instance within its deployment context. + + + + + + + The name of the resource instance. + + + + + + + The names for the workspace as referenced by other workflow tasks. Effectively, a name mapping + so other tasks can use their own local name in their steps. + + + + + + + + + + + + The description of the resource instance. + + + + + + + References to component or service resources that are used to realize the resource instance. + + + + + + + Describes the read-write access control for the workspace relative to the owning resource instance. + + + + + + + A path to a location on disk where the workspace will be available to the associated task's steps. + + + + + + + The name of a domain-specific data type the workspace represents. This property is for CI/CD + frameworks that are able to provide access to structured, managed data at a more granular level + than a filesystem. + + + + + + + Identifies the reference to the request for a specific volume type and parameters. + + + + + + + Information about the actual volume instance allocated to the workspace. + + + + + + Provides the ability to document properties in a name/value store. + This provides flexibility to include data not officially supported in the standard + without having to use additional namespaces or create extensions. Property names + of interest to the general public are encouraged to be registered in the + CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. + Formal registration is OPTIONAL. + + + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + + + + + + An optional identifier which can be used to reference the workflow elsewhere in the BOM. + Uniqueness is enforced within all elements and children of the root-level bom element. + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + + + + + + + + + + + + + + + An identifiable, logical unit of data storage tied to a physical device. + + + + + + + The unique identifier for the volume instance within its deployment context. + + + + + + + The name of the volume instance + + + + + + + The mode for the volume instance. + + + + + + + The underlying path created from the actual volume. + + + + + + + The allocated size of the volume accessible to the associated workspace. This should include + the scalar size as well as IEC standard unit in either decimal or binary form. + + + + + + + Indicates if the volume persists beyond the life of the resource it is associated with. + + + + + + + Indicates if the volume is remotely (i.e., network) attached. + + + + + + Provides the ability to document properties in a name/value store. + This provides flexibility to include data not officially supported in the standard + without having to use additional namespaces or create extensions. Property names + of interest to the general public are encouraged to be registered in the + CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. + Formal registration is OPTIONAL. + + + + + + + + + + + + + + + + Executes specific commands or tools in order to accomplish its owning task as part of a sequence. + + + + + + + A name for the step. + + + + + + + A description of the step. + + + + + + + Ordered list of commands or directives for the step + + + + + + + + + + + A text representation of the executed command. + + + + + + Provides the ability to document properties in a name/value store. + This provides flexibility to include data not officially supported in the standard + without having to use additional namespaces or create extensions. Property names + of interest to the general public are encouraged to be registered in the + CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. + Formal registration is OPTIONAL. + + + + + + + + + + + Provides the ability to document properties in a name/value store. + This provides flexibility to include data not officially supported in the standard + without having to use additional namespaces or create extensions. Property names + of interest to the general public are encouraged to be registered in the + CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. + Formal registration is OPTIONAL. + + + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + + + + + + + The unique identifier for the resource instance within its deployment context. + + + + + + + The name of the resource instance. + + + + + + + The description of the resource instance. + + + + + + + References to component or service resources that are used to realize the resource instance. + + + + + + + The source type of event which caused the trigger to fire. + + + + + + + The event data that caused the associated trigger to activate. + + + + + + + + + + A condition that was used to determine a trigger should be activated. + + + + + + + + Describes the set of conditions which cause the trigger to activate. + + + + + + + The logical expression that was evaluated that determined the trigger should be fired. + + + + + + Provides the ability to document properties in a name/value store. + This provides flexibility to include data not officially supported in the standard + without having to use additional namespaces or create extensions. Property names + of interest to the general public are encouraged to be registered in the + CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. + Formal registration is OPTIONAL. + + + + + + + + + + + + The date and time (timestamp) when the trigger was activated. + + + + + + + Represents resources and data brought into a task at runtime by executor or task commands + + + + + + + + + + + + Represents resources and data output from a task at runtime by executor or task commands + + + + + + + + + + + Provides the ability to document properties in a name/value store. + This provides flexibility to include data not officially supported in the standard + without having to use additional namespaces or create extensions. Property names + of interest to the general public are encouraged to be registered in the + CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. + Formal registration is OPTIONAL. + + + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + + + + + + An optional identifier which can be used to reference the trigger elsewhere in the BOM. + Uniqueness is enforced within all elements and children of the root-level bom element. + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + + + + + + + + + + + + + + + + The unique identifier of the event. + + + + + + + A description of the event. + + + + + + + The date and time (timestamp) when the event was received. + + + + + + + Encoding of the raw event data. + + + + + + + References the component or service that was the source of the event + + + + + + + References the component or service that was the target of the event + + + + + + Provides the ability to document properties in a name/value store. + This provides flexibility to include data not officially supported in the standard + without having to use additional namespaces or create extensions. Property names + of interest to the general public are encouraged to be registered in the + CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. + Formal registration is OPTIONAL. + + + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + + + + + Type that represents various input data types and formats. + + + + + + + + A reference to an independent resource provided as an input to a task by the workflow runtime. + + + + + + + Inputs that have the form of parameters with names and values. + + + + + + + Inputs that have the form of parameters with names and values. + + + + + + + + + + + + + + + + Inputs that have the form of data. + + + + + + + + A references to the component or service that provided the input to the task + (e.g., reference to a service with data flow value of inbound) + + + + + + + A reference to the component or service that received or stored the input if not the task + itself (e.g., a local, named storage workspace) + + + + + + Provides the ability to document properties in a name/value store. + This provides flexibility to include data not officially supported in the standard + without having to use additional namespaces or create extensions. Property names + of interest to the general public are encouraged to be registered in the + CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. + Formal registration is OPTIONAL. + + + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + + + + + Represents resources and data output from a task at runtime by executor or task commands + + + + + + + + A reference to an independent resource generated as output by the task. + + + + + + + Outputs that have the form of environment variables. + + + + + + + + + + + + + + + + Outputs that have the form of data. + + + + + + + + Describes the type of data output. + + + + + + + Component or service that generated or provided the output from the task (e.g., a build tool) + + + + + + + Component or service that received the output from the task + (e.g., reference to an artifactory service with data flow value of outbound) + + + + + + Provides the ability to document properties in a name/value store. + This provides flexibility to include data not officially supported in the standard + without having to use additional namespaces or create extensions. Property names + of interest to the general public are encouraged to be registered in the + CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. + Formal registration is OPTIONAL. + + + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + + + + + + + + + + + + + + + + + + + + + + A representation of a functional parameter. + + + + + + + The name of the parameter. + + + + + + + The value of the parameter. + + + + + + + The data type of the parameter. + + + + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + + + + + Cryptographic assets have properties that uniquely define them and that make them actionable for + further reasoning. As an example, it makes a difference if one knows the algorithm family (e.g. AES) + or the specific variant or instantiation (e.g. AES-128-GCM). This is because the security level and the + algorithm primitive (authenticated encryption) is only defined by the definition of the algorithm variant. + The presence of a weak cryptographic algorithm like SHA1 vs. HMAC-SHA1 also makes a difference. + + + + + + + Cryptographic assets occur in several forms. Algorithms and protocols are most commonly + implemented in specialized cryptographic libraries. They may however also be 'hardcoded' + in software components. Certificates and related cryptographic material like keys, tokens, + secrets or passwords are other cryptographic assets to be modelled. + + + + + + + + Mathematical function commonly used for data encryption, authentication, and + digital signatures. + + + + + + + An electronic document that is used to provide the identity or validate a public key. + + + + + + + A set of rules and guidelines that govern the behavior and communication with each other. + + + + + + + Other cryptographic assets that are related to algorithms, certificate, and protocols + such as keys and tokens. + + + + + + + + + + Additional properties specific to a cryptographic algorithm. + + + + + + + + Cryptographic building blocks used in higher-level cryptographic systems and + protocols. Primitives represent different cryptographic routines: deterministic + random bit generators (drbg, e.g. CTR_DRBG from NIST SP800-90A-r1), message + authentication codes (mac, e.g. HMAC-SHA-256), blockciphers (e.g. AES), + streamciphers (e.g. Salsa20), signatures (e.g. ECDSA), hash functions (e.g. SHA-256), + public-key encryption schemes (pke, e.g. RSA), extended output functions + (xof, e.g. SHAKE256), key derivation functions (e.g. pbkdf2), key agreement + algorithms (e.g. ECDH), key encapsulation mechanisms (e.g. ML-KEM), authenticated + encryption (ae, e.g. AES-GCM) and the combination of multiple algorithms + (combiner, e.g. SP800-56Cr2). + + + + + + + + Deterministic Random Bit Generator (DRBG) is a type of pseudorandom + number generator designed to produce a sequence of bits from an initial + seed value. DRBGs are commonly used in cryptographic applications where + reproducibility of random values is important. + + + + + + + In cryptography, a Message Authentication Code (MAC) is information + used for authenticating and integrity-checking a message. + + + + + + + A block cipher is a symmetric key algorithm that operates on fixed-size + blocks of data. It encrypts or decrypts the data in block units, + providing confidentiality. Block ciphers are widely used in various + cryptographic modes and protocols for secure data transmission. + + + + + + + A stream cipher is a symmetric key cipher where plaintext digits are + combined with a pseudorandom cipher digit stream (keystream). + + + + + + + In cryptography, a signature is a digital representation of a message + or data that proves its origin, identity, and integrity. Digital + signatures are generated using cryptographic algorithms and are widely + used for authentication and verification in secure communication. + + + + + + + A hash function is a mathematical algorithm that takes an input + (or 'message') and produces a fixed-size string of characters, which is + typically a hash value. Hash functions are commonly used in various + cryptographic applications, including data integrity verification and + password hashing. + + + + + + + Public Key Encryption (PKE) is a type of encryption that uses a pair of + public and private keys for secure communication. The public key is used + for encryption, while the private key is used for decryption. PKE is a + fundamental component of public-key cryptography. + + + + + + + An XOF is an extendable output function that can take arbitrary input + and creates a stream of output, up to a limit determined by the size of + the internal state of the hash function that underlies the XOF. + + + + + + + A Key Derivation Function (KDF) derives key material from another source + of entropy while preserving the entropy of the input. + + + + + + + In cryptography, a key-agreement is a protocol whereby two or more + parties agree on a cryptographic key in such a way that both influence + the outcome. + + + + + + + A Key Encapsulation Mechanism (KEM) algorithm is a mechanism for + transporting random keying material to a recipient using the recipient's + public key. + + + + + + + Authenticated Encryption (AE) is a cryptographic process that provides + both confidentiality and data integrity. It ensures that the encrypted + data has not been tampered with and comes from a legitimate source. + AE is commonly used in secure communication protocols. + + + + + + + A combiner aggregates many candidates for a cryptographic primitive and + generates a new candidate for the same primitive. + + + + + + + Another primitive type. + + + + + + + The primitive is not known. + + + + + + + + + + An identifier for the parameter set of the cryptographic algorithm. Examples: in + AES128, '128' identifies the key length in bits, in SHA256, '256' identifies the + digest length, '128' in SHAKE128 identifies its maximum security level in bits, and + 'SHA2-128s' identifies a parameter set used in SLH-DSA (FIPS205). + + + + + + + The specific underlying Elliptic Curve (EC) definition employed which is an indicator + of the level of security strength, performance and complexity. Absent an + authoritative source of curve names, CycloneDX recommends use of curve names as + defined at https://neuromancer.sk/std/, the source from which can be found at + https://github.com/J08nY/std-curves. + + + + + + + The target and execution environment in which the algorithm is implemented in. + + + + + + + + A software implementation running in plain unencrypted RAM. + + + + + + + A software implementation running in encrypted RAM. + + + + + + A software implementation running in a trusted execution environment. + + + + + + A hardware implementation. + + + + + + Another implementation environment. + + + + + + The execution environment is not known. + + + + + + + + + + The target platform for which the algorithm is implemented. The implementation can + be 'generic', running on any platform or for a specific platform. + + + + + + + + + + + + + + + + + + + + + + + + + The certification that the implementation of the cryptographic algorithm has + received, if any. Certifications include revisions and levels of FIPS 140 or + Common Criteria of different Extended Assurance Levels (CC-EAL). + + + + + + + + No certification obtained + + + + + + + FIPS 140-1 Level 1 + + + + + + + FIPS 140-1 Level 2 + + + + + + + FIPS 140-1 Level 3 + + + + + + + FIPS 140-1 Level 4 + + + + + + + FIPS 140-2 Level 1 + + + + + + + FIPS 140-2 Level 2 + + + + + + + FIPS 140-2 Level 3 + + + + + + + FIPS 140-2 Level 4 + + + + + + + FIPS 140-3 Level 1 + + + + + + + FIPS 140-3 Level 2 + + + + + + + FIPS 140-3 Level 3 + + + + + + + FIPS 140-3 Level 4 + + + + + + + Common Criteria - Evaluation Assurance Level 1 + + + + + + + Common Criteria - Evaluation Assurance Level 1 (Augmented) + + + + + + + Common Criteria - Evaluation Assurance Level 2 + + + + + + + Common Criteria - Evaluation Assurance Level 2 (Augmented) + + + + + + + Common Criteria - Evaluation Assurance Level 3 + + + + + + + Common Criteria - Evaluation Assurance Level 3 (Augmented) + + + + + + + Common Criteria - Evaluation Assurance Level 4 + + + + + + + Common Criteria - Evaluation Assurance Level 4 (Augmented) + + + + + + + Common Criteria - Evaluation Assurance Level 5 + + + + + + + Common Criteria - Evaluation Assurance Level 5 (Augmented) + + + + + + + Common Criteria - Evaluation Assurance Level 6 + + + + + + + Common Criteria - Evaluation Assurance Level 6 (Augmented) + + + + + + + Common Criteria - Evaluation Assurance Level 7 + + + + + + + Common Criteria - Evaluation Assurance Level 7 (Augmented) + + + + + + + Another certification + + + + + + + The certification level is not known + + + + + + + + + + The mode of operation in which the cryptographic algorithm (block cipher) is used. + + + + + + + + Cipher block chaining + + + + + + + Electronic codebook + + + + + + + Counter with cipher block chaining message authentication code + + + + + + + Galois/counter + + + + + + + Cipher feedback + + + + + + + Output feedback + + + + + + + Counter + + + + + + + Another mode of operation + + + + + + + The mode of operation is not known + + + + + + + + + + The padding scheme that is used for the cryptographic algorithm. + + + + + + + + Password-Based Cryptography Specification #5 + + + + + + + Public Key Cryptography Standard: Cryptographic Message Syntax + + + + + + + Public Key Cryptography Standard: RSA Cryptography v1.5 + + + + + + + Optimal asymmetric encryption padding + + + + + + + Raw + + + + + + + Another padding scheme + + + + + + + The padding scheme is not known + + + + + + + + + + The cryptographic functions implemented by the cryptographic algorithm. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The classical security level that a cryptographic algorithm provides (in bits). + + + + + + + + + + + + The NIST security strength category as defined in + https://csrc.nist.gov/projects/post-quantum-cryptography/post-quantum-cryptography-standardization/evaluation-criteria/security-(evaluation-criteria). + A value of 0 indicates that none of the categories are met. + + + + + + + + + + + + + - The underlying path created from the actual volume. + Properties for cryptographic assets of asset type 'certificate' + + + + + + The subject name for the certificate + + + + + + + The issuer name for the certificate + + + + + + + The date and time according to ISO-8601 standard from which the certificate is valid + + + + + + + The date and time according to ISO-8601 standard from which the certificate is not valid anymore + + + + + + + The bom-ref to signature algorithm used by the certificate + + + + + + + The bom-ref to the public key of the subject + + + + + + + The format of the certificate. Examples include X.509, PEM, DER, and CVC + + + + + + + The file extension of the certificate. Examples include crt, pem, cer, der, and p12. + + + + + - + - The allocated size of the volume accessible to the associated workspace. This should include - the scalar size as well as IEC standard unit in either decimal or binary form. + Properties for cryptographic assets of asset type 'relatedCryptoMaterial' + + + + + + The type for the related cryptographic material + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The optional unique identifier for the related cryptographic material. + + + + + + + The key state as defined by NIST SP 800-57. + + + + + + + + + + + + + + + + + The bom-ref to the algorithm used to generate the related cryptographic material. + + + + + + + The date and time (timestamp) when the related cryptographic material was created. + + + + + + + The date and time (timestamp) when the related cryptographic material was activated. + + + + + + + The date and time (timestamp) when the related cryptographic material was updated. + + + + + + + The date and time (timestamp) when the related cryptographic material expires. + + + + + + + The associated value of the cryptographic material. + + + + + + + The size of the cryptographic asset (in bits). + + + + + + + The format of the related cryptographic material (e.g. P8, PEM, DER). + + + + + + + The mechanism by which the cryptographic asset is secured by. + + + + + + + + Specifies the mechanism by which the cryptographic asset is secured by. + Examples include HSM, TPM, XGX, Software, and None. + + + + + + + The bom-ref to the algorithm. + + + + + + + + - + - Indicates if the volume persists beyond the life of the resource it is associated with. + Properties specific to cryptographic assets of type: 'protocol'. + + + + + + The concrete protocol type. + + + + + + + + Transport Layer Security + + + + + + + Secure Shell + + + + + + + Internet Protocol Security + + + + + + + Internet Key Exchange + + + + + + + Secure Socket Tunneling Protocol + + + + + + + Wi-Fi Protected Access + + + + + + + Another protocol type + + + + + + + The protocol type is not known + + + + + + + + + + The version of the protocol. Examples include 1.0, 1.2, and 1.99. + + + + + + + A list of cipher suites related to the protocol. + + + + + + + + + + + A common name for the cipher suite. For example: TLS_DHE_RSA_WITH_AES_128_CCM + + + + + + + A list of algorithms related to the cipher suite. + + + + + + + + The bom-ref to algorithm cryptographic asset. + + + + + + + + + + A list of common identifiers for the cipher suite. + + + + + + + + Cipher suite identifier. Examples include 0xC0 and 0x9E. + + + + + + + + + + + + + + + + The IKEv2 transform types supported (types 1-4), defined in RFC7296 section 3.3.2, + and additional properties. + + + + + + + + Transform Type 1: encryption algorithms + + + + + + + Transform Type 2: pseudorandom functions + + + + + + + Transform Type 3: integrity algorithms + + + + + + + Transform Type 4: Key Exchange Method (KE) per RFC9370, formerly called Diffie-Hellman Group (D-H) + + + + + + + Specifies if an Extended Sequence Number (ESN) is used. + + + + + + + IKEv2 Authentication method + + + + + + + + - + - Indicates if the volume is remotely (i.e., network) attached. + The object identifier (OID) of the cryptographic asset. - - - Provides the ability to document properties in a name/value store. - This provides flexibility to include data not officially supported in the standard - without having to use additional namespaces or create extensions. Property names - of interest to the general public are encouraged to be registered in the - CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. - Formal registration is OPTIONAL. - - - - - - - - - - - - - Executes specific commands or tools in order to accomplish its owning task as part of a sequence. - - + - + - A name for the step. + The list of assessors evaluating claims and determining conformance to requirements and confidence in that assessment. + + + + + + The assessor who evaluates claims and determines conformance to requirements and confidence in that assessment. + + + + + + + + The boolean indicating if the assessor is outside the organization generating claims. A value of false indicates a self assessor. + + + + + + + The entity issuing the assessment. + + + + + + + + An optional identifier which can be used to reference the object elsewhere in the BOM. + Every bom-ref MUST be unique within the BOM. + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + + + - + - A description of the step. + The list of attestations asserted by an assessor that maps requirements to claims. + + + + + + An attestation asserted by an assessor that maps requirements to claims. + + + + + + + + The short description explaining the main points of the attestation. + + + + + + + The `bom-ref` to the assessor asserting the attestation. + + + + + + + The grouping of requirements to claims and the attestors declared conformance and confidence thereof. + + + + + + + + The `bom-ref` to the requirement being attested to. + + + + + + + The list of `bom-ref` to the claims being attested to. + + + + + + + + The `bom-ref` to the claim being attested to. + + + + + + + + + + The list of `bom-ref` to the counter claims being attested to. + + + + + + + + The `bom-ref` to the counter claim being attested to. + + + + + + + + + + The conformance of the claim meeting a requirement. + + + + + + + + The conformance of the claim between and inclusive of 0 and 1, where 1 is 100% conformance. + + + + + + + + + + + + + The rationale for the score of conformance. + + + + + + + The list of `bom-ref` to the evidence provided describing the + mitigation strategies. Each mitigation strategy should include an + explanation of how any weaknesses in the evidence will be mitigated. + + + + + + + + + + + + + + + The confidence of the claim meeting the requirement. + + + + + + + + The confidence of the claim between and inclusive of 0 and 1, where 1 is 100% confidence. + + + + + + + + + + + + + The rationale for the confidence score. + + + + + + + + + + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + + + + + + - + - Ordered list of commands or directives for the step + The list of claims. - + - + - A text representation of the executed command. + The `bom-ref` to a target representing a specific system, application, + API, module, team, person, process, business unit, company, etc... + that this claim is being applied to. - + - Provides the ability to document properties in a name/value store. - This provides flexibility to include data not officially supported in the standard - without having to use additional namespaces or create extensions. Property names - of interest to the general public are encouraged to be registered in the - CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. - Formal registration is OPTIONAL. + + The specific statement or assertion about the target. + + + + + + + The list of `bom-ref` to the evidence provided describing the + mitigation strategies. Each mitigation strategy should include an + explanation of how any weaknesses in the evidence will be mitigated. + + + + + + + + + + + + The written explanation of why the evidence provided substantiates the claim. + + + + + + + The list of `bom-ref` to evidence that supports this claim. + + + + + + + The list of `bom-ref` to counterEvidence that supports this claim. + + + + + + Provides the ability to document external references related to the claim the BOM describes. + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + + + + + An optional identifier which can be used to reference the object elsewhere + in the BOM. Every bom-ref MUST be unique within the BOM. + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + - - - Provides the ability to document properties in a name/value store. - This provides flexibility to include data not officially supported in the standard - without having to use additional namespaces or create extensions. Property names - of interest to the general public are encouraged to be registered in the - CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. - Formal registration is OPTIONAL. - - - - - - Allows any undeclared elements as long as the elements are placed in a different namespace. - - - - - - - User-defined attributes may be used on this element as long as they - do not have the same name as an existing attribute used by the schema. - - - - - - - - - - The unique identifier for the resource instance within its deployment context. - - - - - - - The name of the resource instance. - - - - - - - The description of the resource instance. - - - - - - - References to component or service resources that are used to realize the resource instance. - - - - - - - The source type of event which caused the trigger to fire. - - - - + - The event data that caused the associated trigger to activate. + The list of evidence - - - + - A condition that was used to determine a trigger should be activated. + The list of evidence + + + + The reference to the property name as defined in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy/). + + + - Describes the set of conditions which cause the trigger to activate. + The written description of what this evidence is and how it was created. - + - The logical expression that was evaluated that determined the trigger should be fired. + The output or analysis that supports claims. + + + + + + The name of the data. + + + + + + + The contents or references to the contents of the data being described. + + + + + + + An optional way to include textual or encoded data. + + + + + The URL to where the data can be retrieved. + + + + + + + + + Data classification tags data according to its type, sensitivity, and value if altered, stolen, or destroyed. + + + + + + + A description of any sensitive data. + + + + + + - + - Provides the ability to document properties in a name/value store. - This provides flexibility to include data not officially supported in the standard - without having to use additional namespaces or create extensions. Property names - of interest to the general public are encouraged to be registered in the - CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. - Formal registration is OPTIONAL. + The date and time (timestamp) when the evidence was created. + + + + + The optional date and time (timestamp) when the evidence is no longer valid. + + + + + The author of the evidence. + + + + + The reviewer of the evidence. + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + + + + + + An optional identifier which can be used to reference the object elsewhere + in the BOM. Every bom-ref MUST be unique within the BOM. + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + + + + + + + + The list of targets which claims are made against. + + + + + + + + The list of organizations which claims are made against. + + + + + + + + + + + + The list of components which claims are made against. + + + + + + + + + + + + The list of services which claims are made against. + + + + + - - - - The date and time (timestamp) when the trigger was activated. - - - - - - - Represents resources and data brought into a task at runtime by executor or task commands - - - - - - - - - - - - Represents resources and data output from a task at runtime by executor or task commands - - + - + + + + The brief statement affirmed by an individual regarding all declarations. + This could be an affirmation of acceptance by a third-party auditor or receiving + individual of a file. For example: "I certify, to the best of my knowledge, that all information is correct." + + + + + + + The list of signatories authorized on behalf of an organization to assert validity of this document. + + + + + + + + + + + The signatory's name. + + + + + + + The signatory's role within an organization. + + + + + + + The signatory's organization. + + + + + + + An External reference provide a way to document systems, sites, and information that may be relevant, but are not included with the BOM. They may also establish specific relationships within or external to the BOM. + + + + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + + + + + + + + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + - - - Provides the ability to document properties in a name/value store. - This provides flexibility to include data not officially supported in the standard - without having to use additional namespaces or create extensions. Property names - of interest to the general public are encouraged to be registered in the - CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. - Formal registration is OPTIONAL. - - - - - - Allows any undeclared elements as long as the elements are placed in a different namespace. - - - - - - - - An optional identifier which can be used to reference the trigger elsewhere in the BOM. - Uniqueness is enforced within all elements and children of the root-level bom element. - - - - - - User-defined attributes may be used on this element as long as they - do not have the same name as an existing attribute used by the schema. - - - - - - - - - - - - - - - - - - - The unique identifier of the event. - - - - - - - A description of the event. - - - - - - - The date and time (timestamp) when the event was received. - - - - - - - Encoding of the raw event data. - - - - - - - References the component or service that was the source of the event - - - - - - - References the component or service that was the target of the event - - - - - - Provides the ability to document properties in a name/value store. - This provides flexibility to include data not officially supported in the standard - without having to use additional namespaces or create extensions. Property names - of interest to the general public are encouraged to be registered in the - CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. - Formal registration is OPTIONAL. - - @@ -5115,87 +7889,28 @@ limitations under the License. - - - - User-defined attributes may be used on this element as long as they - do not have the same name as an existing attribute used by the schema. - - - - - - - - Type that represents various input data types and formats. - - - - - - - - A reference to an independent resource provided as an input to a task by the workflow runtime. - - - - - - - Inputs that have the form of parameters with names and values. - - - - - - - Inputs that have the form of parameters with names and values. - - - - - - - - - - - - - - - - Inputs that have the form of data. - - - - - - - - A references to the component or service that provided the input to the task - (e.g., reference to a service with data flow value of inbound) - - - - - - - A reference to the component or service that received or stored the input if not the task - itself (e.g., a local, named storage workspace) - - - - - - Provides the ability to document properties in a name/value store. - This provides flexibility to include data not officially supported in the standard - without having to use additional namespaces or create extensions. Property names - of interest to the general public are encouraged to be registered in the - CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. - Formal registration is OPTIONAL. - - + + + + + + + A collection of reusable objects that are defined and may be used elsewhere in the BOM. + + + + + + + + + + + The list of standards which may consist of regulations, industry or organizational-specific standards, maturity models, best practices, or any other requirements which can be evaluated against or attested to. + + + + @@ -5212,136 +7927,208 @@ limitations under the License. - + - Represents resources and data output from a task at runtime by executor or task commands + A standard may consist of regulations, industry or organizational-specific standards, maturity models, best practices, or any other requirements which can be evaluated against or attested to. - - - - - A reference to an independent resource generated as output by the task. - - - - - - - Outputs that have the form of environment variables. - - - - - - - - - - - - - - - - Outputs that have the form of data. - - - - - + - Describes the type of data output. + The name of the standard. This will often be a shortened, single name of the standard. - + - Component or service that generated or provided the output from the task (e.g., a build tool) + The version of the standard. - + - Component or service that received the output from the task - (e.g., reference to an artifactory service with data flow value of outbound) + The description of the standard. - - - Provides the ability to document properties in a name/value store. - This provides flexibility to include data not officially supported in the standard - without having to use additional namespaces or create extensions. Property names - of interest to the general public are encouraged to be registered in the - CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. - Formal registration is OPTIONAL. - - - + - Allows any undeclared elements as long as the elements are placed in a different namespace. + The owner of the standard, often the entity responsible for its release. - - - - - User-defined attributes may be used on this element as long as they - do not have the same name as an existing attribute used by the schema. - - - - - - - - - - - - - - - - - - - - - - - - - A representation of a functional parameter. - - - - + + - The name of the parameter. + The list of requirements comprising the standard. + + + + + + + + + The unique identifier used in the standard to identify a specific requirement. This should match what is in the standard and should not be the requirements bom-ref. + + + + + + + The title of the requirement. + + + + + + + The textual content of the requirement. + + + + + + + The supplemental text that provides additional guidance or context to the requirement, but is not directly part of the requirement. + + + + + + + + + + + + The Common Requirements Enumeration (CRE) identifier(s). CRE is a structured and standardized framework for uniting security standards and guidelines. CRE links each section of a resource to a shared topic identifier (a Common Requirement). Through this shared topic link, all resources map to each other. Use of CRE promotes clear and unambiguous communication among stakeholders. + + + + + + + + + + + + The optional `bom-ref` to a parent requirement. This establishes a hierarchy of requirements. Top-level requirements must not define a parent. Only child requirements should define parents. + + + + + + Provides the ability to document properties in a name/value store. + This provides flexibility to include data not officially supported in the standard + without having to use additional namespaces or create extensions. Property names + of interest to the general public are encouraged to be registered in the + CycloneDX Property Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. + Formal registration is OPTIONAL. + + + + + Provides the ability to document external references related to the BOM or + to the project the BOM describes. + + + + + + + An optional identifier which can be used to reference the object elsewhere + in the BOM. Every bom-ref MUST be unique within the BOM. + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + + + - + - The value of the parameter. + The list of levels associated with the standard. Some standards have different levels of compliance. + + + + + + + + + The identifier used in the standard to identify a specific level. + + + + + + + The title of the level. + + + + + + + The description of the level. + + + + + + + The list of requirement `bom-ref`s that comprise the level. + + + + + + + + + + + + + An optional identifier which can be used to reference the object elsewhere + in the BOM. Every bom-ref MUST be unique within the BOM. + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + + + - + - - The data type of the parameter. - + Provides the ability to document external references related to the BOM or + to the project the BOM describes. @@ -5352,7 +8139,15 @@ limitations under the License. - + + + + An optional identifier which can be used to reference the object elsewhere + in the BOM. Every bom-ref MUST be unique within the BOM. + + + + User-defined attributes may be used on this element as long as they do not have the same name as an existing attribute used by the schema. @@ -5360,6 +8155,22 @@ limitations under the License. + + + + + Textual strings that aid in discovery, search, and retrieval of the associated + object. Tags often serve as a way to group or categorize similar or related objects by various + attributes. + + Examples include: + "json-parser", "object-persistence", "text-to-image", "translation", and "object-detection" + + + + + + @@ -5426,6 +8237,21 @@ limitations under the License. in the manufacturing process. + + + + The list of declarations which describe the conformance to standards. Each declaration may + include attestations, claims, and evidence. + + + + + + + A collection of reusable objects that are defined and may be used elsewhere in the BOM. + + + diff --git a/schema/cyclonedx/spdx.xsd b/schema/cyclonedx/spdx.xsd index 1365ed71f..a339a0857 100644 --- a/schema/cyclonedx/spdx.xsd +++ b/schema/cyclonedx/spdx.xsd @@ -2,7 +2,7 @@ + version="1.0-3.24.0"> @@ -12,6 +12,11 @@ BSD Zero Clause License + + + 3D Slicer License v1.0 + + Attribution Assurance License @@ -117,6 +122,11 @@ Aladdin Free Public License + + + AMD newlib License + + AMD's plpa_map.c License @@ -147,6 +157,11 @@ ANTLR Software Rights Notice with license fallback + + + Any OSI License + + Apache License 1.0 @@ -322,6 +337,11 @@ BSD 2-Clause - Ian Darwin variant + + + BSD 2-Clause - first lines requirement + + BSD 2-Clause FreeBSD License @@ -522,6 +542,11 @@ Caldera License (without preamble) + + + Catharon License + + Computer Associates Trusted Open Source License 1.1 @@ -1002,6 +1027,11 @@ curl License + + + Common Vulnerability Enumeration ToU License + + Deutsche Freie Software Lizenz @@ -1482,6 +1512,11 @@ gtkbook License + + + Gutmann License + + Haskell Language Report License @@ -1532,11 +1567,21 @@ HPND with US Government export control warning + + + HPND with US Government export control warning and acknowledgment + + HPND with US Government export control warning and modification rqmt + + + HPND with US Government export control and 2 disclaimers + + Historical Permission Notice and Disclaimer - Fenneberg-Livingston variant @@ -1547,6 +1592,11 @@ Historical Permission Notice and Disclaimer - INRIA-IMAG variant + + + Historical Permission Notice and Disclaimer - Intel variant + + Historical Permission Notice and Disclaimer - Kevlin Henney variant @@ -1557,6 +1607,11 @@ Historical Permission Notice and Disclaimer - Markus Kuhn variant + + + Historical Permission Notice and Disclaimer - merchantability variant + + Historical Permission Notice and Disclaimer with MIT disclaimer @@ -1587,11 +1642,21 @@ HPND sell variant with MIT disclaimer + + + HPND sell variant with MIT disclaimer - reverse + + Historical Permission Notice and Disclaimer - University of California variant + + + Historical Permission Notice and Disclaimer - University of California, US export warning + + HTML Tidy License @@ -2027,6 +2092,11 @@ MIT Festival Variant + + + MIT Khronos - old variant + + MIT License Modern Variant @@ -2162,11 +2232,21 @@ Net Boolean Public License v1 + + + NCBI Public Domain Notice + + Non-Commercial Government Licence + + + NCL Source Code License + + University of Illinois/NCSA Open Source License @@ -2282,6 +2362,11 @@ Open Use of Data Agreement v1.0 + + + OAR License + + Open CASCADE Technology Public License @@ -2562,6 +2647,11 @@ Pixar License + + + pkgconf License + + Plexus Classworlds License @@ -2587,6 +2677,11 @@ PostgreSQL License + + + Peer Production License + + Python Software Foundation License 2.0 @@ -2862,6 +2957,11 @@ Sun PPP License + + + Sun PPP License (2000) + + SunPro License @@ -2907,6 +3007,11 @@ Transitive Grace Period Public Licence 1.0 + + + threeparttable License + + TMate Open Source License @@ -3132,6 +3237,11 @@ XSkat License + + + xzoom License + + Yahoo! Public License v1.0 @@ -3203,6 +3313,11 @@ Asterisk exception + + + Asterisk linking protocols exception + + Autoconf exception 2.0 @@ -3438,6 +3553,11 @@ OpenVPN OpenSSL Exception + + + PCRE2 exception + + PS/PDF font exception (2017-08-17) @@ -3463,6 +3583,11 @@ Qwt exception 1.0 + + + RRDtool FLOSS exception 2.0 + + SANE Exception diff --git a/syft/format/cyclonedxjson/test-fixtures/identify/1.6.json b/syft/format/cyclonedxjson/test-fixtures/identify/1.6.json new file mode 100644 index 000000000..9f4cb7bdc --- /dev/null +++ b/syft/format/cyclonedxjson/test-fixtures/identify/1.6.json @@ -0,0 +1,59 @@ +{ + "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.6", + "serialNumber": "urn:uuid:5208fea9-73dd-4624-b596-69fddccdb9e7", + "version": 1, + "metadata": { + "timestamp": "2023-09-29T12:02:02-04:00", + "tools": [ + { + "vendor": "anchore", + "name": "syft", + "version": "[not provided]" + } + ], + "component": { + "bom-ref": "a0ff99a6af10f11f", + "type": "file", + "name": "go.mod", + "version": "sha256:sha256:dc333f342905248a52e424d8dfd061251d01867d01a4f9d7397144a775ff9ebd" + } + }, + "components": [ + { + "bom-ref": "pkg:golang/github.com/wagoodman/go-partybus@v0.0.0-20230516145632-8ccac152c651?package-id=2ff71a67fb024c86", + "type": "library", + "name": "github.com/wagoodman/go-partybus", + "version": "v0.0.0-20230516145632-8ccac152c651", + "cpe": "cpe:2.3:a:wagoodman:go-partybus:v0.0.0-20230516145632-8ccac152c651:*:*:*:*:*:*:*", + "purl": "pkg:golang/github.com/wagoodman/go-partybus@v0.0.0-20230516145632-8ccac152c651", + "properties": [ + { + "name": "syft:package:foundBy", + "value": "go-module-file-cataloger" + }, + { + "name": "syft:package:language", + "value": "go" + }, + { + "name": "syft:package:metadataType", + "value": "GolangModMetadata" + }, + { + "name": "syft:package:type", + "value": "go-module" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:wagoodman:go_partybus:v0.0.0-20230516145632-8ccac152c651:*:*:*:*:*:*:*" + }, + { + "name": "syft:location:0:path", + "value": "/go.mod" + } + ] + } + ] +} diff --git a/syft/format/cyclonedxjson/test-fixtures/identify/micronaut-1.6.json b/syft/format/cyclonedxjson/test-fixtures/identify/micronaut-1.6.json new file mode 100644 index 000000000..1e4cd235c --- /dev/null +++ b/syft/format/cyclonedxjson/test-fixtures/identify/micronaut-1.6.json @@ -0,0 +1,28 @@ +{ + "bomFormat": "CycloneDX", + "specVersion": "1.6", + "version": 1, + "components": [ + { + "type": "library", + "group": "io.netty", + "name": "netty-codec-http2", + "version": "4.1.73.Final", + "properties": [ + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:codec:codec:4.1.73.Final:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:codec:netty-codec-http2:4.1.73.Final:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:codec:netty_codec_http2:4.1.73.Final:*:*:*:*:*:*:*" + } + ] + } + ], + "serialNumber": "urn:uuid:3eb5ec7a-cb05-4339-b873-e27b1c1efaba" +} diff --git a/syft/format/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden b/syft/format/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden index a39921ac8..e4e7bd752 100644 --- a/syft/format/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden +++ b/syft/format/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden @@ -1,7 +1,7 @@ { - "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", + "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", "bomFormat": "CycloneDX", - "specVersion": "1.5", + "specVersion": "1.6", "serialNumber": "urn:uuid:redacted", "version": 1, "metadata": { diff --git a/syft/format/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden b/syft/format/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden index 5bbd1a51b..62750e9e6 100644 --- a/syft/format/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden +++ b/syft/format/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden @@ -1,7 +1,7 @@ { - "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", + "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", "bomFormat": "CycloneDX", - "specVersion": "1.5", + "specVersion": "1.6", "serialNumber": "urn:uuid:redacted", "version": 1, "metadata": { diff --git a/syft/format/cyclonedxxml/test-fixtures/identify/1.6.xml b/syft/format/cyclonedxxml/test-fixtures/identify/1.6.xml new file mode 100644 index 000000000..336feb1fb --- /dev/null +++ b/syft/format/cyclonedxxml/test-fixtures/identify/1.6.xml @@ -0,0 +1,33 @@ + + + + 2023-09-29T11:48:10-04:00 + + + anchore + syft + [not provided] + + + + go.mod + sha256:sha256:dc333f342905248a52e424d8dfd061251d01867d01a4f9d7397144a775ff9ebd + + + + + github.com/wagoodman/go-partybus + v0.0.0-20230516145632-8ccac152c651 + cpe:2.3:a:wagoodman:go-partybus:v0.0.0-20230516145632-8ccac152c651:*:*:*:*:*:*:* + pkg:golang/github.com/wagoodman/go-partybus@v0.0.0-20230516145632-8ccac152c651 + + go-module-file-cataloger + go + GolangModMetadata + go-module + cpe:2.3:a:wagoodman:go_partybus:v0.0.0-20230516145632-8ccac152c651:*:*:*:*:*:*:* + /go.mod + + + + \ No newline at end of file diff --git a/syft/format/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden b/syft/format/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden index 9c52a354a..9a9f7bce8 100644 --- a/syft/format/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden +++ b/syft/format/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden @@ -1,5 +1,5 @@ - + redacted diff --git a/syft/format/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden b/syft/format/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden index c130be60d..12c99a5fa 100644 --- a/syft/format/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden +++ b/syft/format/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden @@ -1,5 +1,5 @@ - + redacted diff --git a/syft/format/internal/cyclonedxutil/encoder.go b/syft/format/internal/cyclonedxutil/encoder.go index 252159447..26da2de00 100644 --- a/syft/format/internal/cyclonedxutil/encoder.go +++ b/syft/format/internal/cyclonedxutil/encoder.go @@ -9,7 +9,7 @@ import ( "github.com/anchore/syft/syft/sbom" ) -const DefaultVersion = "1.5" +const DefaultVersion = "1.6" type Encoder struct { version cyclonedx.SpecVersion diff --git a/syft/format/internal/cyclonedxutil/versions.go b/syft/format/internal/cyclonedxutil/versions.go index 426da2c65..7c6e74bab 100644 --- a/syft/format/internal/cyclonedxutil/versions.go +++ b/syft/format/internal/cyclonedxutil/versions.go @@ -19,6 +19,7 @@ func SupportedVersions(id sbom.FormatID) []string { "1.3", "1.4", "1.5", + "1.6", } if id != JSONFormatID { @@ -43,6 +44,8 @@ func SpecVersionFromString(v string) (cyclonedx.SpecVersion, error) { return cyclonedx.SpecVersion1_4, nil case "1.5": return cyclonedx.SpecVersion1_5, nil + case "1.6": + return cyclonedx.SpecVersion1_6, nil } return -1, fmt.Errorf("unsupported CycloneDX version %q", v) } @@ -61,6 +64,8 @@ func VersionFromSpecVersion(spec cyclonedx.SpecVersion) string { return "1.4" case cyclonedx.SpecVersion1_5: return "1.5" + case cyclonedx.SpecVersion1_6: + return "1.6" } return "" } From f5a917a5a2553f09a21f33e681db7a9398f7c663 Mon Sep 17 00:00:00 2001 From: Christopher Angelo Phillips <32073428+spiffcs@users.noreply.github.com> Date: Fri, 21 Jun 2024 12:32:59 -0400 Subject: [PATCH 052/284] docs: update cyclone-dx documentation (#2983) * chore: update docs to show 1.6 for cyclone-dx by default * chore: update README showing version information for formats --------- Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b36ab288d..141257be5 100644 --- a/README.md +++ b/README.md @@ -105,8 +105,10 @@ syft -o Where the `formats` available are: - `syft-json`: Use this to get as much information out of Syft as possible! - `syft-text`: A row-oriented, human-and-machine-friendly output. -- `cyclonedx-xml`: A XML report conforming to the [CycloneDX 1.4 specification](https://cyclonedx.org/specification/overview/). -- `cyclonedx-json`: A JSON report conforming to the [CycloneDX 1.4 specification](https://cyclonedx.org/specification/overview/). +- `cyclonedx-xml`: A XML report conforming to the [CycloneDX 1.6 specification](https://cyclonedx.org/specification/overview/). +- `cyclonedx-xml@1.5`: A XML report conforming to the [CycloneDX 1.5 specification](https://cyclonedx.org/specification/overview/). +- `cyclonedx-json`: A JSON report conforming to the [CycloneDX 1.6 specification](https://cyclonedx.org/specification/overview/). +- `cyclonedx-json@1.5`: A JSON report conforming to the [CycloneDX 1.5 specification](https://cyclonedx.org/specification/overview/). - `spdx-tag-value`: A tag-value formatted report conforming to the [SPDX 2.3 specification](https://spdx.github.io/spdx-spec/v2.3/). - `spdx-tag-value@2.2`: A tag-value formatted report conforming to the [SPDX 2.2 specification](https://spdx.github.io/spdx-spec/v2.2.2/). - `spdx-json`: A JSON report conforming to the [SPDX 2.3 JSON Schema](https://github.com/spdx/spdx-spec/blob/v2.3/schemas/spdx-schema.json). @@ -115,6 +117,8 @@ Where the `formats` available are: - `syft-table`: A columnar summary (default). - `template`: Lets the user specify the output format. See ["Using templates"](#using-templates) below. +Note that flags using the @ can be used for earlier versions of each specification as well. + ### Supported Ecosystems - Alpine (apk) From bd1c1d260c227de88fb4a12b0cd698680cdf8948 Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Mon, 24 Jun 2024 10:27:03 -0400 Subject: [PATCH 053/284] fix: handle errors reading go licenses (#2985) Signed-off-by: Keith Zantow --- internal/cache/filesystem.go | 2 +- internal/cache/filesystem_test.go | 12 +++++ syft/pkg/cataloger/golang/licenses.go | 10 +++- syft/pkg/cataloger/golang/licenses_test.go | 60 ++++++++++++++++++++++ 4 files changed, 82 insertions(+), 2 deletions(-) diff --git a/internal/cache/filesystem.go b/internal/cache/filesystem.go index 8b628cc50..6e7175999 100644 --- a/internal/cache/filesystem.go +++ b/internal/cache/filesystem.go @@ -87,7 +87,7 @@ func subFs(fsys afero.Fs, subDirs ...string) (afero.Fs, error) { if errors.Is(err, afero.ErrFileNotFound) { err = fsys.MkdirAll(dir, dirPermissions) if err != nil { - return nil, fmt.Errorf("unable to create directory at '%s/%s': %v", dir, strings.Join(subDirs, "/"), err) + return nil, fmt.Errorf("unable to create directory at '%s': %v", dir, err) } stat, err = fsys.Stat(dir) if err != nil { diff --git a/internal/cache/filesystem_test.go b/internal/cache/filesystem_test.go index 721cb9f6a..47c693042 100644 --- a/internal/cache/filesystem_test.go +++ b/internal/cache/filesystem_test.go @@ -1,6 +1,7 @@ package cache import ( + "fmt" "io" "net/url" "os" @@ -92,3 +93,14 @@ func Test_makeDiskKey(t *testing.T) { }) } } + +func Test_errors(t *testing.T) { + tmp := t.TempDir() + cache := filepath.Join(tmp, "cache") + // make a non-writable directory + require.NoError(t, os.MkdirAll(cache, 0500|os.ModeDir)) + // attempt to make cache in non-writable directory + dir := filepath.Join(cache, "dir") + _, err := NewFromDir(dir, time.Hour) + require.ErrorContains(t, err, fmt.Sprintf("unable to create directory at '%s':", dir)) +} diff --git a/syft/pkg/cataloger/golang/licenses.go b/syft/pkg/cataloger/golang/licenses.go index 911d386cc..f53246314 100644 --- a/syft/pkg/cataloger/golang/licenses.go +++ b/syft/pkg/cataloger/golang/licenses.go @@ -138,7 +138,15 @@ func (c *goLicenseResolver) getLicensesFromRemote(moduleName, moduleVersion stri func (c *goLicenseResolver) findLicensesInFS(urlPrefix string, fsys fs.FS) ([]goLicense, error) { var out []goLicense - err := fs.WalkDir(fsys, ".", func(filePath string, d fs.DirEntry, _ error) error { + err := fs.WalkDir(fsys, ".", func(filePath string, d fs.DirEntry, err error) error { + if err != nil { + log.Debugf("error reading %s#%s: %v", urlPrefix, filePath, err) + return err + } + if d == nil { + log.Debugf("nil entry for %s#%s", urlPrefix, filePath) + return nil + } if !c.lowerLicenseFileNames.Has(strings.ToLower(d.Name())) { return nil } diff --git a/syft/pkg/cataloger/golang/licenses_test.go b/syft/pkg/cataloger/golang/licenses_test.go index d34d59e5a..0ac644faf 100644 --- a/syft/pkg/cataloger/golang/licenses_test.go +++ b/syft/pkg/cataloger/golang/licenses_test.go @@ -4,6 +4,7 @@ import ( "archive/zip" "bytes" "fmt" + "io/fs" "net/http" "net/http/httptest" "os" @@ -244,3 +245,62 @@ func Test_findVersionPath(t *testing.T) { vp := findVersionPath(f, ".") require.Equal(t, "github.com/someorg/somepkg@version", vp) } + +func Test_walkDirErrors(t *testing.T) { + resolver := newGoLicenseResolver("", CatalogerConfig{}) + _, err := resolver.findLicensesInFS("somewhere", badFS{}) + require.Error(t, err) +} + +type badFS struct{} + +func (b badFS) Open(_ string) (fs.File, error) { + return nil, fmt.Errorf("error") +} + +var _ fs.FS = (*badFS)(nil) + +func Test_noLocalGoModDir(t *testing.T) { + emptyTmp := t.TempDir() + + validTmp := t.TempDir() + require.NoError(t, os.MkdirAll(filepath.Join(validTmp, "mod@ver"), 0700|os.ModeDir)) + + tests := []struct { + name string + dir string + wantErr require.ErrorAssertionFunc + }{ + { + name: "empty", + dir: "", + wantErr: require.Error, + }, + { + name: "invalid dir", + dir: filepath.Join(emptyTmp, "invalid-dir"), + wantErr: require.Error, + }, + { + name: "missing mod dir", + dir: emptyTmp, + wantErr: require.Error, + }, + { + name: "valid mod dir", + dir: validTmp, + wantErr: require.NoError, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + resolver := newGoLicenseResolver("", CatalogerConfig{ + SearchLocalModCacheLicenses: true, + LocalModCacheDir: test.dir, + }) + _, err := resolver.getLicensesFromLocal("mod", "ver") + test.wantErr(t, err) + }) + } +} From 863891f3255a7001f4b4ee719d4edb71117ed9f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 08:27:13 -0700 Subject: [PATCH 054/284] chore(deps): bump github.com/go-test/deep from 1.1.0 to 1.1.1 (#2988) Bumps [github.com/go-test/deep](https://github.com/go-test/deep) from 1.1.0 to 1.1.1. - [Release notes](https://github.com/go-test/deep/releases) - [Changelog](https://github.com/go-test/deep/blob/master/CHANGES.md) - [Commits](https://github.com/go-test/deep/compare/v1.1.0...v1.1.1) --- updated-dependencies: - dependency-name: github.com/go-test/deep dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5d8fe85f4..ef6c42c94 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( github.com/gkampitakis/go-snaps v0.5.4 github.com/go-git/go-billy/v5 v5.5.0 github.com/go-git/go-git/v5 v5.12.0 - github.com/go-test/deep v1.1.0 + github.com/go-test/deep v1.1.1 github.com/google/go-cmp v0.6.0 github.com/google/go-containerregistry v0.19.2 github.com/google/licensecheck v0.3.1 diff --git a/go.sum b/go.sum index b567e8140..ee26ec35a 100644 --- a/go.sum +++ b/go.sum @@ -323,8 +323,8 @@ github.com/go-restruct/restruct v1.2.0-alpha h1:2Lp474S/9660+SJjpVxoKuWX09JsXHSr github.com/go-restruct/restruct v1.2.0-alpha/go.mod h1:KqrpKpn4M8OLznErihXTGLlsXFGeLxHUrLRRI/1YjGk= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= -github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= +github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= From 1eae9333a9450c135ff929578597c79b01c9f5ff Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 08:27:29 -0700 Subject: [PATCH 055/284] chore(deps): update CPE dictionary index (#2986) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: wagoodman <590471+wagoodman@users.noreply.github.com> --- .../cpegenerate/dictionary/data/cpe-index.json | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index 1af72da78..0842a3ce1 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -8535,7 +8535,8 @@ "cpe:2.3:a:quantumcloud:ai_chatbot:*:*:*:*:*:wordpress:*:*" ], "chaty": [ - "cpe:2.3:a:premio:chaty:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:premio:chaty:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:premio:floating_chat_widget:*:*:*:*:*:wordpress:*:*" ], "check-email": [ "cpe:2.3:a:check_email_project:check_email:*:*:*:*:*:wordpress:*:*", @@ -9352,7 +9353,8 @@ "cpe:2.3:a:arwebdesign:dashboard_to-do_list:*:*:*:*:*:wordpress:*:*" ], "dashboard-widgets-suite": [ - "cpe:2.3:a:plugin-planet:dashboard_widget_suite:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:plugin-planet:dashboard_widget_suite:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:plugin-planet:dashboard_widgets_suite:*:*:*:*:*:wordpress:*:*" ], "dashicons-cpt": [ "cpe:2.3:a:halgatewood:dashicons_\\+_custom_post_types:*:*:*:*:*:wordpress:*:*" @@ -9881,6 +9883,9 @@ "elementskit-lite": [ "cpe:2.3:a:wpmet:elements_kit_elementor_addons:*:*:*:*:*:wordpress:*:*" ], + "elespare": [ + "cpe:2.3:a:elespare:elespare:*:*:*:*:*:wordpress:*:*" + ], "emag-marketplace-connector": [ "cpe:2.3:a:zitec:emag_marketplace_connector:*:*:*:*:*:wordpress:*:*" ], @@ -13683,6 +13688,9 @@ "pubsubhubbub": [ "cpe:2.3:a:pubsubhubbub:websub:*:*:*:*:*:wordpress:*:*" ], + "pure-chat": [ + "cpe:2.3:a:purechat:pure_chat:*:*:*:*:*:*:*:*" + ], "purple-xmls-google-product-feed-for-woocommerce": [ "cpe:2.3:a:dpl:product_feed_on_woocommerce_for_google\\,_awin\\,_shareasale\\,_bing\\,_and_more:*:*:*:*:*:wordpress:*:*" ], @@ -15480,6 +15488,9 @@ "themesflat-addons-for-elementor": [ "cpe:2.3:a:themesflat:themesflat_addons_for_elementor:*:*:*:*:*:wordpress:*:*" ], + "themify-builder": [ + "cpe:2.3:a:themify:themify_builder:*:*:*:*:*:wordpress:*:*" + ], "themify-portfolio-post": [ "cpe:2.3:a:themify:portfolio_post:*:*:*:*:*:wordpress:*:*" ], From 0dce67872ec713ab05d982ac984828330f00e90b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 10:10:26 -0700 Subject: [PATCH 056/284] chore(deps): bump github.com/charmbracelet/bubbletea (#2995) Bumps [github.com/charmbracelet/bubbletea](https://github.com/charmbracelet/bubbletea) from 0.26.5 to 0.26.6. - [Release notes](https://github.com/charmbracelet/bubbletea/releases) - [Changelog](https://github.com/charmbracelet/bubbletea/blob/master/.goreleaser.yml) - [Commits](https://github.com/charmbracelet/bubbletea/compare/v0.26.5...v0.26.6) --- updated-dependencies: - dependency-name: github.com/charmbracelet/bubbletea dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ef6c42c94..6b8e77287 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 github.com/bmatcuk/doublestar/v4 v4.6.1 github.com/charmbracelet/bubbles v0.18.0 - github.com/charmbracelet/bubbletea v0.26.5 + github.com/charmbracelet/bubbletea v0.26.6 github.com/charmbracelet/lipgloss v0.11.0 github.com/dave/jennifer v1.7.0 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da diff --git a/go.sum b/go.sum index ee26ec35a..fb9133e72 100644 --- a/go.sum +++ b/go.sum @@ -157,8 +157,8 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0= github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw= -github.com/charmbracelet/bubbletea v0.26.5 h1:90pqTPElAReb/qQUgSMUresTkfwVr0Wx+zczeHHOgxk= -github.com/charmbracelet/bubbletea v0.26.5/go.mod h1:dz8CWPlfCCGLFbBlTY4N7bjLiyOGDJEnd2Muu7pOWhk= +github.com/charmbracelet/bubbletea v0.26.6 h1:zTCWSuST+3yZYZnVSvbXwKOPRSNZceVeqpzOLN2zq1s= +github.com/charmbracelet/bubbletea v0.26.6/go.mod h1:dz8CWPlfCCGLFbBlTY4N7bjLiyOGDJEnd2Muu7pOWhk= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v0.11.0 h1:UoAcbQ6Qml8hDwSWs0Y1cB5TEQuZkDPH/ZqwWWYTG4g= From 580c09b01caf35388c086ec6b4000ed088c17107 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 13:41:08 -0700 Subject: [PATCH 057/284] chore(deps): update stereoscope to 753b5576fe42bc007b22108ad7911d1729957a46 (#2992) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: kzantow <3009477+kzantow@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 6b8e77287..789dd700a 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f - github.com/anchore/stereoscope v0.0.3-0.20240501181043-2e9894674185 + github.com/anchore/stereoscope v0.0.3-0.20240624202600-753b5576fe42 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // we are hinting brotli to latest due to warning when installing archiver v3: // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption @@ -124,7 +124,7 @@ require ( github.com/containerd/typeurl/v2 v2.1.1 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/docker/cli v24.0.0+incompatible // indirect + github.com/docker/cli v26.1.4+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-connections v0.4.0 // indirect diff --git a/go.sum b/go.sum index fb9133e72..515b71dfd 100644 --- a/go.sum +++ b/go.sum @@ -113,8 +113,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f h1:B/E9ixKNCasntpoch61NDaQyGPDXLEJlL+B9B/PbdbA= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.3-0.20240501181043-2e9894674185 h1:SuViDJ27nZ+joGdKbAkxAlm7tYMt9NTxTZZ05po4hls= -github.com/anchore/stereoscope v0.0.3-0.20240501181043-2e9894674185/go.mod h1:ckIamHiRMp8iBwWoTtE5Xkt9VQ5QC+6+O4VzwqyZr5Q= +github.com/anchore/stereoscope v0.0.3-0.20240624202600-753b5576fe42 h1:9rQYUxTHfGuX6ZyzSAG4vv0uG3SjoW1M5uRtGgO92Oc= +github.com/anchore/stereoscope v0.0.3-0.20240624202600-753b5576fe42/go.mod h1:sChrYoP82PZDg1V+7O4f8a2XyFkED7FReZsHmwCmSLc= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= @@ -227,8 +227,8 @@ github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da/go.mod h1:B3tI9iGHi4i github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/cli v24.0.0+incompatible h1:0+1VshNwBQzQAx9lOl+OYCTCEAD8fKs/qeXMx3O0wqM= -github.com/docker/cli v24.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v26.1.4+incompatible h1:I8PHdc0MtxEADqYJZvhBrW9bo8gawKwwenxRM7/rLu8= +github.com/docker/cli v26.1.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU= From 7da15890eb624a38786bca4a109dbad562fc85df Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 13:41:26 -0700 Subject: [PATCH 058/284] chore(deps): update tools to latest versions (#2991) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index 9dc99fa5c..e544efb7f 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -111,7 +111,7 @@ tools: # used for triggering a release - name: gh version: - want: v2.51.0 + want: v2.52.0 method: github-release with: repo: cli/cli From ceced5eb27b94df84d60880e6e41a2d42554a628 Mon Sep 17 00:00:00 2001 From: Laurent Goderre Date: Tue, 25 Jun 2024 17:40:40 -0400 Subject: [PATCH 059/284] Add detection of Erlang in Alpine linux (#2996) Signed-off-by: Laurent Goderre --- .../binary/classifier_cataloger_test.go | 11 +++++++++++ syft/pkg/cataloger/binary/classifiers.go | 17 +++++++++++++++++ .../cataloger/binary/test-fixtures/config.yaml | 8 ++++++++ 3 files changed, 36 insertions(+) diff --git a/syft/pkg/cataloger/binary/classifier_cataloger_test.go b/syft/pkg/cataloger/binary/classifier_cataloger_test.go index 595bbd0f6..978e45755 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger_test.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger_test.go @@ -907,6 +907,17 @@ func Test_Cataloger_PositiveCases(t *testing.T) { Metadata: metadata("erlang-library"), }, }, + { + logicalFixture: "erlang/27.0/linux-amd64", + expected: pkg.Package{ + Name: "erlang", + Version: "27.0", + Type: "binary", + PURL: "pkg:generic/erlang@27.0", + Locations: locations("beam.smp"), + Metadata: metadata("erlang-alpine-binary"), + }, + }, { logicalFixture: "nginx/1.25.1/linux-amd64", expected: pkg.Package{ diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index fb17f0ff2..e11cd2a7f 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -393,6 +393,23 @@ func DefaultClassifiers() []Classifier { PURL: mustPURL("pkg:generic/erlang@version"), CPEs: singleCPE("cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*"), }, + { + Class: "erlang-alpine-binary", + FileGlob: "**/beam.smp", + EvidenceMatcher: evidenceMatchers( + FileContentsVersionMatcher( + // [NUL]/usr/src/otp_src_25.3.2.6/erts/ + `(?m)/src/otp_src_(?P[0-9]+\.[0-9]+(\.[0-9]+){0,2}(-rc[0-9])?)/erts/`, + ), + FileContentsVersionMatcher( + // [NUL]/usr/local/src/otp-25.3.2.7/erts/ + `(?m)/usr/local/src/otp-(?P[0-9]+\.[0-9]+(\.[0-9]+){0,2}(-rc[0-9])?)/erts/`, + ), + ), + Package: "erlang", + PURL: mustPURL("pkg:generic/erlang@version"), + CPEs: singleCPE("cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*"), + }, { Class: "erlang-library", FileGlob: "**/liberts_internal.a", diff --git a/syft/pkg/cataloger/binary/test-fixtures/config.yaml b/syft/pkg/cataloger/binary/test-fixtures/config.yaml index 559b36e63..e14c050c5 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/config.yaml +++ b/syft/pkg/cataloger/binary/test-fixtures/config.yaml @@ -63,6 +63,14 @@ from-images: paths: - /usr/local/lib/erlang/erts-14.2.4/lib/internal/liberts_internal.a + - name: erlang + version: 27.0 + images: + - ref: erlang:27.0.0.0-alpine@sha256:82064a65eb1f9901a479d8ada5f622be3bfac8b474dfc876dc00c28fdef4b1b8 + platform: linux/amd64 + paths: + - /usr/local/lib/erlang/erts-15.0/bin/beam.smp + - version: 1.21.3 images: - ref: golang:1.21.3@sha256:3ce8313c3513515040870c55e0c041a2b94f3576a58cfd3948633604214aa811 From c8b449c92b9f9d9e16bf18f5be86ccc114a63f50 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:40:51 -0700 Subject: [PATCH 060/284] chore(deps): bump github.com/docker/docker (#2994) Bumps [github.com/docker/docker](https://github.com/docker/docker) from 26.1.4+incompatible to 27.0.1+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v26.1.4...v27.0.1) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 789dd700a..294ea7c8c 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/dave/jennifer v1.7.0 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da github.com/distribution/reference v0.6.0 - github.com/docker/docker v26.1.4+incompatible + github.com/docker/docker v27.0.1+incompatible github.com/dustin/go-humanize v1.0.1 github.com/elliotchance/phpserialize v1.4.0 github.com/facebookincubator/nvdtools v0.1.5 diff --git a/go.sum b/go.sum index 515b71dfd..ccdec2d27 100644 --- a/go.sum +++ b/go.sum @@ -231,8 +231,8 @@ github.com/docker/cli v26.1.4+incompatible h1:I8PHdc0MtxEADqYJZvhBrW9bo8gawKwwen github.com/docker/cli v26.1.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU= -github.com/docker/docker v26.1.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.0.1+incompatible h1:AbszR+lCnR3f297p/g0arbQoyhAkImxQOR/XO9YZeIg= +github.com/docker/docker v27.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= From 4d48adfa3f148e091a6845833180ccaedad8938d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Jun 2024 13:44:52 +0000 Subject: [PATCH 061/284] chore(deps): bump github.com/spdx/tools-golang from 0.5.4 to 0.5.5 (#2999) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 294ea7c8c..e2d633c4a 100644 --- a/go.mod +++ b/go.mod @@ -67,7 +67,7 @@ require ( // pinned to pull in 386 arch fix: https://github.com/scylladb/go-set/commit/cc7b2070d91ebf40d233207b633e28f5bd8f03a5 github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 - github.com/spdx/tools-golang v0.5.4 + github.com/spdx/tools-golang v0.5.5 github.com/spf13/afero v1.11.0 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 diff --git a/go.sum b/go.sum index ccdec2d27..24b2ed4b9 100644 --- a/go.sum +++ b/go.sum @@ -726,8 +726,8 @@ github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9yS github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb/go.mod h1:uKWaldnbMnjsSAXRurWqqrdyZen1R7kxl8TkmWk2OyM= -github.com/spdx/tools-golang v0.5.4 h1:fRW4iz16P1ZCUtWStFqS6YiMgnK7WgfTFU/lrsYlvqY= -github.com/spdx/tools-golang v0.5.4/go.mod h1:MVIsXx8ZZzaRWNQpUDhC4Dud34edUYJYecciXgrw5vE= +github.com/spdx/tools-golang v0.5.5 h1:61c0KLfAcNqAjlg6UNMdkwpMernhw3zVRwDZ2x9XOmk= +github.com/spdx/tools-golang v0.5.5/go.mod h1:MVIsXx8ZZzaRWNQpUDhC4Dud34edUYJYecciXgrw5vE= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= From 5283c4687a3f5df6e518af3470480aa629ce07a5 Mon Sep 17 00:00:00 2001 From: Danielle Featherstone <99286933+4ell0@users.noreply.github.com> Date: Mon, 1 Jul 2024 14:27:37 -0400 Subject: [PATCH 062/284] feat: version 3 support for swift package manager of the resolved files (#3001) Signed-off-by: Danielle Featherstone --- .../cataloger/swift/parse_package_resolved.go | 2 +- .../swift/parse_package_resolved_test.go | 34 +++++++++++++++++++ .../swift/test-fixtures/PackageV3.resolved | 24 +++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 syft/pkg/cataloger/swift/test-fixtures/PackageV3.resolved diff --git a/syft/pkg/cataloger/swift/parse_package_resolved.go b/syft/pkg/cataloger/swift/parse_package_resolved.go index 71ccb13ea..cba7f54b3 100644 --- a/syft/pkg/cataloger/swift/parse_package_resolved.go +++ b/syft/pkg/cataloger/swift/parse_package_resolved.go @@ -121,7 +121,7 @@ func pinsForVersion(data map[string]interface{}, version float64) ([]packagePin, pin.State.Version, }) } - case 2: + case 2, 3: t := packageResolvedV2{} jsonString, err := json.Marshal(data) if err != nil { diff --git a/syft/pkg/cataloger/swift/parse_package_resolved_test.go b/syft/pkg/cataloger/swift/parse_package_resolved_test.go index 6cd77c2e5..499e705f6 100644 --- a/syft/pkg/cataloger/swift/parse_package_resolved_test.go +++ b/syft/pkg/cataloger/swift/parse_package_resolved_test.go @@ -80,6 +80,40 @@ func TestParsePackageResolved(t *testing.T) { pkgtest.TestFileParser(t, fixture, parsePackageResolved, expectedPkgs, expectedRelationships) } +func TestParsePackageResolvedV3(t *testing.T) { + fixture := "test-fixtures/PackageV3.resolved" + 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, + 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, + Metadata: pkg.SwiftPackageManagerResolvedEntry{ + Revision: "64889f0c732f210a935a0ad7cda38f77f876262d", + }, + }, + } + + // TODO: no relationships are under test yet + var expectedRelationships []artifact.Relationship + + pkgtest.TestFileParser(t, fixture, parsePackageResolved, expectedPkgs, expectedRelationships) +} + func TestParsePackageResolved_empty(t *testing.T) { // regression for https://github.com/anchore/syft/issues/2225 fixture := "test-fixtures/empty-packages.resolved" diff --git a/syft/pkg/cataloger/swift/test-fixtures/PackageV3.resolved b/syft/pkg/cataloger/swift/test-fixtures/PackageV3.resolved new file mode 100644 index 000000000..9b17d82d8 --- /dev/null +++ b/syft/pkg/cataloger/swift/test-fixtures/PackageV3.resolved @@ -0,0 +1,24 @@ +{ + "originHash" : "ea83017c944c7850b8f60207e6143eb17cb6b5e6b734b3fa08787a5d920dba7b", + "pins" : [ + { + "identity" : "swift-mmio", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-mmio", + "state" : { + "branch" : "swift-embedded-examples", + "revision" : "80c109b87511041338a4d8d88064088c8dfc079b" + } + }, + { + "identity" : "swift-syntax", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-syntax.git", + "state" : { + "revision" : "64889f0c732f210a935a0ad7cda38f77f876262d", + "version" : "509.1.1" + } + } + ], + "version" : 3 +} From 875669bfd102d532009b9bd545c5d0555a8428fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 19:00:07 +0000 Subject: [PATCH 063/284] chore(deps): bump github.com/saferwall/pe from 1.5.3 to 1.5.4 (#3005) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e2d633c4a..4e2ed85e6 100644 --- a/go.mod +++ b/go.mod @@ -60,7 +60,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 github.com/pelletier/go-toml v1.9.5 github.com/quasilyte/go-ruleguard/dsl v0.3.22 - github.com/saferwall/pe v1.5.3 + github.com/saferwall/pe v1.5.4 github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d github.com/sanity-io/litter v1.5.5 github.com/sassoftware/go-rpmutils v0.4.0 diff --git a/go.sum b/go.sum index 24b2ed4b9..75432cb73 100644 --- a/go.sum +++ b/go.sum @@ -684,8 +684,8 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/saferwall/pe v1.5.3 h1:tZ2KJWeJK6N2jjJx+B9hm+wq6qe0o56pql2PXUaQ9eI= -github.com/saferwall/pe v1.5.3/go.mod h1:mJx+PuptmNpoPFBNhWs/uDMFL/kTHVZIkg0d4OUJFbQ= +github.com/saferwall/pe v1.5.4 h1:tLmMggEMUfeqrpJ25zS/okUQmyFdD5xWKL2+z9njCqg= +github.com/saferwall/pe v1.5.4/go.mod h1:mJx+PuptmNpoPFBNhWs/uDMFL/kTHVZIkg0d4OUJFbQ= github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= From a876aaccb23ea9222c47d5e40697854395c090bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 19:00:35 +0000 Subject: [PATCH 064/284] chore(deps): bump github/codeql-action from 3.25.10 to 3.25.11 (#3004) --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 648198a6e..0d39a417c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@23acc5c183826b7a8a97bce3cecc52db901f8251 #v3.25.10 + uses: github/codeql-action/init@b611370bb5703a7efb587f9d136a52ea24c5c38c #v3.25.11 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@23acc5c183826b7a8a97bce3cecc52db901f8251 #v3.25.10 + uses: github/codeql-action/autobuild@b611370bb5703a7efb587f9d136a52ea24c5c38c #v3.25.11 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@23acc5c183826b7a8a97bce3cecc52db901f8251 #v3.25.10 + uses: github/codeql-action/analyze@b611370bb5703a7efb587f9d136a52ea24c5c38c #v3.25.11 From 43e5b1b45f0f914b884ec26484496451d15827c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 19:01:01 +0000 Subject: [PATCH 065/284] chore(deps): bump github.com/docker/docker (#3006) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4e2ed85e6..64e8468c0 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/dave/jennifer v1.7.0 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da github.com/distribution/reference v0.6.0 - github.com/docker/docker v27.0.1+incompatible + github.com/docker/docker v27.0.3+incompatible github.com/dustin/go-humanize v1.0.1 github.com/elliotchance/phpserialize v1.4.0 github.com/facebookincubator/nvdtools v0.1.5 diff --git a/go.sum b/go.sum index 75432cb73..3c4d5dfe9 100644 --- a/go.sum +++ b/go.sum @@ -231,8 +231,8 @@ github.com/docker/cli v26.1.4+incompatible h1:I8PHdc0MtxEADqYJZvhBrW9bo8gawKwwen github.com/docker/cli v26.1.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.0.1+incompatible h1:AbszR+lCnR3f297p/g0arbQoyhAkImxQOR/XO9YZeIg= -github.com/docker/docker v27.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= +github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= From 7f3ca65cf636d10d6096dbda3620a34faede723a Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 15:02:15 -0400 Subject: [PATCH 066/284] chore(deps): update CPE dictionary index (#3002) --- .../dictionary/data/cpe-index.json | 52 +++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index 0842a3ce1..605a9c248 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -64,6 +64,9 @@ "github.com/hamba/avro/v2": [ "cpe:2.3:a:avro_project:avro:*:*:*:*:*:go:*:*" ], + "github.com/hashicorp/go-retryablehttp": [ + "cpe:2.3:a:hashicorp:retryablehttp:*:*:*:*:*:go:*:*" + ], "github.com/jumpserver/koko/pkg/koko": [ "cpe:2.3:a:fit2cloud:koko:*:*:*:*:*:go:*:*" ], @@ -7969,7 +7972,8 @@ ], "better-wp-security": [ "cpe:2.3:a:ithemes:ithemes_security:*:*:*:*:*:wordpress:*:*", - "cpe:2.3:a:ithemes:security:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:ithemes:security:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:solidwp:solid_security:*:*:*:*:*:wordpress:*:*" ], "betterlinks": [ "cpe:2.3:a:wpdeveloper:betterlinks:*:*:*:*:*:wordpress:*:*" @@ -9130,6 +9134,9 @@ "crossslide-jquery-plugin-for-wordpress": [ "cpe:2.3:a:crossslide_jquery_project:crossslide_jquery:*:*:*:*:*:wordpress:*:*" ], + "cryout-serious-slider": [ + "cpe:2.3:a:cryoutcreations:serious_slider:*:*:*:*:*:wordpress:*:*" + ], "crypto-converter-widget": [ "cpe:2.3:a:currencyratetoday:crypto_converter_widget:*:*:*:*:*:wordpress:*:*" ], @@ -9440,10 +9447,11 @@ "cpe:2.3:a:deny_all_firewall_project:deny_all_firewall:*:*:*:*:*:wordpress:*:*" ], "depicter": [ - "cpe:2.3:a:averta:depicter_slider:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:averta:depicter_slider:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:depicter:depicter:*:*:*:*:*:wordpress:*:*" ], "dethemekit-for-elementor": [ - "cpe:2.3:a:dethemekit_for_elementor_project:dethemekit_for_elementor:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:detheme:dethemekit_for_elementor:*:*:*:*:*:wordpress:*:*" ], "diary-availability-calendar": [ "cpe:2.3:a:roosty:diary-availability-calendar:*:*:*:*:*:wordpress:*:*" @@ -9667,6 +9675,9 @@ "easy-accordion-free": [ "cpe:2.3:a:techearty:easy_accordion:*:*:*:*:*:wordpress:*:*" ], + "easy-age-verify": [ + "cpe:2.3:a:5starplugins:easy_age_verify:*:*:*:*:*:wordpress:*:*" + ], "easy-appointments": [ "cpe:2.3:a:easy_appointments_project:easy_appointments:*:*:*:*:*:wordpress:*:*" ], @@ -10544,6 +10555,9 @@ "forms-for-campaign-monitor": [ "cpe:2.3:a:campaignmonitor:campaign_monitor:*:*:*:*:*:wordpress:*:*" ], + "forms-gutenberg": [ + "cpe:2.3:a:gutenbergforms:gutenberg_forms:*:*:*:*:*:wordpress:*:*" + ], "formzu-wp": [ "cpe:2.3:a:formzu:formzu_wp:*:*:*:*:*:wordpress:*:*" ], @@ -14261,6 +14275,9 @@ "search-analytics": [ "cpe:2.3:a:cornelraiu:wp_search_analytics:*:*:*:*:*:wordpress:*:*" ], + "search-and-replace": [ + "cpe:2.3:a:wp-media:search_\\\u0026_replace:*:*:*:*:*:wordpress:*:*" + ], "search-everything": [ "cpe:2.3:a:search_everything_project:search_everything:*:*:*:*:*:wordpress:*:*" ], @@ -15310,6 +15327,9 @@ "tabbed": [ "cpe:2.3:a:rich-web:tab:*:*:*:*:*:wordpress:*:*" ], + "table-addons-for-elementor": [ + "cpe:2.3:a:fusionplugin:table_addons_for_elementor:*:*:*:*:*:wordpress:*:*" + ], "table-of-contents-plus": [ "cpe:2.3:a:dublue:table_of_contents_plus:*:*:*:*:*:wordpress:*:*" ], @@ -15495,6 +15515,7 @@ "cpe:2.3:a:themify:portfolio_post:*:*:*:*:*:wordpress:*:*" ], "themify-wc-product-filter": [ + "cpe:2.3:a:themify:product_filter:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:themify:woocommerce_product_filter:*:*:*:*:*:wordpress:*:*" ], "thesography": [ @@ -15684,6 +15705,9 @@ "typebot": [ "cpe:2.3:a:typebot:typebot:*:*:*:*:*:wordpress:*:*" ], + "typing-text": [ + "cpe:2.3:a:wpdeveloper:typing_text:*:*:*:*:*:wordpress:*:*" + ], "typofr": [ "cpe:2.3:a:typofr_project:typofr:*:*:*:*:*:wordpress:*:*" ], @@ -16027,6 +16051,9 @@ "vikrentcar": [ "cpe:2.3:a:e4jconnect:vikrentcar:*:*:*:*:*:wordpress:*:*" ], + "vimeography": [ + "cpe:2.3:a:davekiss:vimeography:*:*:*:*:*:wordpress:*:*" + ], "vision": [ "cpe:2.3:a:vision_interactive_project:vision_interactive:*:*:*:*:*:wordpress:*:*" ], @@ -18052,6 +18079,7 @@ "cpe:2.3:a:wpstream:wpstream:*:*:*:*:*:wordpress:*:*" ], "wptools": [ + "cpe:2.3:a:billminozzi:wp_tools:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:wptools_project:wptools:*:*:*:*:*:wordpress:*:*" ], "wptouch": [ @@ -18367,6 +18395,9 @@ "bonkers": [ "cpe:2.3:a:colorlib:bonkers:*:*:*:*:*:wordpress:*:*" ], + "book-landing-page": [ + "cpe:2.3:a:rarathemes:book_landing_page:*:*:*:*:*:wordpress:*:*" + ], "brilliance": [ "cpe:2.3:a:cpothemes:brilliance:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:wpchill:brilliance:*:*:*:*:*:wordpress:*:*" @@ -18389,6 +18420,9 @@ "darcie": [ "cpe:2.3:a:catchthemes:darcie:*:*:*:*:*:wordpress:*:*" ], + "digital-newspaper": [ + "cpe:2.3:a:blazethemes:digital_newspaper:*:*:*:*:*:wordpress:*:*" + ], "digitally": [ "cpe:2.3:a:omarfolgheraiter:digitally:*:*:*:*:*:wordpress:*:*" ], @@ -18407,6 +18441,9 @@ "everest-news": [ "cpe:2.3:a:everestthemes:everest_news:*:*:*:*:*:wordpress:*:*" ], + "excellent": [ + "cpe:2.3:a:themefreesia:excellent:*:*:*:*:*:wordpress:*:*" + ], "flashy": [ "cpe:2.3:a:flashy_project:flashy:*:*:*:*:*:wordpress:*:*" ], @@ -18423,12 +18460,18 @@ "cpe:2.3:a:generatepress:generatepress:*:*:*:*:-:wordpress:*:*", "cpe:2.3:a:generatepress:generatepress:*:*:*:*:premium:wordpress:*:*" ], + "grey-opaque": [ + "cpe:2.3:a:grey_opaque_project:grey_opaque:*:*:*:*:*:wordpress:*:*" + ], "hueman": [ "cpe:2.3:a:presscustomizr:hueman:*:*:*:*:*:wordpress:*:*" ], "illdy": [ "cpe:2.3:a:colorlib:illdy:*:*:*:*:*:wordpress:*:*" ], + "interface": [ + "cpe:2.3:a:themehorse:interface:*:*:*:*:*:wordpress:*:*" + ], "kata": [ "cpe:2.3:a:climaxthemes:kata:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:climaxthemes:kata_apps:*:*:*:*:*:wordpress:*:*", @@ -18449,6 +18492,9 @@ "morning-coffee": [ "cpe:2.3:a:adazing:morning_coffee:*:*:*:*:*:wordpress:*:*" ], + "mosaic": [ + "cpe:2.3:a:wildweblab:mosaic:*:*:*:*:*:wordpress:*:*" + ], "newsmag": [ "cpe:2.3:a:machothemes:newsmag:*:*:*:*:*:wordpress:*:*" ], From c816039e91b46ae475207db01c8eac9fbc139c02 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 20:04:45 -0400 Subject: [PATCH 067/284] chore(deps): update tools to latest versions (#3003) --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index e544efb7f..fc2bc32ad 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -103,7 +103,7 @@ tools: # used for running all local and CI tasks - name: task version: - want: v3.37.2 + want: v3.38.0 method: github-release with: repo: go-task/task From 573440b7cf82cc1f21fdeec0da5d744d6b110db5 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Tue, 2 Jul 2024 16:07:08 -0400 Subject: [PATCH 068/284] Infer the package type from ELF package notes (#3008) * fix ELF package types to be honored Signed-off-by: Alex Goodman * prefer OS packages over binary packages when there are duplicates Signed-off-by: Alex Goodman --------- Signed-off-by: Alex Goodman --- .../integration/mariner_distroless_test.go | 3 ++- ...lude_binaries_by_file_ownership_overlap.go | 17 ++++++++++++- ...binaries_by_file_ownership_overlap_test.go | 24 ++++++++++++++++++- syft/pkg/cataloger/binary/elf_package.go | 22 ++++++++++++++--- .../binary/elf_package_cataloger_test.go | 4 ++-- 5 files changed, 62 insertions(+), 8 deletions(-) diff --git a/cmd/syft/internal/test/integration/mariner_distroless_test.go b/cmd/syft/internal/test/integration/mariner_distroless_test.go index 5231f3254..f45098aff 100644 --- a/cmd/syft/internal/test/integration/mariner_distroless_test.go +++ b/cmd/syft/internal/test/integration/mariner_distroless_test.go @@ -10,7 +10,8 @@ import ( func TestMarinerDistroless(t *testing.T) { sbom, _ := catalogFixtureImage(t, "image-mariner-distroless", source.SquashedScope) - expectedPkgs := 12 + // 12 RPMs + 2 binaries with ELF package notes claiming to be RPMs + expectedPkgs := 14 actualPkgs := 0 for range sbom.Artifacts.Packages.Enumerate(pkg.RpmPkg) { actualPkgs += 1 diff --git a/internal/relationship/exclude_binaries_by_file_ownership_overlap.go b/internal/relationship/exclude_binaries_by_file_ownership_overlap.go index 03e2d7fbc..9733c00e7 100644 --- a/internal/relationship/exclude_binaries_by_file_ownership_overlap.go +++ b/internal/relationship/exclude_binaries_by_file_ownership_overlap.go @@ -1,6 +1,7 @@ package relationship import ( + "reflect" "slices" "github.com/anchore/syft/internal/sbomsync" @@ -21,6 +22,10 @@ var ( binaryCatalogerTypes = []pkg.Type{ pkg.BinaryPkg, } + binaryMetadataTypes = []string{ + reflect.TypeOf(pkg.ELFBinaryPackageNoteJSONPayload{}).Name(), + reflect.TypeOf(pkg.BinarySignature{}).Name(), + } ) func ExcludeBinariesByFileOwnershipOverlap(accessor sbomsync.Accessor) { @@ -60,5 +65,15 @@ func excludeBinaryByFileOwnershipOverlap(r artifact.Relationship, c *pkg.Collect return false } - return slices.Contains(binaryCatalogerTypes, child.Type) + if slices.Contains(binaryCatalogerTypes, child.Type) { + return true + } + + if child.Metadata == nil { + return false + } + + childMetadataType := reflect.TypeOf(child.Metadata) + + return slices.Contains(binaryMetadataTypes, childMetadataType.Name()) } diff --git a/internal/relationship/exclude_binaries_by_file_ownership_overlap_test.go b/internal/relationship/exclude_binaries_by_file_ownership_overlap_test.go index 6074e0c16..e8347937b 100644 --- a/internal/relationship/exclude_binaries_by_file_ownership_overlap_test.go +++ b/internal/relationship/exclude_binaries_by_file_ownership_overlap_test.go @@ -12,7 +12,9 @@ func TestExclude(t *testing.T) { packageB := pkg.Package{Name: "package-a", Type: pkg.PythonPkg} packageC := pkg.Package{Name: "package-a", Type: pkg.BinaryPkg} packageD := pkg.Package{Name: "package-d", Type: pkg.BinaryPkg} - for _, p := range []*pkg.Package{&packageA, &packageB, &packageC, &packageD} { + packageE := pkg.Package{Name: "package-e", Type: pkg.RpmPkg, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{Type: "rpm"}} + packageF := pkg.Package{Name: "package-f", Type: pkg.RpmPkg, Metadata: pkg.BinarySignature{}} + for _, p := range []*pkg.Package{&packageA, &packageB, &packageC, &packageD, &packageE, &packageF} { p := p p.SetID() } @@ -43,6 +45,26 @@ func TestExclude(t *testing.T) { packages: pkg.NewCollection(packageA, packageC), shouldExclude: true, }, + { + name: "exclusions from os -> elf binary (as RPM)", + relationship: artifact.Relationship{ + Type: artifact.OwnershipByFileOverlapRelationship, + From: packageA, + To: packageE, + }, + packages: pkg.NewCollection(packageA, packageE), + shouldExclude: true, + }, + { + name: "exclusions from os -> binary (masquerading as RPM)", + relationship: artifact.Relationship{ + Type: artifact.OwnershipByFileOverlapRelationship, + From: packageA, + To: packageF, + }, + packages: pkg.NewCollection(packageA, packageF), + shouldExclude: true, + }, { name: "no exclusions from python -> binary", relationship: artifact.Relationship{ diff --git a/syft/pkg/cataloger/binary/elf_package.go b/syft/pkg/cataloger/binary/elf_package.go index e24853942..9b13647a3 100644 --- a/syft/pkg/cataloger/binary/elf_package.go +++ b/syft/pkg/cataloger/binary/elf_package.go @@ -13,7 +13,7 @@ func newELFPackage(metadata elfBinaryPackageNotes, locations file.LocationSet) p Version: metadata.Version, Licenses: pkg.NewLicenseSet(pkg.NewLicense(metadata.License)), PURL: packageURL(metadata), - Type: pkg.BinaryPkg, + Type: pkgType(metadata.Type), Locations: locations, Metadata: metadata.ELFBinaryPackageNoteJSONPayload, } @@ -67,6 +67,8 @@ func packageURL(metadata elfBinaryPackageNotes) string { ).ToString() } +const alpmType = "alpm" + func purlDistroType(ty string) string { switch ty { case "rpm": @@ -75,8 +77,22 @@ func purlDistroType(ty string) string { return packageurl.TypeDebian case "apk": return packageurl.TypeAlpine - case "alpm": - return "alpm" + case alpmType: + return alpmType } return packageurl.TypeGeneric } + +func pkgType(ty string) pkg.Type { + switch ty { + case "rpm": + return pkg.RpmPkg + case "deb": + return pkg.DebPkg + case "apk": + return pkg.ApkPkg + case alpmType: + return pkg.AlpmPkg + } + return pkg.BinaryPkg +} diff --git a/syft/pkg/cataloger/binary/elf_package_cataloger_test.go b/syft/pkg/cataloger/binary/elf_package_cataloger_test.go index f3569e5f4..4ec6bd61f 100644 --- a/syft/pkg/cataloger/binary/elf_package_cataloger_test.go +++ b/syft/pkg/cataloger/binary/elf_package_cataloger_test.go @@ -77,7 +77,7 @@ func Test_ELF_Package_Cataloger(t *testing.T) { file.NewLocation("/sha1sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), Licenses: pkg.NewLicenseSet(), - Type: pkg.BinaryPkg, + Type: pkg.RpmPkg, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ Type: "rpm", Architecture: "x86_64", @@ -99,7 +99,7 @@ func Test_ELF_Package_Cataloger(t *testing.T) { file.NewLocation("/sha1sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), Licenses: pkg.NewLicenseSet(), - Type: pkg.BinaryPkg, + Type: pkg.RpmPkg, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ Type: "rpm", Architecture: "arm", From 04c861bf777d58f209ab105f41856d054fbab411 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 8 Jul 2024 08:13:17 -0400 Subject: [PATCH 069/284] chore(deps): update CPE dictionary index (#3016) --- .../dictionary/data/cpe-index.json | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index 605a9c248..37cdae870 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -7437,6 +7437,9 @@ "alfred-click-collect": [ "cpe:2.3:a:alfred24_click_\\\u0026_collect_project:alfred24_click_\\\u0026_collect:*:*:*:*:*:wordpress:*:*" ], + "ali2woo-lite": [ + "cpe:2.3:a:ali2woo:ali2woo:*:*:*:*:lite:wordpress:*:*" + ], "alipay": [ "cpe:2.3:a:alipay_project:alipay:*:*:*:*:*:wordpress:*:*" ], @@ -9040,6 +9043,9 @@ "coru-lfmember": [ "cpe:2.3:a:marcorulicke:coru_lfmember:*:*:*:*:*:wordpress:*:*" ], + "cost-calculator-builder": [ + "cpe:2.3:a:stylemixthemes:cost_calculator_builder:*:*:*:*:*:wordpress:*:*" + ], "countdown-block": [ "cpe:2.3:a:wpdeveloper:countdown_block:*:*:*:*:*:wordpress:*:*" ], @@ -11052,6 +11058,9 @@ "gwyns-imagemap-selector": [ "cpe:2.3:a:gwyn\\'s_imagemap_selector_project:gwyn\\'s_imagemap_selector:*:*:*:*:*:wordpress:*:*" ], + "h5p": [ + "cpe:2.3:a:h5p:h5p:*:*:*:*:*:wordpress:*:*" + ], "hal": [ "cpe:2.3:a:cnrs:hal:*:*:*:*:*:wordpress:*:*" ], @@ -11704,6 +11713,9 @@ "jvm-rich-text-icons": [ "cpe:2.3:a:jorisvm:jvm_gutenberg_rich_text_icons:*:*:*:*:*:wordpress:*:*" ], + "kadence-blocks": [ + "cpe:2.3:a:kadencewp:gutenberg_blocks_with_ai:*:*:*:*:*:wordpress:*:*" + ], "kadence-starter-templates": [ "cpe:2.3:a:kadencewp:starter_templates:*:*:*:*:*:wordpress:*:*" ], @@ -12287,6 +12299,9 @@ "mediavine-control-panel": [ "cpe:2.3:a:mediavine:mediavine_control_panel:*:*:*:*:*:wordpress:*:*" ], + "mediavine-create": [ + "cpe:2.3:a:mediavine:create:*:*:*:*:*:wordpress:*:*" + ], "meeting-scheduler-by-vcita": [ "cpe:2.3:a:vcita:online_booking_\\\u0026_scheduling_calendar_for_wordpress:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:vcita:online_booking_\\\u0026_scheduling_calendar_for_wordpress_by_vcita:*:*:*:*:*:wordpress:*:*" @@ -15747,6 +15762,9 @@ "ultimate-author-box-lite": [ "cpe:2.3:a:accesspressthemes:ultimate_author_box_lite:*:*:*:*:*:wordpress:*:*" ], + "ultimate-blocks": [ + "cpe:2.3:a:dotcamp:ultimate_blocks:*:*:*:*:*:wordpress:*:*" + ], "ultimate-carousel-for-elementor": [ "cpe:2.3:a:topdigitaltrends:ultimate_carousel_for_elementor:*:*:*:*:*:wordpress:*:*" ], @@ -16867,6 +16885,9 @@ "wp-chgfontsize": [ "cpe:2.3:a:wp-chgfontsize_project:wp-chgfontsize:*:*:*:*:*:wordpress:*:*" ], + "wp-child-theme-generator": [ + "cpe:2.3:a:wensolutions:wp_child_theme_generator:*:*:*:*:*:wordpress:*:*" + ], "wp-cirrus": [ "cpe:2.3:a:wp-cirrus_project:wp-cirrus:*:*:*:*:*:wordpress:*:*" ], @@ -17216,6 +17237,9 @@ "wp-hide": [ "cpe:2.3:a:weberge:wp_hide:*:*:*:*:*:wordpress:*:*" ], + "wp-hide-backed-notices": [ + "cpe:2.3:a:wprepublic:hide_dashboard_notifications:*:*:*:*:*:wordpress:*:*" + ], "wp-hide-pages": [ "cpe:2.3:a:nxsn:wp_hide_pages:*:*:*:*:*:wordpress:*:*" ], @@ -17892,6 +17916,9 @@ "wp-voting-contest": [ "cpe:2.3:a:ohiowebtech:wp_voting_contest:*:*:*:*:*:wordpress:*:*" ], + "wp-whatsapp": [ + "cpe:2.3:a:ninjateam:wp_chat_app:*:*:*:*:*:wordpress:*:*" + ], "wp-whatsapp-chat": [ "cpe:2.3:a:quadlayers:wp_social_chat:*:*:*:*:*:wordpress:*:*" ], @@ -18097,6 +18124,9 @@ "wpvr": [ "cpe:2.3:a:coderex:wp_vr:*:*:*:*:*:wordpress:*:*" ], + "wpzoom-elementor-addons": [ + "cpe:2.3:a:wpzoom:wpzoom_elementor_addons:*:*:*:*:*:wordpress:*:*" + ], "wpzoom-portfolio": [ "cpe:2.3:a:wpzoom:wpzoom_portfolio:*:*:*:*:*:wordpress:*:*" ], From 6dda9edd7c809faf3225335bbddfef1c075ca66c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 07:07:53 -0700 Subject: [PATCH 070/284] chore(deps): bump github.com/adrg/xdg from 0.4.0 to 0.5.0 (#3020) Bumps [github.com/adrg/xdg](https://github.com/adrg/xdg) from 0.4.0 to 0.5.0. - [Release notes](https://github.com/adrg/xdg/releases) - [Commits](https://github.com/adrg/xdg/compare/v0.4.0...v0.5.0) --- updated-dependencies: - dependency-name: github.com/adrg/xdg dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 64e8468c0..a8aa04dce 100644 --- a/go.mod +++ b/go.mod @@ -88,7 +88,7 @@ require google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirec require ( github.com/BurntSushi/toml v1.4.0 - github.com/adrg/xdg v0.4.0 + github.com/adrg/xdg v0.5.0 github.com/magiconair/properties v1.8.7 ) @@ -232,7 +232,7 @@ require ( golang.org/x/crypto v0.24.0 // indirect golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.22.0 // indirect golang.org/x/term v0.21.0 // indirect golang.org/x/text v0.16.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect diff --git a/go.sum b/go.sum index 3c4d5dfe9..0f95cc29b 100644 --- a/go.sum +++ b/go.sum @@ -85,8 +85,8 @@ github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpH github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/acobaugh/osrelease v0.1.0 h1:Yb59HQDGGNhCj4suHaFQQfBps5wyoKLSSX/J/+UifRE= github.com/acobaugh/osrelease v0.1.0/go.mod h1:4bFEs0MtgHNHBrmHCt67gNisnabCRAlzdVasCEGHTWY= -github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= -github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= +github.com/adrg/xdg v0.5.0 h1:dDaZvhMXatArP1NPHhnfaQUqWBLBsmx1h1HXQdMoFCY= +github.com/adrg/xdg v0.5.0/go.mod h1:dDdY4M4DF9Rjy4kHPeNL+ilVF+p2lK8IdM9/rTSGcI4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -1081,8 +1081,8 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= From b8dce675feaf6b91a127ed02db709730f30284e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 07:08:02 -0700 Subject: [PATCH 071/284] chore(deps): bump github.com/google/go-containerregistry (#3019) Bumps [github.com/google/go-containerregistry](https://github.com/google/go-containerregistry) from 0.19.2 to 0.20.0. - [Release notes](https://github.com/google/go-containerregistry/releases) - [Changelog](https://github.com/google/go-containerregistry/blob/main/.goreleaser.yml) - [Commits](https://github.com/google/go-containerregistry/compare/v0.19.2...v0.20.0) --- updated-dependencies: - dependency-name: github.com/google/go-containerregistry dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a8aa04dce..76077db97 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/go-git/go-git/v5 v5.12.0 github.com/go-test/deep v1.1.1 github.com/google/go-cmp v0.6.0 - github.com/google/go-containerregistry v0.19.2 + github.com/google/go-containerregistry v0.20.0 github.com/google/licensecheck v0.3.1 github.com/google/uuid v1.6.0 github.com/gookit/color v1.5.4 diff --git a/go.sum b/go.sum index 0f95cc29b..566f81c74 100644 --- a/go.sum +++ b/go.sum @@ -384,8 +384,8 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.19.2 h1:TannFKE1QSajsP6hPWb5oJNgKe1IKjHukIKDUmvsV6w= -github.com/google/go-containerregistry v0.19.2/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI= +github.com/google/go-containerregistry v0.20.0 h1:wRqHpOeVh3DnenOrPy9xDOLdnLatiGuuNRVelR2gSbg= +github.com/google/go-containerregistry v0.20.0/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/licensecheck v0.3.1 h1:QoxgoDkaeC4nFrtGN1jV7IPmDCHFNIVh54e5hSt6sPs= github.com/google/licensecheck v0.3.1/go.mod h1:ORkR35t/JjW+emNKtfJDII0zlciG9JgbT7SmsohlHmY= From 7dc1b1ce277624ba4153aeca7b0a977d4e0a2acb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 07:08:12 -0700 Subject: [PATCH 072/284] chore(deps): bump actions/upload-artifact from 4.3.3 to 4.3.4 (#3017) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.3 to 4.3.4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/65462800fd760344b1a7b4382951275a0abb4808...0b2256b8c012f0828dc542b3febcab082c67f72b) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/benchmark-testing.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/benchmark-testing.yaml b/.github/workflows/benchmark-testing.yaml index c23197c83..7cdf9b4b8 100644 --- a/.github/workflows/benchmark-testing.yaml +++ b/.github/workflows/benchmark-testing.yaml @@ -39,7 +39,7 @@ jobs: OUTPUT="${OUTPUT//$'\r'/'%0D'}" # URL encode all '\r' characters echo "result=$OUTPUT" >> $GITHUB_OUTPUT - - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + - uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 with: name: benchmark-test-results path: test/results/**/* From 13d01ecaff0aae22f3a5bf6f922a0be4ae7c4d06 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 07:08:25 -0700 Subject: [PATCH 073/284] chore(deps): bump golang.org/x/mod from 0.18.0 to 0.19.0 (#3014) Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.18.0 to 0.19.0. - [Commits](https://github.com/golang/mod/compare/v0.18.0...v0.19.0) --- updated-dependencies: - dependency-name: golang.org/x/mod dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 76077db97..385a53502 100644 --- a/go.mod +++ b/go.mod @@ -78,7 +78,7 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1 go.uber.org/goleak v1.3.0 - golang.org/x/mod v0.18.0 + golang.org/x/mod v0.19.0 golang.org/x/net v0.26.0 gopkg.in/yaml.v3 v3.0.1 modernc.org/sqlite v1.30.1 diff --git a/go.sum b/go.sum index 566f81c74..3a4761268 100644 --- a/go.sum +++ b/go.sum @@ -919,8 +919,8 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= From b2f9904d745fb48ac7d6b7996d1adac4adacb30e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 07:52:32 -0700 Subject: [PATCH 074/284] chore(deps): bump golang.org/x/net from 0.26.0 to 0.27.0 (#3015) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.26.0 to 0.27.0. - [Commits](https://github.com/golang/net/compare/v0.26.0...v0.27.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 385a53502..c223fa034 100644 --- a/go.mod +++ b/go.mod @@ -79,7 +79,7 @@ require ( github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1 go.uber.org/goleak v1.3.0 golang.org/x/mod v0.19.0 - golang.org/x/net v0.26.0 + golang.org/x/net v0.27.0 gopkg.in/yaml.v3 v3.0.1 modernc.org/sqlite v1.30.1 ) @@ -229,11 +229,11 @@ require ( go.opentelemetry.io/otel/trace v1.19.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.25.0 // indirect golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.22.0 // indirect - golang.org/x/term v0.21.0 // indirect + golang.org/x/term v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect diff --git a/go.sum b/go.sum index 3a4761268..58462424b 100644 --- a/go.sum +++ b/go.sum @@ -877,8 +877,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -968,8 +968,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1088,8 +1088,8 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From de3313cfb60f952d87c356ef31e8d90376ceec93 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 07:53:04 -0700 Subject: [PATCH 075/284] chore(deps): update stereoscope to e46739e217969fa67cbe8834b64bb165a10a1548 (#3013) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: kzantow <3009477+kzantow@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index c223fa034..7817206cc 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f - github.com/anchore/stereoscope v0.0.3-0.20240624202600-753b5576fe42 + github.com/anchore/stereoscope v0.0.3-0.20240705165118-e46739e21796 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // we are hinting brotli to latest due to warning when installing archiver v3: // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption @@ -124,7 +124,7 @@ require ( github.com/containerd/typeurl/v2 v2.1.1 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/docker/cli v26.1.4+incompatible // indirect + github.com/docker/cli v27.0.3+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-connections v0.4.0 // indirect @@ -182,7 +182,7 @@ require ( github.com/muesli/termenv v0.15.2 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect github.com/nwaples/rardecode v1.1.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc3 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opencontainers/runc v1.1.12 // indirect github.com/opencontainers/runtime-spec v1.1.0-rc.1 // indirect github.com/opencontainers/selinux v1.11.0 // indirect @@ -208,7 +208,7 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.18.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/sylabs/sif/v2 v2.11.5 // indirect + github.com/sylabs/sif/v2 v2.17.1 // indirect github.com/sylabs/squashfs v0.6.1 // indirect github.com/therootcompany/xz v1.0.1 // indirect github.com/tidwall/gjson v1.17.0 // indirect diff --git a/go.sum b/go.sum index 58462424b..a5e50ecb7 100644 --- a/go.sum +++ b/go.sum @@ -113,8 +113,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f h1:B/E9ixKNCasntpoch61NDaQyGPDXLEJlL+B9B/PbdbA= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.3-0.20240624202600-753b5576fe42 h1:9rQYUxTHfGuX6ZyzSAG4vv0uG3SjoW1M5uRtGgO92Oc= -github.com/anchore/stereoscope v0.0.3-0.20240624202600-753b5576fe42/go.mod h1:sChrYoP82PZDg1V+7O4f8a2XyFkED7FReZsHmwCmSLc= +github.com/anchore/stereoscope v0.0.3-0.20240705165118-e46739e21796 h1:mb2i23zBKaSloS4RHMwBCKTCB3X5HnObcRvjxrvvMr8= +github.com/anchore/stereoscope v0.0.3-0.20240705165118-e46739e21796/go.mod h1:6r8piaIGsYZuVkFw+fAXYtEGFI58dZuni/jNdvK+IxQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= @@ -227,8 +227,8 @@ github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da/go.mod h1:B3tI9iGHi4i github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/cli v26.1.4+incompatible h1:I8PHdc0MtxEADqYJZvhBrW9bo8gawKwwenxRM7/rLu8= -github.com/docker/cli v26.1.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v27.0.3+incompatible h1:usGs0/BoBW8MWxGeEtqPMkzOY56jZ6kYlSN5BLDioCQ= +github.com/docker/cli v27.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= @@ -617,8 +617,8 @@ github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8= -github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= github.com/opencontainers/runtime-spec v1.1.0-rc.1 h1:wHa9jroFfKGQqFHj0I1fMRKLl0pfj+ynAqBxo3v6u9w= @@ -768,8 +768,8 @@ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/sylabs/sif/v2 v2.11.5 h1:7ssPH3epSonsTrzbS1YxeJ9KuqAN7ISlSM61a7j/mQM= -github.com/sylabs/sif/v2 v2.11.5/go.mod h1:GBoZs9LU3e4yJH1dcZ3Akf/jsqYgy5SeguJQC+zd75Y= +github.com/sylabs/sif/v2 v2.17.1 h1:p6Sl0LWyShXBj2SBsS1dMOMIMrZHe8pwBnBrYt6uo4M= +github.com/sylabs/sif/v2 v2.17.1/go.mod h1:XUGB6AQUXGkms3qPOPdevctT3lBLRLWZNWHVnt5HMKE= github.com/sylabs/squashfs v0.6.1 h1:4hgvHnD9JGlYWwT0bPYNt9zaz23mAV3Js+VEgQoRGYQ= github.com/sylabs/squashfs v0.6.1/go.mod h1:ZwpbPCj0ocIvMy2br6KZmix6Gzh6fsGQcCnydMF+Kx8= github.com/terminalstatic/go-xsd-validate v0.1.5 h1:RqpJnf6HGE2CB/lZB1A8BYguk8uRtcvYAPLCF15qguo= From b101f44aba03b1fa301f0d58056d854f26b86d97 Mon Sep 17 00:00:00 2001 From: Laurent Goderre Date: Tue, 9 Jul 2024 12:01:58 -0400 Subject: [PATCH 076/284] Map the downloadLocation field for PHP Composer packages (#3011) Signed-off-by: Laurent Goderre --- .../spdxutil/helpers/download_location.go | 4 ++ .../helpers/download_location_test.go | 44 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/syft/format/internal/spdxutil/helpers/download_location.go b/syft/format/internal/spdxutil/helpers/download_location.go index 894306dea..3ed1c9ed6 100644 --- a/syft/format/internal/spdxutil/helpers/download_location.go +++ b/syft/format/internal/spdxutil/helpers/download_location.go @@ -22,6 +22,10 @@ func DownloadLocation(p pkg.Package) string { return NoneIfEmpty(metadata.URL) case pkg.NpmPackageLockEntry: return NoneIfEmpty(metadata.Resolved) + case pkg.PhpComposerLockEntry: + return NoneIfEmpty(metadata.Dist.URL) + case pkg.PhpComposerInstalledEntry: + return NoneIfEmpty(metadata.Dist.URL) } } return NOASSERTION diff --git a/syft/format/internal/spdxutil/helpers/download_location_test.go b/syft/format/internal/spdxutil/helpers/download_location_test.go index 7ccbed44c..2cbbaa30e 100644 --- a/syft/format/internal/spdxutil/helpers/download_location_test.go +++ b/syft/format/internal/spdxutil/helpers/download_location_test.go @@ -64,6 +64,50 @@ func Test_DownloadLocation(t *testing.T) { }, expected: NONE, }, + { + name: "from php installed.json", + input: pkg.Package{ + Metadata: pkg.PhpComposerInstalledEntry{ + Dist: pkg.PhpComposerExternalReference{ + URL: "http://package-lock.test", + }, + }, + }, + expected: "http://package-lock.test", + }, + { + name: "empty", + input: pkg.Package{ + Metadata: pkg.PhpComposerInstalledEntry{ + Dist: pkg.PhpComposerExternalReference{ + URL: "", + }, + }, + }, + expected: "NONE", + }, + { + name: "from php composer.lock", + input: pkg.Package{ + Metadata: pkg.PhpComposerLockEntry{ + Dist: pkg.PhpComposerExternalReference{ + URL: "http://package-lock.test", + }, + }, + }, + expected: "http://package-lock.test", + }, + { + name: "empty", + input: pkg.Package{ + Metadata: pkg.PhpComposerLockEntry{ + Dist: pkg.PhpComposerExternalReference{ + URL: "", + }, + }, + }, + expected: "NONE", + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { From f7ffcc534fd44e304527dfd34c6e0b372310456a Mon Sep 17 00:00:00 2001 From: Christopher Angelo Phillips <32073428+spiffcs@users.noreply.github.com> Date: Tue, 9 Jul 2024 14:24:21 -0400 Subject: [PATCH 077/284] fix: stabilize cpe sorting during collection sort (#3009) --- syft/cpe/by_source_then_specificity_test.go | 22 +++++++++++++++++++ .../internal/cpegenerate/generate.go | 3 ++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/syft/cpe/by_source_then_specificity_test.go b/syft/cpe/by_source_then_specificity_test.go index 9687447f9..7d62bba4b 100644 --- a/syft/cpe/by_source_then_specificity_test.go +++ b/syft/cpe/by_source_then_specificity_test.go @@ -64,6 +64,28 @@ func TestBySourceThenSpecificity(t *testing.T) { Must("cpe:2.3:a:some:package:*:*:*:*:*:*:*:*", "some-unknown-source"), }, }, + { + name: "lexical sorting on equal sources puts escaped characters later", + input: []CPE{ + Must("cpe:2.3:a:jenkins:pipeline\\\\:_supporting_apis:865.v43e78cc44e0d:*:*:*:*:jenkins:*:*", "nvd-cpe-dictionary"), + Must("cpe:2.3:a:jenkins:pipeline_supporting_apis:865.v43e78cc44e0d:*:*:*:*:jenkins:*:*", "nvd-cpe-dictionary"), + }, + want: []CPE{ + Must("cpe:2.3:a:jenkins:pipeline_supporting_apis:865.v43e78cc44e0d:*:*:*:*:jenkins:*:*", "nvd-cpe-dictionary"), + Must("cpe:2.3:a:jenkins:pipeline\\\\:_supporting_apis:865.v43e78cc44e0d:*:*:*:*:jenkins:*:*", "nvd-cpe-dictionary"), + }, + }, + { + name: "lexical sorting on equal sources puts more specific attributes earlier", + input: []CPE{ + Must("cpe:2.3:a:jenkins:mailer:472.vf7c289a_4b_420:*:*:*:*:*:*:*", "nvd-cpe-dictionary"), + Must("cpe:2.3:a:jenkins:mailer:472.vf7c289a_4b_420:*:*:*:*:jenkins:*:*", "nvd-cpe-dictionary"), + }, + want: []CPE{ + Must("cpe:2.3:a:jenkins:mailer:472.vf7c289a_4b_420:*:*:*:*:jenkins:*:*", "nvd-cpe-dictionary"), + Must("cpe:2.3:a:jenkins:mailer:472.vf7c289a_4b_420:*:*:*:*:*:*:*", "nvd-cpe-dictionary"), + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/syft/pkg/cataloger/internal/cpegenerate/generate.go b/syft/pkg/cataloger/internal/cpegenerate/generate.go index 174076460..ef8701657 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/generate.go +++ b/syft/pkg/cataloger/internal/cpegenerate/generate.go @@ -127,6 +127,7 @@ func FromDictionaryFind(p pkg.Package) ([]cpe.CPE, bool) { return []cpe.CPE{}, false } + sort.Sort(cpe.BySourceThenSpecificity(parsedCPEs)) return parsedCPEs, true } @@ -163,12 +164,12 @@ func FromPackageAttributes(p pkg.Package) []cpe.CPE { // filter out any known combinations that don't accurately represent this package cpes = filter(cpes, p, cpeFilters...) - sort.Sort(cpe.BySpecificity(cpes)) var result []cpe.CPE for _, c := range cpes { result = append(result, cpe.CPE{Attributes: c, Source: cpe.GeneratedSource}) } + sort.Sort(cpe.BySourceThenSpecificity(result)) return result } From 863793a3ccd71c8c009f9a11e97e207173584b2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Jul 2024 10:19:14 -0700 Subject: [PATCH 078/284] chore(deps): bump github.com/charmbracelet/lipgloss (#3028) Bumps [github.com/charmbracelet/lipgloss](https://github.com/charmbracelet/lipgloss) from 0.11.0 to 0.11.1. - [Release notes](https://github.com/charmbracelet/lipgloss/releases) - [Changelog](https://github.com/charmbracelet/lipgloss/blob/master/.goreleaser.yml) - [Commits](https://github.com/charmbracelet/lipgloss/compare/v0.11.0...v0.11.1) --- updated-dependencies: - dependency-name: github.com/charmbracelet/lipgloss dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 7817206cc..62345421e 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/bmatcuk/doublestar/v4 v4.6.1 github.com/charmbracelet/bubbles v0.18.0 github.com/charmbracelet/bubbletea v0.26.6 - github.com/charmbracelet/lipgloss v0.11.0 + github.com/charmbracelet/lipgloss v0.11.1 github.com/dave/jennifer v1.7.0 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da github.com/distribution/reference v0.6.0 @@ -109,7 +109,7 @@ require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/becheran/wildmatch-go v1.0.0 // indirect github.com/charmbracelet/harmonica v0.2.0 // indirect - github.com/charmbracelet/x/ansi v0.1.2 // indirect + github.com/charmbracelet/x/ansi v0.1.3 // indirect github.com/charmbracelet/x/input v0.1.0 // indirect github.com/charmbracelet/x/term v0.1.1 // indirect github.com/charmbracelet/x/windows v0.1.0 // indirect diff --git a/go.sum b/go.sum index a5e50ecb7..208364ae4 100644 --- a/go.sum +++ b/go.sum @@ -161,10 +161,10 @@ github.com/charmbracelet/bubbletea v0.26.6 h1:zTCWSuST+3yZYZnVSvbXwKOPRSNZceVeqp github.com/charmbracelet/bubbletea v0.26.6/go.mod h1:dz8CWPlfCCGLFbBlTY4N7bjLiyOGDJEnd2Muu7pOWhk= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= -github.com/charmbracelet/lipgloss v0.11.0 h1:UoAcbQ6Qml8hDwSWs0Y1cB5TEQuZkDPH/ZqwWWYTG4g= -github.com/charmbracelet/lipgloss v0.11.0/go.mod h1:1UdRTH9gYgpcdNN5oBtjbu/IzNKtzVtb7sqN1t9LNn8= -github.com/charmbracelet/x/ansi v0.1.2 h1:6+LR39uG8DE6zAmbu023YlqjJHkYXDF1z36ZwzO4xZY= -github.com/charmbracelet/x/ansi v0.1.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/lipgloss v0.11.1 h1:a8KgVPHa7kOoP95vm2tQQrjD2AKhbWmfr4uJ2RW6kNk= +github.com/charmbracelet/lipgloss v0.11.1/go.mod h1:beLlcmkF7MWA+5UrKKIRo/VJ21xGXr7YJ9miWfdMRIU= +github.com/charmbracelet/x/ansi v0.1.3 h1:RBh/eleNWML5R524mjUF0yVRePTwqN9tPtV+DPgO5Lw= +github.com/charmbracelet/x/ansi v0.1.3/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/input v0.1.0 h1:TEsGSfZYQyOtp+STIjyBq6tpRaorH0qpwZUj8DavAhQ= github.com/charmbracelet/x/input v0.1.0/go.mod h1:ZZwaBxPF7IG8gWWzPUVqHEtWhc1+HXJPNuerJGRGZ28= github.com/charmbracelet/x/term v0.1.1 h1:3cosVAiPOig+EV4X9U+3LDgtwwAoEzJjNdwbXDjF6yI= From 4e09908ba124dca7e6f1f6e7dc4f4663fae658ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Jul 2024 10:19:48 -0700 Subject: [PATCH 079/284] chore(deps): bump actions/setup-go from 5.0.1 to 5.0.2 (#3027) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5.0.1 to 5.0.2. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/cdcb36043654635271a94b9a6d1392de5bb323a7...0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/update-stereoscope-release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 0d39a417c..422eeefa5 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -39,7 +39,7 @@ jobs: uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - name: Install Go - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 #v5.0.1 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 #v5.0.2 with: go-version-file: go.mod diff --git a/.github/workflows/update-stereoscope-release.yml b/.github/workflows/update-stereoscope-release.yml index 894d04c7f..94ea0ee1b 100644 --- a/.github/workflows/update-stereoscope-release.yml +++ b/.github/workflows/update-stereoscope-release.yml @@ -19,7 +19,7 @@ jobs: steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 #v5.0.1 + - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 #v5.0.2 with: go-version: ${{ env.GO_VERSION }} stable: ${{ env.GO_STABLE_VERSION }} From e2fe955262cad2386d66ecaef69c80ae5ce668b1 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Thu, 11 Jul 2024 10:38:10 -0700 Subject: [PATCH 080/284] chore(deps): update stereoscope to 27b66b76fc6686fcf6bde656aa09e1f0e047fec1 (#3026) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: kzantow <3009477+kzantow@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 62345421e..3f6589f18 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f - github.com/anchore/stereoscope v0.0.3-0.20240705165118-e46739e21796 + github.com/anchore/stereoscope v0.0.3-0.20240710175110-27b66b76fc66 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // we are hinting brotli to latest due to warning when installing archiver v3: // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption @@ -137,7 +137,7 @@ require ( github.com/felixge/fgprof v0.9.3 // indirect github.com/felixge/httpsnoop v1.0.3 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.4 // indirect github.com/gkampitakis/ciinfo v0.3.0 // indirect github.com/gkampitakis/go-diff v1.3.2 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect diff --git a/go.sum b/go.sum index 208364ae4..fe588d484 100644 --- a/go.sum +++ b/go.sum @@ -113,8 +113,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f h1:B/E9ixKNCasntpoch61NDaQyGPDXLEJlL+B9B/PbdbA= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.3-0.20240705165118-e46739e21796 h1:mb2i23zBKaSloS4RHMwBCKTCB3X5HnObcRvjxrvvMr8= -github.com/anchore/stereoscope v0.0.3-0.20240705165118-e46739e21796/go.mod h1:6r8piaIGsYZuVkFw+fAXYtEGFI58dZuni/jNdvK+IxQ= +github.com/anchore/stereoscope v0.0.3-0.20240710175110-27b66b76fc66 h1:Z/yFalhLPfmE1MmIDKpE4GIVcWI0r7WpYX+7nLONRj0= +github.com/anchore/stereoscope v0.0.3-0.20240710175110-27b66b76fc66/go.mod h1:Ttqzw15V5ku7hITQNH4t6Nc+naBNAfSTDagmhSNPwJo= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= @@ -284,8 +284,8 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/gabriel-vasile/mimetype v1.4.0 h1:Cn9dkdYsMIu56tGho+fqzh7XmvY2YyGU0FnbhiOsEro= -github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= +github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I= +github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/github/go-spdx/v2 v2.3.1 h1:ffGuHTbHuHzWPt53n8f9o8clGutuLPObo3zB4JAjxU8= github.com/github/go-spdx/v2 v2.3.1/go.mod h1:2ZxKsOhvBp+OYBDlsGnUMcchLeo2mrpEBn2L1C+U3IQ= @@ -961,7 +961,6 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= From 37245a21ccb99d4195b414beb06b0c8433bfa97b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Jul 2024 14:50:48 -0400 Subject: [PATCH 081/284] chore(deps): bump anchore/sbom-action from 0.16.0 to 0.16.1 (#3023) Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.16.0 to 0.16.1. - [Release notes](https://github.com/anchore/sbom-action/releases) - [Commits](https://github.com/anchore/sbom-action/compare/e8d2a6937ecead383dfe75190d104edd1f9c5751...95b086ac308035dc0850b3853be5b7ab108236a8) --- updated-dependencies: - dependency-name: anchore/sbom-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 1e2d26f4b..9b1887860 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -148,7 +148,7 @@ jobs: # for updating brew formula in anchore/homebrew-syft GITHUB_BREW_TOKEN: ${{ secrets.ANCHOREOPS_GITHUB_OSS_WRITE_TOKEN }} - - uses: anchore/sbom-action@e8d2a6937ecead383dfe75190d104edd1f9c5751 #v0.16.0 + - uses: anchore/sbom-action@95b086ac308035dc0850b3853be5b7ab108236a8 #v0.16.1 continue-on-error: true with: artifact-name: sbom.spdx.json From 278b72d39b0d983de1d2937c8b905c27540235b0 Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Mon, 15 Jul 2024 12:37:09 -0400 Subject: [PATCH 082/284] chore: pin fedora image for elf binary test (#3041) Signed-off-by: Keith Zantow --- syft/pkg/cataloger/binary/elf_package_cataloger_test.go | 4 ++-- .../binary/test-fixtures/image-fedora-64bit/Dockerfile | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/syft/pkg/cataloger/binary/elf_package_cataloger_test.go b/syft/pkg/cataloger/binary/elf_package_cataloger_test.go index 4ec6bd61f..d9a97cc64 100644 --- a/syft/pkg/cataloger/binary/elf_package_cataloger_test.go +++ b/syft/pkg/cataloger/binary/elf_package_cataloger_test.go @@ -70,8 +70,8 @@ func Test_ELF_Package_Cataloger(t *testing.T) { expected: []pkg.Package{ { Name: "coreutils", - Version: "9.5-1.fc41", - PURL: "pkg:rpm/fedora/coreutils@9.5-1.fc41?distro=fedora-40", + Version: "9.5-3.fc41", + PURL: "pkg:rpm/fedora/coreutils@9.5-3.fc41?distro=fedora-40", Locations: file.NewLocationSet( file.NewLocation("/sha256sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), file.NewLocation("/sha1sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), diff --git a/syft/pkg/cataloger/binary/test-fixtures/image-fedora-64bit/Dockerfile b/syft/pkg/cataloger/binary/test-fixtures/image-fedora-64bit/Dockerfile index 14dc99c44..e1c508b85 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/image-fedora-64bit/Dockerfile +++ b/syft/pkg/cataloger/binary/test-fixtures/image-fedora-64bit/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=linux/amd64 fedora:41 as build +FROM --platform=linux/amd64 fedora:41@sha256:c05bf79137835bf5c521c58f8252d6031780ae865a0379ab57f412e0ac6b42aa as build FROM scratch COPY --from=build /bin/sha256sum /sha256sum From 75902b0540b6c7c701ea14ed0f32163e6ced2da2 Mon Sep 17 00:00:00 2001 From: William Murphy Date: Tue, 16 Jul 2024 09:51:14 -0400 Subject: [PATCH 083/284] fix: stop panicking on "devel" version go stdlib (#3043) Previously, if a Go binary was cataloged with build info indicating that the go compiler version used was "deve", syft would panic on a nil pointer dereference. Instead, skip creating a Go stdlib reference and relationship for such a package. Signed-off-by: Will Murphy --- syft/pkg/cataloger/golang/stdlib_package.go | 7 ++++--- syft/pkg/cataloger/golang/stdlib_package_test.go | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/syft/pkg/cataloger/golang/stdlib_package.go b/syft/pkg/cataloger/golang/stdlib_package.go index 19d37fe89..6e480e8c8 100644 --- a/syft/pkg/cataloger/golang/stdlib_package.go +++ b/syft/pkg/cataloger/golang/stdlib_package.go @@ -33,10 +33,11 @@ func stdlibPackageAndRelationships(pkgs []pkg.Package) ([]pkg.Package, []artifac } stdLibPkg := newGoStdLib(mValue.GoCompiledVersion, goPkg.Locations) - if stdLibPkg != nil { - goCompilerPkgs = append(goCompilerPkgs, *stdLibPkg) - totalLocations.Add(location) + if stdLibPkg == nil { + continue } + goCompilerPkgs = append(goCompilerPkgs, *stdLibPkg) + totalLocations.Add(location) relationships = append(relationships, artifact.Relationship{ From: *stdLibPkg, diff --git a/syft/pkg/cataloger/golang/stdlib_package_test.go b/syft/pkg/cataloger/golang/stdlib_package_test.go index 44653f82b..295266d33 100644 --- a/syft/pkg/cataloger/golang/stdlib_package_test.go +++ b/syft/pkg/cataloger/golang/stdlib_package_test.go @@ -68,6 +68,22 @@ func Test_stdlibPackageAndRelationships(t *testing.T) { wantPkgs: 1, wantRels: 1, }, + { + name: "go binary package with devel stdlib", + pkgs: []pkg.Package{ + { + Name: "github.com/something/go", + Version: "1.0.0", + Locations: file.NewLocationSet(file.NewLocation("/bin/my-app")), + Metadata: pkg.GolangBinaryBuildinfoEntry{ + GoCompiledVersion: "devel", + MainModule: "github.com/something/go", + }, + }, + }, + wantPkgs: 0, + wantRels: 0, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { From 77c300d617260bc3ca7b5129da9e2f674d2fd729 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jul 2024 06:58:07 -0700 Subject: [PATCH 084/284] chore(deps): bump anchore/sbom-action from 0.16.1 to 0.17.0 (#3044) Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.16.1 to 0.17.0. - [Release notes](https://github.com/anchore/sbom-action/releases) - [Commits](https://github.com/anchore/sbom-action/compare/95b086ac308035dc0850b3853be5b7ab108236a8...d94f46e13c6c62f59525ac9a1e147a99dc0b9bf5) --- updated-dependencies: - dependency-name: anchore/sbom-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 9b1887860..3c644a62c 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -148,7 +148,7 @@ jobs: # for updating brew formula in anchore/homebrew-syft GITHUB_BREW_TOKEN: ${{ secrets.ANCHOREOPS_GITHUB_OSS_WRITE_TOKEN }} - - uses: anchore/sbom-action@95b086ac308035dc0850b3853be5b7ab108236a8 #v0.16.1 + - uses: anchore/sbom-action@d94f46e13c6c62f59525ac9a1e147a99dc0b9bf5 #v0.17.0 continue-on-error: true with: artifact-name: sbom.spdx.json From 6bf91a410dabfd33d96e7849e51bb105b7a0125a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jul 2024 06:58:18 -0700 Subject: [PATCH 085/284] chore(deps): bump github/codeql-action from 3.25.11 to 3.25.12 (#3034) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.11 to 3.25.12. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/b611370bb5703a7efb587f9d136a52ea24c5c38c...4fa2a7953630fd2f3fb380f21be14ede0169dd4f) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 422eeefa5..d1791caf9 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@b611370bb5703a7efb587f9d136a52ea24c5c38c #v3.25.11 + uses: github/codeql-action/init@4fa2a7953630fd2f3fb380f21be14ede0169dd4f #v3.25.12 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@b611370bb5703a7efb587f9d136a52ea24c5c38c #v3.25.11 + uses: github/codeql-action/autobuild@4fa2a7953630fd2f3fb380f21be14ede0169dd4f #v3.25.12 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b611370bb5703a7efb587f9d136a52ea24c5c38c #v3.25.11 + uses: github/codeql-action/analyze@4fa2a7953630fd2f3fb380f21be14ede0169dd4f #v3.25.12 From d4d4e003e9f023098e0051cca25185c560eec20e Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Tue, 16 Jul 2024 06:58:33 -0700 Subject: [PATCH 086/284] chore(deps): update tools to latest versions (#3031) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.binny.yaml b/.binny.yaml index fc2bc32ad..38b0c4704 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -18,7 +18,7 @@ tools: # used to sign mac binaries at release - name: quill version: - want: v0.4.1 + want: v0.4.2 method: github-release with: repo: anchore/quill @@ -58,7 +58,7 @@ tools: # used to release all artifacts - name: goreleaser version: - want: v2.0.1 + want: v2.1.0 method: github-release with: repo: goreleaser/goreleaser From d4fa61e0a2a730370979b98f01babba482454f4f Mon Sep 17 00:00:00 2001 From: Adam McClenaghan Date: Tue, 16 Jul 2024 14:59:14 +0100 Subject: [PATCH 087/284] chore: Fix apache shield in readme (#3021) Signed-off-by: Adam McClenaghan --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 141257be5..3d22f2a02 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@  Go Report Card   GitHub release   GitHub go.mod Go version  -  License: Apache-2.0  +  License: Apache-2.0   Slack 

From 4d23990dd41fc0c62e4b8a7b52c4888848437c80 Mon Sep 17 00:00:00 2001 From: Bradley Jones Date: Tue, 16 Jul 2024 14:59:31 +0100 Subject: [PATCH 088/284] docs: link to contrib/dev docs in readme (#3029) These docs are full of great information so make them easily accessible from the README so they aren't overlooked. Signed-off-by: Bradley Jones --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 3d22f2a02..4a714210c 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,10 @@ Our [wiki](https://github.com/anchore/syft/wiki) contains further details on the * [Adding an SBOM to an image as an attestation using Syft](https://github.com/anchore/syft/wiki/attestation#adding-an-sbom-to-an-image-as-an-attestation-using-syft) * [Configuration](https://github.com/anchore/syft/wiki/configuration) +## Contributing + +Check out our [contributing](/CONTRIBUTING.md) guide and [developer](/DEVELOPING.md) docs. + ## Syft Team Meetings The Syft Team hold regular community meetings online. All are welcome to join to bring topics for discussion. From cca9a06a6439289da22dc901940160b3b6124a32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jul 2024 09:10:34 -0400 Subject: [PATCH 089/284] chore(deps): bump modernc.org/sqlite from 1.30.1 to 1.30.2 (#3039) Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.30.1 to 1.30.2. - [Commits](https://gitlab.com/cznic/sqlite/compare/v1.30.1...v1.30.2) --- updated-dependencies: - dependency-name: modernc.org/sqlite dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3f6589f18..1f75c96ce 100644 --- a/go.mod +++ b/go.mod @@ -81,7 +81,7 @@ require ( golang.org/x/mod v0.19.0 golang.org/x/net v0.27.0 gopkg.in/yaml.v3 v3.0.1 - modernc.org/sqlite v1.30.1 + modernc.org/sqlite v1.30.2 ) require google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect diff --git a/go.sum b/go.sum index fe588d484..b640f76f3 100644 --- a/go.sum +++ b/go.sum @@ -1378,8 +1378,8 @@ modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= -modernc.org/sqlite v1.30.1 h1:YFhPVfu2iIgUf9kuA1CR7iiHdcEEsI2i+yjRYHscyxk= -modernc.org/sqlite v1.30.1/go.mod h1:DUmsiWQDaAvU4abhc/N+djlom/L2o8f7gZ95RCvyoLU= +modernc.org/sqlite v1.30.2 h1:IPVVkhLu5mMVnS1dQgh3h0SAACRWcVk7aoLP9Us3UCk= +modernc.org/sqlite v1.30.2/go.mod h1:DUmsiWQDaAvU4abhc/N+djlom/L2o8f7gZ95RCvyoLU= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= From 276df9576827b066f84576f88d4b75b37538bac4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jul 2024 11:21:14 -0700 Subject: [PATCH 090/284] chore(deps): bump github.com/moby/sys/mountinfo from 0.7.1 to 0.7.2 (#3048) Bumps [github.com/moby/sys/mountinfo](https://github.com/moby/sys) from 0.7.1 to 0.7.2. - [Release notes](https://github.com/moby/sys/releases) - [Commits](https://github.com/moby/sys/compare/signal/v0.7.1...mountinfo/v0.7.2) --- updated-dependencies: - dependency-name: github.com/moby/sys/mountinfo dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1f75c96ce..a0fb50ceb 100644 --- a/go.mod +++ b/go.mod @@ -55,7 +55,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/mitchellh/mapstructure v1.5.0 - github.com/moby/sys/mountinfo v0.7.1 + github.com/moby/sys/mountinfo v0.7.2 github.com/olekukonko/tablewriter v0.0.5 github.com/opencontainers/go-digest v1.0.0 github.com/pelletier/go-toml v1.9.5 diff --git a/go.sum b/go.sum index b640f76f3..947a8c998 100644 --- a/go.sum +++ b/go.sum @@ -583,8 +583,8 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= -github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g= -github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= +github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= +github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI= From 5d729a5e9e4e18d4587350ce7c602d5af5c01b21 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jul 2024 11:21:23 -0700 Subject: [PATCH 091/284] chore(deps): bump github.com/google/go-containerregistry (#3047) Bumps [github.com/google/go-containerregistry](https://github.com/google/go-containerregistry) from 0.20.0 to 0.20.1. - [Release notes](https://github.com/google/go-containerregistry/releases) - [Changelog](https://github.com/google/go-containerregistry/blob/main/.goreleaser.yml) - [Commits](https://github.com/google/go-containerregistry/compare/v0.20.0...v0.20.1) --- updated-dependencies: - dependency-name: github.com/google/go-containerregistry dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a0fb50ceb..54a5d378b 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/go-git/go-git/v5 v5.12.0 github.com/go-test/deep v1.1.1 github.com/google/go-cmp v0.6.0 - github.com/google/go-containerregistry v0.20.0 + github.com/google/go-containerregistry v0.20.1 github.com/google/licensecheck v0.3.1 github.com/google/uuid v1.6.0 github.com/gookit/color v1.5.4 diff --git a/go.sum b/go.sum index 947a8c998..7f3199fde 100644 --- a/go.sum +++ b/go.sum @@ -384,8 +384,8 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.20.0 h1:wRqHpOeVh3DnenOrPy9xDOLdnLatiGuuNRVelR2gSbg= -github.com/google/go-containerregistry v0.20.0/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI= +github.com/google/go-containerregistry v0.20.1 h1:eTgx9QNYugV4DN5mz4U8hiAGTi1ybXn0TPi4Smd8du0= +github.com/google/go-containerregistry v0.20.1/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/licensecheck v0.3.1 h1:QoxgoDkaeC4nFrtGN1jV7IPmDCHFNIVh54e5hSt6sPs= github.com/google/licensecheck v0.3.1/go.mod h1:ORkR35t/JjW+emNKtfJDII0zlciG9JgbT7SmsohlHmY= From ba31c2f1ae28d264c0222c43ccf839721d636db9 Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Wed, 17 Jul 2024 14:23:58 -0400 Subject: [PATCH 092/284] fix: include CPEs with Maven groupId as vendor (#3045) Signed-off-by: Keith Zantow --- .../internal/cpegenerate/generate_test.go | 16 ++++++++++++++++ syft/pkg/cataloger/internal/cpegenerate/java.go | 7 +++++++ .../cataloger/internal/cpegenerate/java_test.go | 2 +- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/syft/pkg/cataloger/internal/cpegenerate/generate_test.go b/syft/pkg/cataloger/internal/cpegenerate/generate_test.go index e0b9af6cb..bd4070852 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/generate_test.go +++ b/syft/pkg/cataloger/internal/cpegenerate/generate_test.go @@ -203,6 +203,8 @@ func TestGeneratePackageCPEs(t *testing.T) { "cpe:2.3:a:nexus:nexus:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:sonatype:name:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:sonatype:nexus:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:org.sonatype.nexus:name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:org.sonatype.nexus:nexus:3.2:*:*:*:*:*:*:*", }, }, { @@ -371,6 +373,7 @@ func TestGeneratePackageCPEs(t *testing.T) { "cpe:2.3:a:name:name:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:jenkins:name:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:cloudbees:name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:com.cloudbees.jenkins.plugins:name:3.2:*:*:*:*:*:*:*", }, }, { @@ -394,6 +397,8 @@ func TestGeneratePackageCPEs(t *testing.T) { "cpe:2.3:a:something:something:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:jenkins:name:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:jenkins:something:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:io.jenkins.plugins.name.something:name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:io.jenkins.plugins.name.something:something:3.2:*:*:*:*:*:*:*", }, }, { @@ -413,6 +418,7 @@ func TestGeneratePackageCPEs(t *testing.T) { expected: []string{ "cpe:2.3:a:name:name:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:jenkins:name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:io.jenkins.plugins:name:3.2:*:*:*:*:*:*:*", }, }, { @@ -434,6 +440,7 @@ func TestGeneratePackageCPEs(t *testing.T) { "cpe:2.3:a:jenkins-ci:name:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:jenkins:name:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:jenkins_ci:name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:io.jenkins-ci.plugins:name:3.2:*:*:*:*:*:*:*", }, }, { @@ -455,6 +462,7 @@ func TestGeneratePackageCPEs(t *testing.T) { "cpe:2.3:a:jenkins-ci:name:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:jenkins:name:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:jenkins_ci:name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:org.jenkins-ci.plugins:name:3.2:*:*:*:*:*:*:*", }, }, { @@ -489,6 +497,9 @@ func TestGeneratePackageCPEs(t *testing.T) { "cpe:2.3:a:jira_client_core:jira-client-core:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:jira_client_core:jira:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:jira_client_core:jira_client_core:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:org.atlassian.jira:jira:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:org.atlassian.jira:jira_client_core:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:org.atlassian.jira:jira-client-core:3.2:*:*:*:*:*:*:*", }, }, { @@ -521,6 +532,8 @@ func TestGeneratePackageCPEs(t *testing.T) { "cpe:2.3:a:jenkins:cloudbees_installation_manager:2.89.0.33:*:*:*:*:*:*:*", "cpe:2.3:a:modules:cloudbees-installation-manager:2.89.0.33:*:*:*:*:*:*:*", "cpe:2.3:a:modules:cloudbees_installation_manager:2.89.0.33:*:*:*:*:*:*:*", + "cpe:2.3:a:com.cloudbees.jenkins.modules:cloudbees_installation_manager:2.89.0.33:*:*:*:*:*:*:*", + "cpe:2.3:a:com.cloudbees.jenkins.modules:cloudbees-installation-manager:2.89.0.33:*:*:*:*:*:*:*", }, }, { @@ -594,6 +607,7 @@ func TestGeneratePackageCPEs(t *testing.T) { "cpe:2.3:a:jenkins:handlebars:3.0.8:*:*:*:*:*:*:*", "cpe:2.3:a:jenkins_ci:handlebars:3.0.8:*:*:*:*:*:*:*", "cpe:2.3:a:ui:handlebars:3.0.8:*:*:*:*:*:*:*", + "cpe:2.3:a:org.jenkins-ci.ui:handlebars:3.0.8:*:*:*:*:*:*:*", }, }, { @@ -631,6 +645,8 @@ func TestGeneratePackageCPEs(t *testing.T) { "cpe:2.3:a:jenkins:active_directory:2.25.1:*:*:*:*:*:*:*", // important! "cpe:2.3:a:jenkins_ci:active-directory:2.25.1:*:*:*:*:*:*:*", "cpe:2.3:a:jenkins_ci:active_directory:2.25.1:*:*:*:*:*:*:*", + "cpe:2.3:a:org.jenkins-ci.plugins:active-directory:2.25.1:*:*:*:*:*:*:*", + "cpe:2.3:a:org.jenkins-ci.plugins:active_directory:2.25.1:*:*:*:*:*:*:*", }, }, { diff --git a/syft/pkg/cataloger/internal/cpegenerate/java.go b/syft/pkg/cataloger/internal/cpegenerate/java.go index 7de85c9e6..8ccd38059 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/java.go +++ b/syft/pkg/cataloger/internal/cpegenerate/java.go @@ -98,6 +98,13 @@ func vendorsFromJavaManifestNames(p pkg.Package) fieldCandidateSet { func vendorsFromGroupIDs(groupIDs []string) fieldCandidateSet { vendors := newFieldCandidateSet() for _, groupID := range groupIDs { + // always include the groupId as a vendor -- the Grype database may include alternate matches with these + vendors.add(fieldCandidate{ + value: groupID, + disallowSubSelections: true, + disallowDelimiterVariations: true, + }) + for i, field := range strings.Split(groupID, ".") { field = strings.TrimSpace(field) diff --git a/syft/pkg/cataloger/internal/cpegenerate/java_test.go b/syft/pkg/cataloger/internal/cpegenerate/java_test.go index a08c0fec9..3573b8c9b 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/java_test.go +++ b/syft/pkg/cataloger/internal/cpegenerate/java_test.go @@ -139,7 +139,7 @@ func Test_vendorsFromGroupIDs(t *testing.T) { } for _, test := range tests { t.Run(test.groupID, func(t *testing.T) { - assert.ElementsMatch(t, test.expected, vendorsFromGroupIDs([]string{test.groupID}).values(), "different vendors") + assert.ElementsMatch(t, append(test.expected, test.groupID), vendorsFromGroupIDs([]string{test.groupID}).values(), "different vendors") }) } } From 761a161e7f28030dda209803c12cd1c8484b4f3d Mon Sep 17 00:00:00 2001 From: Alan Pope Date: Wed, 17 Jul 2024 22:33:17 +0100 Subject: [PATCH 093/284] docs: CODE_OF_CONDUCT.md (#3046) This PR adds a code of conduct document to the repo, as agreed at our recent OSS team catch up. Signed-off-by: Alan Pope --- CODE_OF_CONDUCT.md | 128 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..5d19a3c26 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[opensource@anchore.com](mailto:opensource@anchore.com). +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. From 69031b064664981fba4a77b719228605593b8a90 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Thu, 18 Jul 2024 08:21:31 -0700 Subject: [PATCH 094/284] chore(deps): update tools to latest versions (#3050) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index 38b0c4704..0a1dafff5 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -111,7 +111,7 @@ tools: # used for triggering a release - name: gh version: - want: v2.52.0 + want: v2.53.0 method: github-release with: repo: cli/cli From 034a98f02972e94cbf3dddfdd116b94176a9d56e Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Thu, 18 Jul 2024 09:26:01 -0700 Subject: [PATCH 095/284] chore(deps): update stereoscope to 487b11e5ba2622d976acda10c605da63b4fbbb0a (#3032) * chore(deps): update stereoscope to 487b11e5ba2622d976acda10c605da63b4fbbb0a Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * chore: allow unlicense Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> --------- Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> Co-authored-by: kzantow <3009477+kzantow@users.noreply.github.com> Co-authored-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> --- .bouncer.yaml | 1 + go.mod | 8 ++++---- go.sum | 15 ++++++++------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/.bouncer.yaml b/.bouncer.yaml index b27baa6ea..5360418ef 100644 --- a/.bouncer.yaml +++ b/.bouncer.yaml @@ -6,6 +6,7 @@ permit: - MPL.* - ISC - WTFPL + - Unlicense ignore-packages: # packageurl-go is released under the MIT license located in the root of the repo at /mit.LICENSE diff --git a/go.mod b/go.mod index 54a5d378b..65d42acfb 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f - github.com/anchore/stereoscope v0.0.3-0.20240710175110-27b66b76fc66 + github.com/anchore/stereoscope v0.0.3-0.20240711134149-487b11e5ba26 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // we are hinting brotli to latest due to warning when installing archiver v3: // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption @@ -162,7 +162,7 @@ require ( github.com/klauspost/pgzip v1.2.5 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 // indirect + github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/maruel/natural v1.1.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -188,7 +188,7 @@ require ( github.com/opencontainers/selinux v1.11.0 // indirect github.com/pborman/indent v1.2.1 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect - github.com/pierrec/lz4/v4 v4.1.15 // indirect + github.com/pierrec/lz4/v4 v4.1.19 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pkg/profile v1.7.0 // indirect @@ -209,7 +209,7 @@ require ( github.com/spf13/viper v1.18.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/sylabs/sif/v2 v2.17.1 // indirect - github.com/sylabs/squashfs v0.6.1 // indirect + github.com/sylabs/squashfs v1.0.0 // indirect github.com/therootcompany/xz v1.0.1 // indirect github.com/tidwall/gjson v1.17.0 // indirect github.com/tidwall/match v1.1.1 // indirect diff --git a/go.sum b/go.sum index 7f3199fde..f94a26c1d 100644 --- a/go.sum +++ b/go.sum @@ -113,8 +113,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f h1:B/E9ixKNCasntpoch61NDaQyGPDXLEJlL+B9B/PbdbA= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.3-0.20240710175110-27b66b76fc66 h1:Z/yFalhLPfmE1MmIDKpE4GIVcWI0r7WpYX+7nLONRj0= -github.com/anchore/stereoscope v0.0.3-0.20240710175110-27b66b76fc66/go.mod h1:Ttqzw15V5ku7hITQNH4t6Nc+naBNAfSTDagmhSNPwJo= +github.com/anchore/stereoscope v0.0.3-0.20240711134149-487b11e5ba26 h1:nOTfmXionIzGtg487nREmvDNr7QbR9vf6HbC2Z6n1ZE= +github.com/anchore/stereoscope v0.0.3-0.20240711134149-487b11e5ba26/go.mod h1:DcQdMes8SwpFli3rDH0v+Vd9qU9Jariq7JSHNJV5X/A= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= @@ -522,8 +522,9 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 h1:bqDmpDG49ZRnB5PcgP0RXtQvnMSgIF14M7CBd2shtXs= github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= +github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= @@ -635,8 +636,8 @@ github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0= -github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.19 h1:tYLzDnjDXh9qIxSTKHwXwOYmm9d887Y7Y1ZkyXYHAN4= +github.com/pierrec/lz4/v4 v4.1.19/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -770,8 +771,8 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/sylabs/sif/v2 v2.17.1 h1:p6Sl0LWyShXBj2SBsS1dMOMIMrZHe8pwBnBrYt6uo4M= github.com/sylabs/sif/v2 v2.17.1/go.mod h1:XUGB6AQUXGkms3qPOPdevctT3lBLRLWZNWHVnt5HMKE= -github.com/sylabs/squashfs v0.6.1 h1:4hgvHnD9JGlYWwT0bPYNt9zaz23mAV3Js+VEgQoRGYQ= -github.com/sylabs/squashfs v0.6.1/go.mod h1:ZwpbPCj0ocIvMy2br6KZmix6Gzh6fsGQcCnydMF+Kx8= +github.com/sylabs/squashfs v1.0.0 h1:xAyMS21ogglkuR5HaY55PCfqY3H32ma9GkasTYo28Zg= +github.com/sylabs/squashfs v1.0.0/go.mod h1:rhWzvgefq1X+R+LZdts10hfMsTg3g74OfGunW8tvg/4= github.com/terminalstatic/go-xsd-validate v0.1.5 h1:RqpJnf6HGE2CB/lZB1A8BYguk8uRtcvYAPLCF15qguo= github.com/terminalstatic/go-xsd-validate v0.1.5/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw= github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw= From b263b1ec1f8af615c8ee01d13b8120464d293140 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 10:55:55 -0400 Subject: [PATCH 096/284] chore(deps): bump github/codeql-action from 3.25.12 to 3.25.13 (#3059) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.12 to 3.25.13. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/4fa2a7953630fd2f3fb380f21be14ede0169dd4f...2d790406f505036ef40ecba973cc774a50395aac) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d1791caf9..e92c3d4fc 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@4fa2a7953630fd2f3fb380f21be14ede0169dd4f #v3.25.12 + uses: github/codeql-action/init@2d790406f505036ef40ecba973cc774a50395aac #v3.25.13 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@4fa2a7953630fd2f3fb380f21be14ede0169dd4f #v3.25.12 + uses: github/codeql-action/autobuild@2d790406f505036ef40ecba973cc774a50395aac #v3.25.13 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@4fa2a7953630fd2f3fb380f21be14ede0169dd4f #v3.25.12 + uses: github/codeql-action/analyze@2d790406f505036ef40ecba973cc774a50395aac #v3.25.13 From 0c53a087f0a14bdf54bdcaa1170dbcb79c4a0136 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 08:44:06 -0700 Subject: [PATCH 097/284] chore(deps): bump docker/login-action from 3.2.0 to 3.3.0 (#3058) Bumps [docker/login-action](https://github.com/docker/login-action) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/0d4c9c5ea7693da7b068278f7b52bda2a190a446...9780b0c442fbb1117ed29e0efdff1e18412f7567) --- updated-dependencies: - dependency-name: docker/login-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3c644a62c..734fc7a32 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -113,13 +113,13 @@ jobs: uses: ./.github/actions/bootstrap - name: Login to Docker Hub - uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 #v3.2.0 + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 #v3.3.0 with: username: ${{ secrets.ANCHOREOSSWRITE_DH_USERNAME }} password: ${{ secrets.ANCHOREOSSWRITE_DH_PAT }} - name: Login to GitHub Container Registry - uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 #v3.2.0 + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 #v3.3.0 with: registry: ghcr.io username: ${{ github.actor }} From d0a7d4c43edc2f57a96ff2b2ced15f51d5ee4a42 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 08:45:01 -0700 Subject: [PATCH 098/284] chore(deps): bump modernc.org/sqlite from 1.30.2 to 1.31.1 (#3057) Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.30.2 to 1.31.1. - [Commits](https://gitlab.com/cznic/sqlite/compare/v1.30.2...v1.31.1) --- updated-dependencies: - dependency-name: modernc.org/sqlite dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 65d42acfb..a45445541 100644 --- a/go.mod +++ b/go.mod @@ -81,7 +81,7 @@ require ( golang.org/x/mod v0.19.0 golang.org/x/net v0.27.0 gopkg.in/yaml.v3 v3.0.1 - modernc.org/sqlite v1.30.2 + modernc.org/sqlite v1.31.1 ) require google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect @@ -243,7 +243,7 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect - modernc.org/libc v1.52.1 // indirect + modernc.org/libc v1.55.3 // indirect modernc.org/mathutil v1.6.0 // indirect modernc.org/memory v1.8.0 // indirect modernc.org/strutil v1.2.0 // indirect diff --git a/go.sum b/go.sum index f94a26c1d..6258f54a2 100644 --- a/go.sum +++ b/go.sum @@ -1359,18 +1359,18 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -modernc.org/cc/v4 v4.21.2 h1:dycHFB/jDc3IyacKipCNSDrjIC0Lm1hyoWOZTRR20Lk= -modernc.org/cc/v4 v4.21.2/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= -modernc.org/ccgo/v4 v4.17.10 h1:6wrtRozgrhCxieCeJh85QsxkX/2FFrT9hdaWPlbn4Zo= -modernc.org/ccgo/v4 v4.17.10/go.mod h1:0NBHgsqTTpm9cA5z2ccErvGZmtntSM9qD2kFAs6pjXM= +modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ= +modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= +modernc.org/ccgo/v4 v4.19.2 h1:lwQZgvboKD0jBwdaeVCTouxhxAyN6iawF3STraAal8Y= +modernc.org/ccgo/v4 v4.19.2/go.mod h1:ysS3mxiMV38XGRTTcgo0DQTeTmAO4oCmJl1nX9VFI3s= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= -modernc.org/libc v1.52.1 h1:uau0VoiT5hnR+SpoWekCKbLqm7v6dhRL3hI+NQhgN3M= -modernc.org/libc v1.52.1/go.mod h1:HR4nVzFDSDizP620zcMCgjb1/8xk2lg5p/8yjfGv1IQ= +modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U= +modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= @@ -1379,8 +1379,8 @@ modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= -modernc.org/sqlite v1.30.2 h1:IPVVkhLu5mMVnS1dQgh3h0SAACRWcVk7aoLP9Us3UCk= -modernc.org/sqlite v1.30.2/go.mod h1:DUmsiWQDaAvU4abhc/N+djlom/L2o8f7gZ95RCvyoLU= +modernc.org/sqlite v1.31.1 h1:XVU0VyzxrYHlBhIs1DiEgSl0ZtdnPtbLVy8hSkzxGrs= +modernc.org/sqlite v1.31.1/go.mod h1:UqoylwmTb9F+IqXERT8bW9zzOWN8qwAIcLdzeBZs4hA= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= From 536611fa2554e487fa94c0b9c6d0fc07209694b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 08:45:25 -0700 Subject: [PATCH 099/284] chore(deps): bump github.com/gkampitakis/go-snaps from 0.5.4 to 0.5.5 (#3056) Bumps [github.com/gkampitakis/go-snaps](https://github.com/gkampitakis/go-snaps) from 0.5.4 to 0.5.5. - [Release notes](https://github.com/gkampitakis/go-snaps/releases) - [Commits](https://github.com/gkampitakis/go-snaps/compare/v0.5.4...v0.5.5) --- updated-dependencies: - dependency-name: github.com/gkampitakis/go-snaps dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a45445541..783900ba4 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/elliotchance/phpserialize v1.4.0 github.com/facebookincubator/nvdtools v0.1.5 github.com/github/go-spdx/v2 v2.3.1 - github.com/gkampitakis/go-snaps v0.5.4 + github.com/gkampitakis/go-snaps v0.5.5 github.com/go-git/go-billy/v5 v5.5.0 github.com/go-git/go-git/v5 v5.12.0 github.com/go-test/deep v1.1.1 diff --git a/go.sum b/go.sum index 6258f54a2..2a9c32856 100644 --- a/go.sum +++ b/go.sum @@ -293,8 +293,8 @@ github.com/gkampitakis/ciinfo v0.3.0 h1:gWZlOC2+RYYttL0hBqcoQhM7h1qNkVqvRCV1fOvp github.com/gkampitakis/ciinfo v0.3.0/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk= -github.com/gkampitakis/go-snaps v0.5.4 h1:GX+dkKmVsRenz7SoTbdIEL4KQARZctkMiZ8ZKprRwT8= -github.com/gkampitakis/go-snaps v0.5.4/go.mod h1:ZABkO14uCuVxBHAXAfKG+bqNz+aa1bGPAg8jkI0Nk8Y= +github.com/gkampitakis/go-snaps v0.5.5 h1:FZ01SXOE/uIsD8lZGUjUAxTevz9tf7c1QGIgezv2KNM= +github.com/gkampitakis/go-snaps v0.5.5/go.mod h1:ZABkO14uCuVxBHAXAfKG+bqNz+aa1bGPAg8jkI0Nk8Y= github.com/glebarez/go-sqlite v1.20.3 h1:89BkqGOXR9oRmG58ZrzgoY/Fhy5x0M+/WV48U5zVrZ4= github.com/glebarez/go-sqlite v1.20.3/go.mod h1:u3N6D/wftiAzIOJtZl6BmedqxmmkDfH3q+ihjqxC9u0= github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= From aead40e1de387a1a520d440dcebbd205f460b023 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 08:56:01 -0700 Subject: [PATCH 100/284] chore(deps): bump github.com/docker/docker (#3055) Bumps [github.com/docker/docker](https://github.com/docker/docker) from 27.0.3+incompatible to 27.1.0+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.0.3...v27.1.0) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 783900ba4..dcdc4d5a8 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/dave/jennifer v1.7.0 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da github.com/distribution/reference v0.6.0 - github.com/docker/docker v27.0.3+incompatible + github.com/docker/docker v27.1.0+incompatible github.com/dustin/go-humanize v1.0.1 github.com/elliotchance/phpserialize v1.4.0 github.com/facebookincubator/nvdtools v0.1.5 diff --git a/go.sum b/go.sum index 2a9c32856..f023a58a6 100644 --- a/go.sum +++ b/go.sum @@ -231,8 +231,8 @@ github.com/docker/cli v27.0.3+incompatible h1:usGs0/BoBW8MWxGeEtqPMkzOY56jZ6kYlS github.com/docker/cli v27.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= From bfe6f5204aa5e848fd8466f3c92de10383b98ee5 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 08:56:58 -0700 Subject: [PATCH 101/284] chore(deps): update CPE dictionary index (#3035) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: wagoodman <590471+wagoodman@users.noreply.github.com> --- .../dictionary/data/cpe-index.json | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index 37cdae870..361a897e2 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -6980,6 +6980,9 @@ "99fy-core": [ "cpe:2.3:a:hasthemes:free_woocommerce_theme_99fy_extension:*:*:*:*:*:wordpress:*:*" ], + "Ultimate_VC_Addons": [ + "cpe:2.3:a:brainstormforce:ultimate_addons_for_wpbakery_page_builder:*:*:*:*:*:wordpress:*:*" + ], "a-forms": [ "cpe:2.3:a:a-forms_project:a-forms:*:*:*:*:*:wordpress:*:*" ], @@ -9471,6 +9474,9 @@ "digital-publications-by-supsystic": [ "cpe:2.3:a:supsystic:digital_publications_by_supsystic:*:*:*:*:*:wordpress:*:*" ], + "dimage-360": [ + "cpe:2.3:a:darteweb:dimage_360:*:*:*:*:*:wordpress:*:*" + ], "directorist": [ "cpe:2.3:a:wpwax:directorist:*:*:*:*:*:wordpress:*:*" ], @@ -10323,6 +10329,9 @@ "feedburner-alternative-and-rss-redirect": [ "cpe:2.3:a:inisev:rss_redirect_\\\u0026_feedburner_alternative:*:*:*:*:*:wordpress:*:*" ], + "feeds-for-youtube": [ + "cpe:2.3:a:smashballoon:feeds_for_youtube:*:*:*:*:*:wordpress:*:*" + ], "feedwordpress": [ "cpe:2.3:a:feedwordpress_project:feedwordpress:*:*:*:*:*:wordpress:*:*" ], @@ -11398,6 +11407,9 @@ "imdb-widget": [ "cpe:2.3:a:imdb-widget_project:imdb-widget:*:*:*:*:*:wordpress:*:*" ], + "imgspider": [ + "cpe:2.3:a:wbolt:imgspider:*:*:*:*:*:wordpress:*:*" + ], "import-legacy-media": [ "cpe:2.3:a:import_legacy_media_project:import_legacy_media:*:*:*:*:*:wordpress:*:*" ], @@ -11692,6 +11704,9 @@ "jsmol2wp": [ "cpe:2.3:a:jsmol2wp_project:jsmol2wp:*:*:*:*:*:wordpress:*:*" ], + "json-api-user": [ + "cpe:2.3:a:parorrey:json_api_user:*:*:*:*:*:wordpress:*:*" + ], "json-content-importer": [ "cpe:2.3:a:json-content-importer:json_content_importer:*:*:*:*:*:wordpress:*:*" ], @@ -12925,6 +12940,9 @@ "one-click-demo-import": [ "cpe:2.3:a:ocdi:one_click_demo_import:*:*:*:*:*:wordpress:*:*" ], + "one-click-order-reorder": [ + "cpe:2.3:a:cedcommerce:one_click_order_re-order:*:*:*:*:*:wordpress:*:*" + ], "one-click-plugin-updater": [ "cpe:2.3:a:one_click_plugin_updater_project:one_click_plugin_updater:*:*:*:*:*:wordpress:*:*" ], @@ -13103,6 +13121,9 @@ "paid-memberships-pro": [ "cpe:2.3:a:strangerstudios:paid_memberships_pro:*:*:*:*:*:wordpress:*:*" ], + "pandavideo": [ + "cpe:2.3:a:pandavideo:panda_video:*:*:*:*:*:wordpress:*:*" + ], "parallax-image": [ "cpe:2.3:a:howardehrenberg:parallax_image:*:*:*:*:*:wordpress:*:*" ], @@ -13690,6 +13711,9 @@ "project-status": [ "cpe:2.3:a:3.7designs:project_status:*:*:*:*:*:wordpress:*:*" ], + "projecthuddle-child-site": [ + "cpe:2.3:a:brainstormforce:surefeedback:*:*:*:*:*:wordpress:*:*" + ], "promobar": [ "cpe:2.3:a:bestwebsoft:promobar:*:*:*:*:*:wordpress:*:*" ], @@ -14263,6 +14287,9 @@ "schedulicity-online-appointment-booking": [ "cpe:2.3:a:schedulicity:schedulicity:*:*:*:*:*:wordpress:*:*" ], + "schema-and-structured-data-for-wp": [ + "cpe:2.3:a:magazine3:schema_\\\u0026_structured_data_for_wp_\\\u0026_amp:*:*:*:*:*:wordpress:*:*" + ], "school-management-system": [ "cpe:2.3:a:weblizar:school_management_-_education_\\\u0026_learning_management:*:*:*:*:*:wordpress:*:*" ], @@ -14497,6 +14524,9 @@ "shortcode-to-display-post-and-user-data": [ "cpe:2.3:a:vegacorp:display_custom_fields_in_the_frontend_-_post_and_user_profile_fields:*:*:*:*:*:wordpress:*:*" ], + "shortcode-variables": [ + "cpe:2.3:a:yeken:snippet_shortcodes:*:*:*:*:*:wordpress:*:*" + ], "shortcodes-finder": [ "cpe:2.3:a:scribit:shortcodes_finder:*:*:*:*:*:wordpress:*:*" ], @@ -15467,6 +15497,9 @@ "the-holiday-calendar": [ "cpe:2.3:a:theholidaycalendar:the_holiday_calendar:*:*:*:*:*:wordpress:*:*" ], + "the-moneytizer": [ + "cpe:2.3:a:themoneytizer:the_moneytizer:*:*:*:*:*:wordpress:*:*" + ], "the-plus-addons-for-elementor-page-builder": [ "cpe:2.3:a:posimyth:the_plus_addons_for_elementor:*:*:*:*:free:wordpress:*:*", "cpe:2.3:a:posimyth:the_plus_addons_for_elementor_page_builder_lite:*:*:*:*:*:wordpress:*:*" @@ -15833,6 +15866,9 @@ "ultra-companion": [ "cpe:2.3:a:wpoperation:ultra_companion:*:*:*:*:*:wordpress:*:*" ], + "ultraaddons-elementor-lite": [ + "cpe:2.3:a:codeastrology:ultraaddons:*:*:*:*:*:*:*:*" + ], "uncanny-automator": [ "cpe:2.3:a:uncannyowl:uncanny_automator:*:*:*:*:*:wordpress:*:*" ], @@ -18244,6 +18280,9 @@ "yith-woocommerce-product-add-ons": [ "cpe:2.3:a:yithemes:yith_woocommerce_product_add-ons:*:*:*:*:free:wordpress:*:*" ], + "ymc-smart-filter": [ + "cpe:2.3:a:ymc-22:filter_\\\u0026_grids:*:*:*:*:*:wordpress:*:*" + ], "yookassa": [ "cpe:2.3:a:yookassa:yukassa_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], From 125c787e40abec0daa83a50cdaf2d6afd7f40c9f Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Mon, 22 Jul 2024 13:05:04 -0400 Subject: [PATCH 102/284] chore: add debug logging for errors reading RPM files (#3051) Signed-off-by: Keith Zantow --- .../pkg/cataloger/redhat/parse_rpm_archive.go | 39 ++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/syft/pkg/cataloger/redhat/parse_rpm_archive.go b/syft/pkg/cataloger/redhat/parse_rpm_archive.go index 349db9492..8c4b395a7 100644 --- a/syft/pkg/cataloger/redhat/parse_rpm_archive.go +++ b/syft/pkg/cataloger/redhat/parse_rpm_archive.go @@ -8,6 +8,7 @@ import ( rpmdb "github.com/knqyf263/go-rpmdb/pkg" "github.com/sassoftware/go-rpmutils" + "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -26,12 +27,22 @@ func parseRpmArchive(_ context.Context, _ file.Resolver, _ *generic.Environment, return nil, nil, err } - licenses, _ := rpm.Header.GetStrings(rpmutils.LICENSE) - sourceRpm, _ := rpm.Header.GetString(rpmutils.SOURCERPM) - vendor, _ := rpm.Header.GetString(rpmutils.VENDOR) - digestAlgorithm := getDigestAlgorithm(rpm.Header) - size, _ := rpm.Header.InstalledSize() - files, _ := rpm.Header.GetFiles() + licenses, err := rpm.Header.GetStrings(rpmutils.LICENSE) + logRpmArchiveErr(reader.Location, "license", err) + + sourceRpm, err := rpm.Header.GetString(rpmutils.SOURCERPM) + logRpmArchiveErr(reader.Location, "sourcerpm", err) + + vendor, err := rpm.Header.GetString(rpmutils.VENDOR) + logRpmArchiveErr(reader.Location, "vendor", err) + + digestAlgorithm := getDigestAlgorithm(reader.Location, rpm.Header) + + size, err := rpm.Header.InstalledSize() + logRpmArchiveErr(reader.Location, "size", err) + + files, err := rpm.Header.GetFiles() + logRpmArchiveErr(reader.Location, "files", err) metadata := pkg.RpmArchive{ Name: nevra.Name, @@ -48,12 +59,16 @@ func parseRpmArchive(_ context.Context, _ file.Resolver, _ *generic.Environment, return []pkg.Package{newArchivePackage(reader.Location, metadata, licenses)}, nil, nil } -func getDigestAlgorithm(header *rpmutils.RpmHeader) string { - digestAlgorithm, _ := header.GetString(rpmutils.FILEDIGESTALGO) +func getDigestAlgorithm(location file.Location, header *rpmutils.RpmHeader) string { + digestAlgorithm, err := header.GetString(rpmutils.FILEDIGESTALGO) + logRpmArchiveErr(location, "file digest algo", err) + if digestAlgorithm != "" { return digestAlgorithm } - digestAlgorithms, _ := header.GetUint32s(rpmutils.FILEDIGESTALGO) + digestAlgorithms, err := header.GetUint32s(rpmutils.FILEDIGESTALGO) + logRpmArchiveErr(location, "file digest algo 32-bit", err) + if len(digestAlgorithms) > 0 { digestAlgo := int(digestAlgorithms[0]) return rpmutils.GetFileAlgoName(digestAlgo) @@ -91,3 +106,9 @@ func parseEpoch(epoch string) *int { } return &i } + +func logRpmArchiveErr(location file.Location, operation string, err error) { + if err != nil { + log.Debugf("ERROR in parse_rpm_archive %s file: %s: %v", operation, location.RealPath, err) + } +} From fe7c5a71740d8ddf0af14215447f8a7fe934b34f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 10:43:17 -0700 Subject: [PATCH 103/284] chore(deps): bump github.com/charmbracelet/lipgloss from 0.11.1 to 0.12.1 (#3040) * chore(deps): bump github.com/charmbracelet/lipgloss Bumps [github.com/charmbracelet/lipgloss](https://github.com/charmbracelet/lipgloss) from 0.11.1 to 0.12.1. - [Release notes](https://github.com/charmbracelet/lipgloss/releases) - [Changelog](https://github.com/charmbracelet/lipgloss/blob/master/.goreleaser.yml) - [Commits](https://github.com/charmbracelet/lipgloss/compare/v0.11.1...v0.12.1) --- updated-dependencies: - dependency-name: github.com/charmbracelet/lipgloss dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * chore: pin fedora linux/amd64 to sha Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> Signed-off-by: Christopher Angelo Phillips <32073428+spiffcs@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- .../binary/test-fixtures/image-fedora-64bit/Dockerfile | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index dcdc4d5a8..8f0a9cef6 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/bmatcuk/doublestar/v4 v4.6.1 github.com/charmbracelet/bubbles v0.18.0 github.com/charmbracelet/bubbletea v0.26.6 - github.com/charmbracelet/lipgloss v0.11.1 + github.com/charmbracelet/lipgloss v0.12.1 github.com/dave/jennifer v1.7.0 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da github.com/distribution/reference v0.6.0 @@ -109,7 +109,7 @@ require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/becheran/wildmatch-go v1.0.0 // indirect github.com/charmbracelet/harmonica v0.2.0 // indirect - github.com/charmbracelet/x/ansi v0.1.3 // indirect + github.com/charmbracelet/x/ansi v0.1.4 // indirect github.com/charmbracelet/x/input v0.1.0 // indirect github.com/charmbracelet/x/term v0.1.1 // indirect github.com/charmbracelet/x/windows v0.1.0 // indirect diff --git a/go.sum b/go.sum index f023a58a6..4eea6a29e 100644 --- a/go.sum +++ b/go.sum @@ -161,10 +161,10 @@ github.com/charmbracelet/bubbletea v0.26.6 h1:zTCWSuST+3yZYZnVSvbXwKOPRSNZceVeqp github.com/charmbracelet/bubbletea v0.26.6/go.mod h1:dz8CWPlfCCGLFbBlTY4N7bjLiyOGDJEnd2Muu7pOWhk= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= -github.com/charmbracelet/lipgloss v0.11.1 h1:a8KgVPHa7kOoP95vm2tQQrjD2AKhbWmfr4uJ2RW6kNk= -github.com/charmbracelet/lipgloss v0.11.1/go.mod h1:beLlcmkF7MWA+5UrKKIRo/VJ21xGXr7YJ9miWfdMRIU= -github.com/charmbracelet/x/ansi v0.1.3 h1:RBh/eleNWML5R524mjUF0yVRePTwqN9tPtV+DPgO5Lw= -github.com/charmbracelet/x/ansi v0.1.3/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/lipgloss v0.12.1 h1:/gmzszl+pedQpjCOH+wFkZr/N90Snz40J/NR7A0zQcs= +github.com/charmbracelet/lipgloss v0.12.1/go.mod h1:V2CiwIuhx9S1S1ZlADfOj9HmxeMAORuz5izHb0zGbB8= +github.com/charmbracelet/x/ansi v0.1.4 h1:IEU3D6+dWwPSgZ6HBH+v6oUuZ/nVawMiWj5831KfiLM= +github.com/charmbracelet/x/ansi v0.1.4/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/input v0.1.0 h1:TEsGSfZYQyOtp+STIjyBq6tpRaorH0qpwZUj8DavAhQ= github.com/charmbracelet/x/input v0.1.0/go.mod h1:ZZwaBxPF7IG8gWWzPUVqHEtWhc1+HXJPNuerJGRGZ28= github.com/charmbracelet/x/term v0.1.1 h1:3cosVAiPOig+EV4X9U+3LDgtwwAoEzJjNdwbXDjF6yI= diff --git a/syft/pkg/cataloger/binary/test-fixtures/image-fedora-64bit/Dockerfile b/syft/pkg/cataloger/binary/test-fixtures/image-fedora-64bit/Dockerfile index e1c508b85..0d65e7341 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/image-fedora-64bit/Dockerfile +++ b/syft/pkg/cataloger/binary/test-fixtures/image-fedora-64bit/Dockerfile @@ -1,5 +1,6 @@ FROM --platform=linux/amd64 fedora:41@sha256:c05bf79137835bf5c521c58f8252d6031780ae865a0379ab57f412e0ac6b42aa as build + FROM scratch COPY --from=build /bin/sha256sum /sha256sum COPY --from=build /bin/sha1sum /sha1sum From ca945d16e0949a41aa8786f55d21908242b224c8 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:16:25 -0400 Subject: [PATCH 104/284] chore(deps): update tools to latest versions (#3061) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index 0a1dafff5..c5f5aeb43 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -42,7 +42,7 @@ tools: # used for signing the checksums file at release - name: cosign version: - want: v2.2.4 + want: v2.3.0 method: github-release with: repo: sigstore/cosign From 9573f557d12756f8c873b98a6af476835f611055 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 24 Jul 2024 09:34:40 -0400 Subject: [PATCH 105/284] better go mod detection from partial package builds (#3060) Signed-off-by: Alex Goodman --- syft/pkg/cataloger/golang/parse_go_binary.go | 54 +++++++++-- .../cataloger/golang/parse_go_binary_test.go | 97 ++++++++++++++++++- syft/pkg/cataloger/golang/scan_binary.go | 2 +- 3 files changed, 141 insertions(+), 12 deletions(-) diff --git a/syft/pkg/cataloger/golang/parse_go_binary.go b/syft/pkg/cataloger/golang/parse_go_binary.go index 88600355c..4b4962830 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary.go +++ b/syft/pkg/cataloger/golang/parse_go_binary.go @@ -11,6 +11,7 @@ import ( "io" "regexp" "runtime/debug" + "slices" "strings" "time" @@ -97,17 +98,19 @@ func createModuleRelationships(main pkg.Package, deps []pkg.Package) []artifact. return relationships } +var emptyModule debug.Module +var moduleFromPartialPackageBuild = debug.Module{Path: "command-line-arguments"} + func (c *goBinaryCataloger) buildGoPkgInfo(resolver file.Resolver, location file.Location, mod *extendedBuildInfo, arch string, reader io.ReadSeekCloser) (*pkg.Package, []pkg.Package) { - var pkgs []pkg.Package if mod == nil { - return nil, pkgs + return nil, nil } - var empty debug.Module - if mod.Main == empty && mod.Path != "" { - mod.Main = createMainModuleFromPath(mod.Path) + if missingMainModule(mod) { + mod.Main = createMainModuleFromPath(mod) } + var pkgs []pkg.Package for _, dep := range mod.Deps { if dep == nil { continue @@ -130,7 +133,7 @@ func (c *goBinaryCataloger) buildGoPkgInfo(resolver file.Resolver, location file } } - if mod.Main == empty { + if mod.Main == emptyModule { return nil, pkgs } @@ -139,6 +142,16 @@ func (c *goBinaryCataloger) buildGoPkgInfo(resolver file.Resolver, location file return &main, pkgs } +func missingMainModule(mod *extendedBuildInfo) bool { + if mod.Main == emptyModule && mod.Path != "" { + return true + } + // special case: when invoking go build with a source file and not a package (directory) then you will + // see "command-line-arguments" as the main module path... even though that's not the main module. In this + // circumstance, we should treat the main module as missing and search for it within the dependencies. + return mod.Main == moduleFromPartialPackageBuild +} + func (c *goBinaryCataloger) makeGoMainPackage(resolver file.Resolver, mod *extendedBuildInfo, arch string, location file.Location, reader io.ReadSeekCloser) pkg.Package { gbs := getBuildSettings(mod.Settings) gover, experiments := getExperimentsFromVersion(mod.GoVersion) @@ -358,8 +371,29 @@ func getExperimentsFromVersion(version string) (string, []string) { return version, experiments } -func createMainModuleFromPath(path string) (mod debug.Module) { - mod.Path = path - mod.Version = devel - return +func createMainModuleFromPath(existing *extendedBuildInfo) debug.Module { + // search for a main module candidate within the dependencies + var mainModuleCandidates []debug.Module + var usedIndex int + for i, dep := range existing.Deps { + if dep == nil { + continue + } + + if dep.Version == devel { + usedIndex = i + mainModuleCandidates = append(mainModuleCandidates, *dep) + } + } + if len(mainModuleCandidates) == 1 { + // we need to prune the dependency from module list + existing.Deps = slices.Delete(existing.Deps, usedIndex, usedIndex+1) + return mainModuleCandidates[0] + } + + // otherwise craft a main module from the path (a bit of a cop out, but allows us to have a main module) + return debug.Module{ + Path: existing.Path, + Version: devel, + } } diff --git a/syft/pkg/cataloger/golang/parse_go_binary_test.go b/syft/pkg/cataloger/golang/parse_go_binary_test.go index 0346324fe..8b88b9e12 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary_test.go +++ b/syft/pkg/cataloger/golang/parse_go_binary_test.go @@ -210,7 +210,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, { name: "buildGoPkgInfo parses a blank mod and returns no packages", - mod: &extendedBuildInfo{&debug.BuildInfo{}, nil, ""}, + mod: &extendedBuildInfo{BuildInfo: &debug.BuildInfo{}, cryptoSettings: nil, arch: ""}, expected: []pkg.Package(nil), }, { @@ -946,6 +946,95 @@ func TestBuildGoPkgInfo(t *testing.T) { }, }}, }, + { + name: "parse a mod from path (partial build of package)", + mod: &extendedBuildInfo{ + BuildInfo: &debug.BuildInfo{ + GoVersion: "go1.22.2", + Main: debug.Module{Path: "command-line-arguments"}, + Settings: []debug.BuildSetting{ + { + Key: "-ldflags", + Value: `build -ldflags="-w -s -X github.com/kuskoman/logstash-exporter/config.Version=v1.7.0 -X github.com/kuskoman/logstash-exporter/config.GitCommit=db696dbcfe5a91d288d5ad44ce8ccbea97e65978 -X github.com/kuskoman/logstash-exporter/config.BuildDate=2024-07-17T08:12:17Z"`, + }, + {Key: "GOARCH", Value: archDetails}, + {Key: "GOOS", Value: "darwin"}, + {Key: "GOAMD64", Value: "v1"}, + }, + Deps: []*debug.Module{ + { + Path: "github.com/kuskoman/something-else", + Version: "v1.2.3", + }, + { + Path: "github.com/kuskoman/logstash-exporter", + Version: "(devel)", + }, + }, + }, + arch: archDetails, + }, + expected: []pkg.Package{ + { + Name: "github.com/kuskoman/something-else", + Language: pkg.Go, + Type: pkg.GoModulePkg, + Version: "v1.2.3", + PURL: "pkg:golang/github.com/kuskoman/something-else@v1.2.3", + Locations: file.NewLocationSet( + file.NewLocationFromCoordinates( + file.Coordinates{ + RealPath: "/a-path", + FileSystemID: "layer-id", + }, + ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + Metadata: pkg.GolangBinaryBuildinfoEntry{ + GoCompiledVersion: "go1.22.2", + Architecture: archDetails, + MainModule: "github.com/kuskoman/logstash-exporter", // correctly attached the main module + }, + }, + { + Name: "github.com/kuskoman/logstash-exporter", + Language: pkg.Go, + Type: pkg.GoModulePkg, + Version: "v1.7.0", + PURL: "pkg:golang/github.com/kuskoman/logstash-exporter@v1.7.0", + Locations: file.NewLocationSet( + file.NewLocationFromCoordinates( + file.Coordinates{ + RealPath: "/a-path", + FileSystemID: "layer-id", + }, + ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + Metadata: pkg.GolangBinaryBuildinfoEntry{ + GoCompiledVersion: "go1.22.2", + BuildSettings: []pkg.KeyValue{ + { + Key: "-ldflags", + Value: `build -ldflags="-w -s -X github.com/kuskoman/logstash-exporter/config.Version=v1.7.0 -X github.com/kuskoman/logstash-exporter/config.GitCommit=db696dbcfe5a91d288d5ad44ce8ccbea97e65978 -X github.com/kuskoman/logstash-exporter/config.BuildDate=2024-07-17T08:12:17Z"`, + }, + { + Key: "GOARCH", + Value: "amd64", + }, + { + Key: "GOOS", + Value: "darwin", + }, + { + Key: "GOAMD64", + Value: "v1", + }, + }, + Architecture: archDetails, + MainModule: "github.com/kuskoman/logstash-exporter", + }, + }, + }, + }, } for _, test := range tests { @@ -1092,6 +1181,12 @@ func Test_extractVersionFromLDFlags(t *testing.T) { wantMajorVersion: "6", wantFullVersion: "v6.1.7", }, + { + name: "logstash-exporter", + ldflags: `build -ldflags="-w -s -X github.com/kuskoman/logstash-exporter/config.Version=v1.7.0 -X github.com/kuskoman/logstash-exporter/config.GitCommit=db696dbcfe5a91d288d5ad44ce8ccbea97e65978 -X github.com/kuskoman/logstash-exporter/config.BuildDate=2024-07-17T08:12:17Z"`, + wantMajorVersion: "1", + wantFullVersion: "v1.7.0", + }, ////////////////////////////////////////////////////////////////// // negative cases { diff --git a/syft/pkg/cataloger/golang/scan_binary.go b/syft/pkg/cataloger/golang/scan_binary.go index 846e34a11..720008045 100644 --- a/syft/pkg/cataloger/golang/scan_binary.go +++ b/syft/pkg/cataloger/golang/scan_binary.go @@ -56,7 +56,7 @@ func scanFile(reader unionreader.UnionReader, filename string) []*extendedBuildI } } - builds = append(builds, &extendedBuildInfo{bi, v, arch}) + builds = append(builds, &extendedBuildInfo{BuildInfo: bi, cryptoSettings: v, arch: arch}) } return builds } From 741c8fb9bd0cbe1f8b7cf8fdd59709641d21fedd Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Wed, 24 Jul 2024 10:14:20 -0400 Subject: [PATCH 106/284] fix: SPDX output performance with many relationships (#3053) --- .../package_binary_elf_relationships_test.go | 4 +- .../binary/binary_dependencies.go | 35 +- .../binary/binary_dependencies_test.go | 16 +- internal/relationship/index.go | 193 ++++++--- internal/relationship/index_test.go | 404 +++++++++--------- .../common/spdxhelpers/to_format_model.go | 20 +- .../spdxhelpers/to_format_model_test.go | 3 +- syft/pkg/cataloger/python/dependency.go | 8 +- syft/sbom/sbom.go | 4 + 9 files changed, 403 insertions(+), 284 deletions(-) diff --git a/cmd/syft/internal/test/integration/package_binary_elf_relationships_test.go b/cmd/syft/internal/test/integration/package_binary_elf_relationships_test.go index 354c7fba8..a76a30e1e 100644 --- a/cmd/syft/internal/test/integration/package_binary_elf_relationships_test.go +++ b/cmd/syft/internal/test/integration/package_binary_elf_relationships_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/anchore/syft/internal/relationship" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/source" ) @@ -44,12 +45,13 @@ func TestBinaryElfRelationships(t *testing.T) { } } + relationshipIndex := relationship.NewIndex(sbom.Relationships...) for name, expectedDepNames := range expectedGraph { pkgId := nameToId[name] p := sbom.Artifacts.Packages.Package(pkgId) require.NotNil(t, p, "expected package %q to be present in the SBOM", name) - rels := sbom.RelationshipsForPackage(*p, artifact.DependencyOfRelationship) + rels := relationshipIndex.References(*p, artifact.DependencyOfRelationship) require.NotEmpty(t, rels, "expected package %q to have relationships", name) toIds := map[artifact.ID]struct{}{} diff --git a/internal/relationship/binary/binary_dependencies.go b/internal/relationship/binary/binary_dependencies.go index e30b64282..b23b42b9a 100644 --- a/internal/relationship/binary/binary_dependencies.go +++ b/internal/relationship/binary/binary_dependencies.go @@ -21,27 +21,22 @@ func NewDependencyRelationships(resolver file.Resolver, accessor sbomsync.Access // 3. craft package-to-package relationships for each binary that represent shared library dependencies //note: we only care about package-to-package relationships - var relIndex *relationship.Index - accessor.ReadFromSBOM(func(s *sbom.SBOM) { - relIndex = relationship.NewIndex(s.Relationships...) - }) - - return generateRelationships(resolver, accessor, index, relIndex) + return generateRelationships(resolver, accessor, index) } -func generateRelationships(resolver file.Resolver, accessor sbomsync.Accessor, index *sharedLibraryIndex, relIndex *relationship.Index) []artifact.Relationship { - // read all existing dependencyOf relationships +func generateRelationships(resolver file.Resolver, accessor sbomsync.Accessor, index *sharedLibraryIndex) []artifact.Relationship { + newRelationships := relationship.NewIndex() + + // find all package-to-package relationships for shared library dependencies accessor.ReadFromSBOM(func(s *sbom.SBOM) { - for _, r := range s.Relationships { - if r.Type != artifact.DependencyOfRelationship { - continue + relIndex := relationship.NewIndex(s.Relationships...) + + addRelationship := func(r artifact.Relationship) { + if !relIndex.Contains(r) { + newRelationships.Add(r) } - relIndex.Track(r) } - }) - // find all package-to-package relationships for shared library dependencies - accessor.ReadFromSBOM(func(s *sbom.SBOM) { for _, parentPkg := range s.Artifacts.Packages.Sorted(pkg.BinaryPkg) { for _, evidentLocation := range parentPkg.Locations.ToSlice() { if evidentLocation.Annotations[pkg.EvidenceAnnotationKey] != pkg.PrimaryEvidenceAnnotation { @@ -54,12 +49,12 @@ func generateRelationships(resolver file.Resolver, accessor sbomsync.Accessor, i continue } - populateRelationships(exec, parentPkg, resolver, relIndex, index) + populateRelationships(exec, parentPkg, resolver, addRelationship, index) } } }) - return relIndex.NewRelationships() + return newRelationships.All() } // PackagesToRemove returns a list of binary packages (resolved by the ELF cataloger) that should be removed from the SBOM @@ -147,7 +142,7 @@ func getBinaryPackagesToDelete(resolver file.Resolver, s *sbom.SBOM) []artifact. return pkgsToDelete } -func populateRelationships(exec file.Executable, parentPkg pkg.Package, resolver file.Resolver, relIndex *relationship.Index, index *sharedLibraryIndex) { +func populateRelationships(exec file.Executable, parentPkg pkg.Package, resolver file.Resolver, addRelationship func(artifact.Relationship), index *sharedLibraryIndex) { for _, libReference := range exec.ImportedLibraries { // for each library reference, check s.Artifacts.Packages.Sorted(pkg.BinaryPkg) for a binary package that represents that library // if found, create a relationship between the parent package and the library package @@ -167,7 +162,7 @@ func populateRelationships(exec file.Executable, parentPkg pkg.Package, resolver realBaseName := path.Base(loc.RealPath) pkgCollection := index.owningLibraryPackage(realBaseName) if pkgCollection.PackageCount() < 1 { - relIndex.Add( + addRelationship( artifact.Relationship{ From: loc.Coordinates, To: parentPkg, @@ -176,7 +171,7 @@ func populateRelationships(exec file.Executable, parentPkg pkg.Package, resolver ) } for _, p := range pkgCollection.Sorted() { - relIndex.Add( + addRelationship( artifact.Relationship{ From: p, To: parentPkg, diff --git a/internal/relationship/binary/binary_dependencies_test.go b/internal/relationship/binary/binary_dependencies_test.go index 8696b82b4..33c6436c3 100644 --- a/internal/relationship/binary/binary_dependencies_test.go +++ b/internal/relationship/binary/binary_dependencies_test.go @@ -2,6 +2,7 @@ package binary import ( "path" + "strings" "testing" "github.com/google/go-cmp/cmp" @@ -328,7 +329,20 @@ func relationshipComparer(x, y []artifact.Relationship) string { artifact.Relationship{}, file.LocationSet{}, pkg.LicenseSet{}, - )) + ), cmpopts.SortSlices(lessRelationships)) +} + +func lessRelationships(r1, r2 artifact.Relationship) bool { + c := strings.Compare(string(r1.Type), string(r2.Type)) + if c != 0 { + return c < 0 + } + c = strings.Compare(string(r1.From.ID()), string(r2.From.ID())) + if c != 0 { + return c < 0 + } + c = strings.Compare(string(r1.To.ID()), string(r2.To.ID())) + return c < 0 } func newAccessor(pkgs []pkg.Package, coordinateIndex map[file.Coordinates]file.Executable, preexistingRelationships []artifact.Relationship) sbomsync.Accessor { diff --git a/internal/relationship/index.go b/internal/relationship/index.go index e99211606..a94c84f85 100644 --- a/internal/relationship/index.go +++ b/internal/relationship/index.go @@ -1,88 +1,181 @@ package relationship import ( - "github.com/scylladb/go-set/strset" + "slices" + "strings" "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/file" ) +// Index indexes relationships, preventing duplicates type Index struct { - typesByFromTo map[artifact.ID]map[artifact.ID]*strset.Set - existing []artifact.Relationship - additional []artifact.Relationship + all []*sortableRelationship + fromID map[artifact.ID]*mappedRelationships + toID map[artifact.ID]*mappedRelationships } -func NewIndex(existing ...artifact.Relationship) *Index { - r := &Index{ - typesByFromTo: make(map[artifact.ID]map[artifact.ID]*strset.Set), - } - r.TrackAll(existing...) - return r +// NewIndex returns a new relationship Index +func NewIndex(relationships ...artifact.Relationship) *Index { + out := Index{} + out.Add(relationships...) + return &out } -func (i *Index) track(r artifact.Relationship) bool { - fromID := r.From.ID() - if _, ok := i.typesByFromTo[fromID]; !ok { - i.typesByFromTo[fromID] = make(map[artifact.ID]*strset.Set) +// Add adds all the given relationships to the index, without adding duplicates +func (i *Index) Add(relationships ...artifact.Relationship) { + if i.fromID == nil { + i.fromID = map[artifact.ID]*mappedRelationships{} } - - toID := r.To.ID() - if _, ok := i.typesByFromTo[fromID][toID]; !ok { - i.typesByFromTo[fromID][toID] = strset.New() + if i.toID == nil { + i.toID = map[artifact.ID]*mappedRelationships{} } - var exists bool - if i.typesByFromTo[fromID][toID].Has(string(r.Type)) { - exists = true + // store appropriate indexes for stable ordering to minimize ID() calls + for _, r := range relationships { + // prevent duplicates + if i.Contains(r) { + continue + } + + fromID := r.From.ID() + toID := r.To.ID() + + relationship := &sortableRelationship{ + from: fromID, + to: toID, + relationship: r, + } + + // add to all relationships + i.all = append(i.all, relationship) + + // add from -> to mapping + mapped := i.fromID[fromID] + if mapped == nil { + mapped = &mappedRelationships{} + i.fromID[fromID] = mapped + } + mapped.add(toID, relationship) + + // add to -> from mapping + mapped = i.toID[toID] + if mapped == nil { + mapped = &mappedRelationships{} + i.toID[toID] = mapped + } + mapped.add(fromID, relationship) } +} - i.typesByFromTo[fromID][toID].Add(string(r.Type)) +// From returns all relationships from the given identifiable, with specified types +func (i *Index) From(identifiable artifact.Identifiable, types ...artifact.RelationshipType) []artifact.Relationship { + return toSortedSlice(fromMapped(i.fromID, identifiable), types) +} + +// To returns all relationships to the given identifiable, with specified types +func (i *Index) To(identifiable artifact.Identifiable, types ...artifact.RelationshipType) []artifact.Relationship { + return toSortedSlice(fromMapped(i.toID, identifiable), types) +} - return !exists +// References returns all relationships that reference to or from the given identifiable +func (i *Index) References(identifiable artifact.Identifiable, types ...artifact.RelationshipType) []artifact.Relationship { + return toSortedSlice(append(fromMapped(i.fromID, identifiable), fromMapped(i.toID, identifiable)...), types) } -// Track this relationship as "exists" in the index (this is used to prevent duplicate relationships from being added). -// returns true if the relationship is new to the index, false otherwise. -func (i *Index) Track(r artifact.Relationship) bool { - unique := i.track(r) - if unique { - i.existing = append(i.existing, r) +// Coordinates returns all coordinates for the provided identifiable for provided relationship types +// If no types are provided, all relationship types are considered. +func (i *Index) Coordinates(identifiable artifact.Identifiable, types ...artifact.RelationshipType) []file.Coordinates { + var coordinates []file.Coordinates + for _, relationship := range i.References(identifiable, types...) { + cords := extractCoordinates(relationship) + coordinates = append(coordinates, cords...) } - return unique + return coordinates } -// Add a new relationship to the index, returning true if the relationship is new to the index, false otherwise (thus is a duplicate). -func (i *Index) Add(r artifact.Relationship) bool { - if i.track(r) { - i.additional = append(i.additional, r) - return true +// Contains indicates the relationship is present in this index +func (i *Index) Contains(r artifact.Relationship) bool { + if mapped := i.fromID[r.From.ID()]; mapped != nil { + if ids := mapped.typeMap[r.Type]; ids != nil { + return ids[r.To.ID()] != nil + } } return false } -func (i *Index) TrackAll(rs ...artifact.Relationship) { - for _, r := range rs { - i.Track(r) +// All returns a sorted set of relationships matching all types, or all relationships if no types specified +func (i *Index) All(types ...artifact.RelationshipType) []artifact.Relationship { + return toSortedSlice(i.all, types) +} + +func fromMapped(idMap map[artifact.ID]*mappedRelationships, identifiable artifact.Identifiable) []*sortableRelationship { + if identifiable == nil || idMap == nil { + return nil + } + mapped := idMap[identifiable.ID()] + if mapped == nil { + return nil } + return mapped.allRelated } -func (i *Index) AddAll(rs ...artifact.Relationship) { - for _, r := range rs { - i.Add(r) +func toSortedSlice(relationships []*sortableRelationship, types []artifact.RelationshipType) []artifact.Relationship { + // always return sorted for SBOM stability + slices.SortFunc(relationships, sortFunc) + var out []artifact.Relationship + for _, r := range relationships { + if len(types) == 0 || slices.Contains(types, r.relationship.Type) { + out = append(out, r.relationship) + } } + return out } -func (i *Index) NewRelationships() []artifact.Relationship { - return i.additional +func extractCoordinates(relationship artifact.Relationship) (results []file.Coordinates) { + if coordinates, exists := relationship.From.(file.Coordinates); exists { + results = append(results, coordinates) + } + + if coordinates, exists := relationship.To.(file.Coordinates); exists { + results = append(results, coordinates) + } + + return results +} + +type mappedRelationships struct { + typeMap map[artifact.RelationshipType]map[artifact.ID]*sortableRelationship + allRelated []*sortableRelationship +} + +func (m *mappedRelationships) add(id artifact.ID, newRelationship *sortableRelationship) { + m.allRelated = append(m.allRelated, newRelationship) + if m.typeMap == nil { + m.typeMap = map[artifact.RelationshipType]map[artifact.ID]*sortableRelationship{} + } + typeMap := m.typeMap[newRelationship.relationship.Type] + if typeMap == nil { + typeMap = map[artifact.ID]*sortableRelationship{} + m.typeMap[newRelationship.relationship.Type] = typeMap + } + typeMap[id] = newRelationship } -func (i *Index) ExistingRelationships() []artifact.Relationship { - return i.existing +type sortableRelationship struct { + from artifact.ID + to artifact.ID + relationship artifact.Relationship } -func (i *Index) AllUniqueRelationships() []artifact.Relationship { - var all []artifact.Relationship - all = append(all, i.existing...) - all = append(all, i.additional...) - return all +func sortFunc(a, b *sortableRelationship) int { + cmp := strings.Compare(string(a.relationship.Type), string(b.relationship.Type)) + if cmp != 0 { + return cmp + } + cmp = strings.Compare(string(a.from), string(b.from)) + if cmp != 0 { + return cmp + } + return strings.Compare(string(a.to), string(b.to)) } diff --git a/internal/relationship/index_test.go b/internal/relationship/index_test.go index b1acbc214..1f4e66c27 100644 --- a/internal/relationship/index_test.go +++ b/internal/relationship/index_test.go @@ -3,223 +3,231 @@ package relationship import ( "testing" - "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/require" "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" ) -func Test_newRelationshipIndex(t *testing.T) { - from := fakeIdentifiable{id: "from"} - to := fakeIdentifiable{id: "to"} - tests := []struct { - name string - given []artifact.Relationship - track []artifact.Relationship - add []artifact.Relationship - wantExisting []string - wantAdditional []string - }{ - { - name: "empty", - }, - { - name: "tracks existing relationships", - given: []artifact.Relationship{ - { - From: from, - To: to, - Type: artifact.EvidentByRelationship, - }, - }, - wantExisting: []string{"from [evident-by] to"}, - }, - { - name: "deduplicate tracked relationships", - given: []artifact.Relationship{ - { - From: from, - To: to, - Type: artifact.EvidentByRelationship, - }, - { - From: from, - To: to, - Type: artifact.EvidentByRelationship, - }, - { - From: from, - To: to, - Type: artifact.EvidentByRelationship, - }, - }, - track: []artifact.Relationship{ - { - From: from, - To: to, - Type: artifact.EvidentByRelationship, - }, - { - From: from, - To: to, - Type: artifact.EvidentByRelationship, - }, - }, - wantExisting: []string{"from [evident-by] to"}, - }, - { - name: "deduplicate any input relationships", - given: []artifact.Relationship{ - { - From: from, - To: to, - Type: artifact.EvidentByRelationship, - }, - { - From: from, - To: to, - Type: artifact.EvidentByRelationship, - }, - }, - track: []artifact.Relationship{ - { - From: from, - To: to, - Type: artifact.EvidentByRelationship, - }, - { - From: from, - To: to, - Type: artifact.EvidentByRelationship, - }, - }, - add: []artifact.Relationship{ - { - From: from, - To: to, - Type: artifact.EvidentByRelationship, - }, - { - From: from, - To: to, - Type: artifact.EvidentByRelationship, - }, - }, - wantExisting: []string{"from [evident-by] to"}, - }, - { - name: "deduplicate any added relationships", - add: []artifact.Relationship{ - { - From: from, - To: to, - Type: artifact.EvidentByRelationship, - }, - { - From: from, - To: to, - Type: artifact.EvidentByRelationship, - }, - }, - wantAdditional: []string{"from [evident-by] to"}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - idx := NewIndex(tt.given...) - idx.TrackAll(tt.track...) - idx.AddAll(tt.add...) - diffRelationships(t, tt.wantExisting, idx.existing) - diffRelationships(t, tt.wantAdditional, idx.additional) - }) +func Test_Index(t *testing.T) { + p1 := pkg.Package{ + Name: "pkg-1", + } + p2 := pkg.Package{ + Name: "pkg-2", + } + p3 := pkg.Package{ + Name: "pkg-3", + } + c1 := file.Coordinates{ + RealPath: "/coords/1", + } + c2 := file.Coordinates{ + RealPath: "/coords/2", } -} -func diffRelationships(t *testing.T, expected []string, actual []artifact.Relationship) { - if d := cmp.Diff(expected, stringRelationships(actual)); d != "" { - t.Errorf("unexpected relationships (-want, +got): %s", d) + for _, p := range []*pkg.Package{&p1, &p2, &p3} { + p.SetID() + } + + r1 := artifact.Relationship{ + From: p1, + To: p2, + Type: artifact.DependencyOfRelationship, + } + r2 := artifact.Relationship{ + From: p1, + To: p3, + Type: artifact.DependencyOfRelationship, + } + r3 := artifact.Relationship{ + From: p1, + To: c1, + Type: artifact.ContainsRelationship, + } + r4 := artifact.Relationship{ + From: p2, + To: c2, + Type: artifact.ContainsRelationship, + } + r5 := artifact.Relationship{ + From: p3, + To: c2, + Type: artifact.ContainsRelationship, } -} -func stringRelationships(relationships []artifact.Relationship) []string { - var result []string - for _, r := range relationships { - result = append(result, string(r.From.ID())+" ["+string(r.Type)+"] "+string(r.To.ID())) + dup := artifact.Relationship{ + From: p3, + To: c2, + Type: artifact.ContainsRelationship, } - return result + idx := NewIndex(r1, r2, r3, r4, r5, dup) + require.ElementsMatch(t, slice(r1, r2, r3, r4, r5), idx.All()) + + require.ElementsMatch(t, slice(r1, r4), idx.References(p2)) + require.ElementsMatch(t, slice(r4), idx.References(p2, artifact.ContainsRelationship)) + + require.ElementsMatch(t, slice(r1), idx.To(p2)) + require.ElementsMatch(t, []artifact.Relationship(nil), idx.To(p2, artifact.ContainsRelationship)) + + require.ElementsMatch(t, slice(r4), idx.From(p2)) + require.ElementsMatch(t, slice(r4), idx.From(p2, artifact.ContainsRelationship)) } -func Test_relationshipIndex_track(t *testing.T) { - from := fakeIdentifiable{id: "from"} - to := fakeIdentifiable{id: "to"} - relationship := artifact.Relationship{From: from, To: to, Type: artifact.EvidentByRelationship} - tests := []struct { - name string - existing []artifact.Relationship - given artifact.Relationship - want bool - }{ - { - name: "track returns true for a new relationship", - existing: []artifact.Relationship{}, - given: relationship, - want: true, - }, - { - name: "track returns false for an existing relationship", - existing: []artifact.Relationship{relationship}, - given: relationship, - want: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - i := NewIndex(tt.existing...) - if got := i.Track(tt.given); got != tt.want { - t.Errorf("track() = %v, want %v", got, tt.want) - } - }) +func Test_sortOrder(t *testing.T) { + r1 := artifact.Relationship{ + From: id("1"), + To: id("2"), + Type: "1", + } + r2 := artifact.Relationship{ + From: id("2"), + To: id("3"), + Type: "1", + } + r3 := artifact.Relationship{ + From: id("3"), + To: id("4"), + Type: "1", + } + r4 := artifact.Relationship{ + From: id("1"), + To: id("2"), + Type: "2", + } + r5 := artifact.Relationship{ + From: id("2"), + To: id("3"), + Type: "2", + } + dup := artifact.Relationship{ + From: id("2"), + To: id("3"), + Type: "2", + } + r6 := artifact.Relationship{ + From: id("2"), + To: id("3"), + Type: "3", } + + idx := NewIndex(r5, r2, r6, r4, r1, r3, dup) + require.EqualValues(t, slice(r1, r2, r3, r4, r5, r6), idx.All()) + + require.EqualValues(t, slice(r1, r4), idx.From(id("1"))) + + require.EqualValues(t, slice(r2, r5, r6), idx.To(id("3"))) + + rLast := artifact.Relationship{ + From: id("0"), + To: id("3"), + Type: "9999", + } + + rFirst := artifact.Relationship{ + From: id("0"), + To: id("3"), + Type: "1", + } + + rMid := artifact.Relationship{ + From: id("0"), + To: id("1"), + Type: "2", + } + + idx.Add(rLast, rFirst, rMid) + + require.EqualValues(t, slice(rFirst, r1, r2, r3, rMid, r4, r5, r6, rLast), idx.All()) + + require.EqualValues(t, slice(rFirst, r2, r5, r6, rLast), idx.To(id("3"))) } -func Test_relationshipIndex_add(t *testing.T) { - from := fakeIdentifiable{id: "from"} - to := fakeIdentifiable{id: "to"} - relationship := artifact.Relationship{From: from, To: to, Type: artifact.EvidentByRelationship} - tests := []struct { - name string - existing []artifact.Relationship - given artifact.Relationship - want bool - }{ - { - name: "add returns true for a new relationship", - existing: []artifact.Relationship{}, - given: relationship, - want: true, - }, - { - name: "add returns false for an existing relationship", - existing: []artifact.Relationship{relationship}, - given: relationship, - want: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - i := NewIndex(tt.existing...) - if got := i.Add(tt.given); got != tt.want { - t.Errorf("add() = %v, want %v", got, tt.want) - } - }) +func Test_Coordinates(t *testing.T) { + p1 := pkg.Package{ + Name: "pkg-1", + } + p2 := pkg.Package{ + Name: "pkg-2", + } + p3 := pkg.Package{ + Name: "pkg-3", + } + c1 := file.Coordinates{ + RealPath: "/coords/1", + } + c2 := file.Coordinates{ + RealPath: "/coords/2", + } + c3 := file.Coordinates{ + RealPath: "/coords/3", + } + c4 := file.Coordinates{ + RealPath: "/coords/4", + } + + for _, p := range []*pkg.Package{&p1, &p2, &p3} { + p.SetID() } + r1 := artifact.Relationship{ + From: p1, + To: p2, + Type: artifact.DependencyOfRelationship, + } + r2 := artifact.Relationship{ + From: p1, + To: p3, + Type: artifact.DependencyOfRelationship, + } + r3 := artifact.Relationship{ + From: p1, + To: c1, + Type: artifact.ContainsRelationship, + } + r4 := artifact.Relationship{ + From: p2, + To: c2, + Type: artifact.ContainsRelationship, + } + r5 := artifact.Relationship{ + From: p3, + To: c1, + Type: artifact.ContainsRelationship, + } + r6 := artifact.Relationship{ + From: p3, + To: c2, + Type: artifact.ContainsRelationship, + } + r7 := artifact.Relationship{ + From: c1, + To: c3, + Type: artifact.ContainsRelationship, + } + r8 := artifact.Relationship{ + From: c3, + To: c4, + Type: artifact.ContainsRelationship, + } + + idx := NewIndex(r1, r2, r3, r4, r5, r6, r7, r8) + + got := idx.Coordinates(p1) + require.ElementsMatch(t, slice(c1), got) + + got = idx.Coordinates(p3) + require.ElementsMatch(t, slice(c1, c2), got) } -type fakeIdentifiable struct { - id string +type id string + +func (i id) ID() artifact.ID { + return artifact.ID(i) } -func (f fakeIdentifiable) ID() artifact.ID { - return artifact.ID(f.id) +func slice[T any](values ...T) []T { + return values } diff --git a/syft/format/common/spdxhelpers/to_format_model.go b/syft/format/common/spdxhelpers/to_format_model.go index 767ffdcbe..3fd136e84 100644 --- a/syft/format/common/spdxhelpers/to_format_model.go +++ b/syft/format/common/spdxhelpers/to_format_model.go @@ -16,6 +16,7 @@ import ( "github.com/anchore/packageurl-go" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/mimetype" + "github.com/anchore/syft/internal/relationship" "github.com/anchore/syft/internal/spdxlicense" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" @@ -45,9 +46,10 @@ const ( func ToFormatModel(s sbom.SBOM) *spdx.Document { name, namespace := helpers.DocumentNameAndNamespace(s.Source, s.Descriptor) - packages := toPackages(s.Artifacts.Packages, s) + rels := relationship.NewIndex(s.Relationships...) + packages := toPackages(rels, s.Artifacts.Packages, s) - relationships := toRelationships(s.RelationshipsSorted()) + allRelationships := toRelationships(rels.All()) // for valid SPDX we need a document describes relationship describesID := spdx.ElementID("DOCUMENT") @@ -57,7 +59,7 @@ func ToFormatModel(s sbom.SBOM) *spdx.Document { describesID = rootPackage.PackageSPDXIdentifier // add all relationships from the document root to all other packages - relationships = append(relationships, toRootRelationships(rootPackage, packages)...) + allRelationships = append(allRelationships, toRootRelationships(rootPackage, packages)...) // append the root package packages = append(packages, rootPackage) @@ -75,7 +77,7 @@ func ToFormatModel(s sbom.SBOM) *spdx.Document { } // add the root document relationship - relationships = append(relationships, documentDescribesRelationship) + allRelationships = append(allRelationships, documentDescribesRelationship) return &spdx.Document{ // 6.1: SPDX Version; should be in the format "SPDX-x.x" @@ -150,7 +152,7 @@ func ToFormatModel(s sbom.SBOM) *spdx.Document { }, Packages: packages, Files: toFiles(s), - Relationships: relationships, + Relationships: allRelationships, OtherLicenses: toOtherLicenses(s.Artifacts.Packages), } } @@ -302,7 +304,7 @@ func toSPDXID(identifiable artifact.Identifiable) spdx.ElementID { // packages populates all Package Information from the package Collection (see https://spdx.github.io/spdx-spec/3-package-information/) // //nolint:funlen -func toPackages(catalog *pkg.Collection, sbom sbom.SBOM) (results []*spdx.Package) { +func toPackages(rels *relationship.Index, catalog *pkg.Collection, sbom sbom.SBOM) (results []*spdx.Package) { for _, p := range catalog.Sorted() { // name should be guaranteed to be unique, but semantically useful and stable id := toSPDXID(p) @@ -318,7 +320,7 @@ func toPackages(catalog *pkg.Collection, sbom sbom.SBOM) (results []*spdx.Packag // 2. syft has generated a sha1 digest for the package's contents packageChecksums, filesAnalyzed := toPackageChecksums(p) - packageVerificationCode := newPackageVerificationCode(p, sbom) + packageVerificationCode := newPackageVerificationCode(rels, p, sbom) if packageVerificationCode != nil { filesAnalyzed = true } @@ -744,12 +746,12 @@ func toOtherLicenses(catalog *pkg.Collection) []*spdx.OtherLicense { // f file is an "excludes" file, skip it /* exclude SPDX analysis file(s) */ // see: https://spdx.github.io/spdx-spec/v2.3/package-information/#79-package-verification-code-field // the above link contains the SPDX algorithm for a package verification code -func newPackageVerificationCode(p pkg.Package, sbom sbom.SBOM) *spdx.PackageVerificationCode { +func newPackageVerificationCode(rels *relationship.Index, p pkg.Package, sbom sbom.SBOM) *spdx.PackageVerificationCode { // key off of the contains relationship; // spdx validator will fail if a package claims to contain a file but no sha1 provided // if a sha1 for a file is provided then the validator will fail if the package does not have // a package verification code - coordinates := sbom.CoordinatesForPackage(p, artifact.ContainsRelationship) + coordinates := rels.Coordinates(p, artifact.ContainsRelationship) var digests []file.Digest for _, c := range coordinates { digest := sbom.Artifacts.FileDigests[c] diff --git a/syft/format/common/spdxhelpers/to_format_model_test.go b/syft/format/common/spdxhelpers/to_format_model_test.go index c2f181f0d..e986069bb 100644 --- a/syft/format/common/spdxhelpers/to_format_model_test.go +++ b/syft/format/common/spdxhelpers/to_format_model_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/anchore/syft/internal/relationship" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/format/internal/spdxutil/helpers" @@ -665,7 +666,7 @@ func Test_H1Digest(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { catalog := pkg.NewCollection(test.pkg) - pkgs := toPackages(catalog, s) + pkgs := toPackages(relationship.NewIndex(), catalog, s) require.Len(t, pkgs, 1) for _, p := range pkgs { if test.expectedDigest == "" { diff --git a/syft/pkg/cataloger/python/dependency.go b/syft/pkg/cataloger/python/dependency.go index 7479649d0..6110281e9 100644 --- a/syft/pkg/cataloger/python/dependency.go +++ b/syft/pkg/cataloger/python/dependency.go @@ -167,7 +167,7 @@ func wheelEggRelationships(ctx context.Context, resolver file.Resolver, pkgs []p if err != nil { return nil, nil, fmt.Errorf("failed to resolve relationships for global site package %q: %w", globalSitePackage, err) } - relationshipIndex.AddAll(siteRels...) + relationshipIndex.Add(siteRels...) } // create relationships between packages within each virtual env site package directory (that doesn't link to a global site-packages directory) @@ -180,7 +180,7 @@ func wheelEggRelationships(ctx context.Context, resolver file.Resolver, pkgs []p if err != nil { return nil, nil, fmt.Errorf("failed to resolve relationships for virtualenv site package %q: %w", venv.SitePackagesPath, err) } - relationshipIndex.AddAll(siteRels...) + relationshipIndex.Add(siteRels...) } // create relationships between packages within each virtual env site package directory (that links to a global site package directory) @@ -197,10 +197,10 @@ func wheelEggRelationships(ctx context.Context, resolver file.Resolver, pkgs []p return nil, nil, fmt.Errorf("failed to resolve relationships for virtualenv + global site package path %q + %q: %w", venv.SitePackagesPath, globalSitePackage, err) } - relationshipIndex.AddAll(siteRels...) + relationshipIndex.Add(siteRels...) } - return pkgs, relationshipIndex.AllUniqueRelationships(), err + return pkgs, relationshipIndex.All(), err } func collectPackages(pkgsBySitePackageAndName map[string]map[string]pkg.Package, sites []string) []pkg.Package { diff --git a/syft/sbom/sbom.go b/syft/sbom/sbom.go index b3f3cd74f..ba3f95f3d 100644 --- a/syft/sbom/sbom.go +++ b/syft/sbom/sbom.go @@ -35,6 +35,8 @@ type Descriptor struct { Configuration interface{} } +// RelationshipsSorted returns a sorted slice of all relationships +// Deprecated -- use relationship.Index func (s SBOM) RelationshipsSorted() []artifact.Relationship { relationships := s.Relationships sort.SliceStable(relationships, func(i, j int) bool { @@ -70,6 +72,7 @@ func (s SBOM) AllCoordinates() []file.Coordinates { // RelationshipsForPackage returns all relationships for the provided types. // If no types are provided, all relationships for the package are returned. +// Deprecated -- use relationship.Index func (s SBOM) RelationshipsForPackage(p pkg.Package, rt ...artifact.RelationshipType) []artifact.Relationship { if len(rt) == 0 { rt = artifact.AllRelationshipTypes() @@ -103,6 +106,7 @@ func (s SBOM) RelationshipsForPackage(p pkg.Package, rt ...artifact.Relationship // CoordinatesForPackage returns all coordinates for the provided package for provided relationship types // If no types are provided, all relationship types are considered. +// Deprecated -- use relationship.Index func (s SBOM) CoordinatesForPackage(p pkg.Package, rt ...artifact.RelationshipType) []file.Coordinates { var coordinates []file.Coordinates for _, relationship := range s.RelationshipsForPackage(p, rt...) { From 3917989f864ea5645b0d96467637332a198f1fb0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Jul 2024 13:50:06 -0400 Subject: [PATCH 107/284] chore(deps): bump github/codeql-action from 3.25.13 to 3.25.14 (#3072) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.13 to 3.25.14. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/2d790406f505036ef40ecba973cc774a50395aac...5cf07d8b700b67e235fbb65cbc84f69c0cf10464) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e92c3d4fc..58c2ae72a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@2d790406f505036ef40ecba973cc774a50395aac #v3.25.13 + uses: github/codeql-action/init@5cf07d8b700b67e235fbb65cbc84f69c0cf10464 #v3.25.14 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@2d790406f505036ef40ecba973cc774a50395aac #v3.25.13 + uses: github/codeql-action/autobuild@5cf07d8b700b67e235fbb65cbc84f69c0cf10464 #v3.25.14 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@2d790406f505036ef40ecba973cc774a50395aac #v3.25.13 + uses: github/codeql-action/analyze@5cf07d8b700b67e235fbb65cbc84f69c0cf10464 #v3.25.14 From 68b96ae444d5b46cf552728aab307b7d7e70c1b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Jul 2024 13:50:33 -0400 Subject: [PATCH 108/284] chore(deps): bump github.com/docker/docker (#3066) Bumps [github.com/docker/docker](https://github.com/docker/docker) from 27.1.0+incompatible to 27.1.1+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.1.0...v27.1.1) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8f0a9cef6..ec2085c73 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/dave/jennifer v1.7.0 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da github.com/distribution/reference v0.6.0 - github.com/docker/docker v27.1.0+incompatible + github.com/docker/docker v27.1.1+incompatible github.com/dustin/go-humanize v1.0.1 github.com/elliotchance/phpserialize v1.4.0 github.com/facebookincubator/nvdtools v0.1.5 diff --git a/go.sum b/go.sum index 4eea6a29e..c129b300f 100644 --- a/go.sum +++ b/go.sum @@ -231,8 +231,8 @@ github.com/docker/cli v27.0.3+incompatible h1:usGs0/BoBW8MWxGeEtqPMkzOY56jZ6kYlS github.com/docker/cli v27.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= From 36f95d682895c1a95d949fc9328260861e116c00 Mon Sep 17 00:00:00 2001 From: mikcl <43545032+Mikcl@users.noreply.github.com> Date: Thu, 25 Jul 2024 18:54:13 +0100 Subject: [PATCH 109/284] python-cataloger: normalize package names (#3069) Signed-off-by: mikcl --- .../catalog_packages_cases_test.go | 4 ++-- syft/pkg/cataloger/python/cataloger_test.go | 16 ++++++------- syft/pkg/cataloger/python/package.go | 21 ++++++++++++++-- syft/pkg/cataloger/python/package_test.go | 18 ++++++++++++++ .../python/parse_requirements_test.go | 24 ++++++++++++++----- .../test-fixtures/requires/requirements.txt | 1 + 6 files changed, 66 insertions(+), 18 deletions(-) diff --git a/cmd/syft/internal/test/integration/catalog_packages_cases_test.go b/cmd/syft/internal/test/integration/catalog_packages_cases_test.go index 188b4ae45..ff21bd1c1 100644 --- a/cmd/syft/internal/test/integration/catalog_packages_cases_test.go +++ b/cmd/syft/internal/test/integration/catalog_packages_cases_test.go @@ -35,7 +35,7 @@ var imageOnlyTestCases = []testCase{ pkgType: pkg.PythonPkg, pkgLanguage: pkg.Python, pkgInfo: map[string]string{ - "Pygments": "2.6.1", + "pygments": "2.6.1", "requests": "2.22.0", "somerequests": "3.22.0", "someotherpkg": "3.19.0", @@ -172,7 +172,7 @@ var dirOnlyTestCases = []testCase{ "passlib": "1.7.2", "mypy": "v0.770", // common to image and directory - "Pygments": "2.6.1", + "pygments": "2.6.1", "requests": "2.22.0", "somerequests": "3.22.0", "someotherpkg": "3.19.0", diff --git a/syft/pkg/cataloger/python/cataloger_test.go b/syft/pkg/cataloger/python/cataloger_test.go index e1093a55a..f3fc06017 100644 --- a/syft/pkg/cataloger/python/cataloger_test.go +++ b/syft/pkg/cataloger/python/cataloger_test.go @@ -119,9 +119,9 @@ func Test_PackageCataloger(t *testing.T) { "test-fixtures/dist-info/direct_url.json", }, expectedPackage: pkg.Package{ - Name: "Pygments", + Name: "pygments", Version: "2.6.1", - PURL: "pkg:pypi/Pygments@2.6.1?vcs_url=git%2Bhttps://github.com/python-test/test.git%40aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + PURL: "pkg:pypi/pygments@2.6.1?vcs_url=git%2Bhttps://github.com/python-test/test.git%40aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", Type: pkg.PythonPkg, Language: pkg.Python, Licenses: pkg.NewLicenseSet( @@ -161,9 +161,9 @@ func Test_PackageCataloger(t *testing.T) { "test-fixtures/casesensitive/DIST-INFO/direct_url.json", }, expectedPackage: pkg.Package{ - Name: "Pygments", + Name: "pygments", Version: "2.6.1", - PURL: "pkg:pypi/Pygments@2.6.1?vcs_url=git%2Bhttps://github.com/python-test/test.git%40aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + PURL: "pkg:pypi/pygments@2.6.1?vcs_url=git%2Bhttps://github.com/python-test/test.git%40aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", Type: pkg.PythonPkg, Language: pkg.Python, Licenses: pkg.NewLicenseSet( @@ -199,9 +199,9 @@ func Test_PackageCataloger(t *testing.T) { "test-fixtures/malformed-record/dist-info/RECORD", }, expectedPackage: pkg.Package{ - Name: "Pygments", + Name: "pygments", Version: "2.6.1", - PURL: "pkg:pypi/Pygments@2.6.1", + PURL: "pkg:pypi/pygments@2.6.1", Type: pkg.PythonPkg, Language: pkg.Python, Licenses: pkg.NewLicenseSet( @@ -231,9 +231,9 @@ func Test_PackageCataloger(t *testing.T) { name: "partial dist-info directory", fixtures: []string{"test-fixtures/partial.dist-info/METADATA"}, expectedPackage: pkg.Package{ - Name: "Pygments", + Name: "pygments", Version: "2.6.1", - PURL: "pkg:pypi/Pygments@2.6.1", + PURL: "pkg:pypi/pygments@2.6.1", Type: pkg.PythonPkg, Language: pkg.Python, Licenses: pkg.NewLicenseSet( diff --git a/syft/pkg/cataloger/python/package.go b/syft/pkg/cataloger/python/package.go index f2d51ac32..e574d583a 100644 --- a/syft/pkg/cataloger/python/package.go +++ b/syft/pkg/cataloger/python/package.go @@ -2,6 +2,8 @@ package python import ( "fmt" + "regexp" + "strings" "github.com/anchore/packageurl-go" "github.com/anchore/syft/internal/licenses" @@ -10,7 +12,16 @@ import ( "github.com/anchore/syft/syft/pkg" ) +func normalize(name string) string { + // https://packaging.python.org/en/latest/specifications/name-normalization/ + re := regexp.MustCompile(`[-_.]+`) + normalized := re.ReplaceAllString(name, "-") + return strings.ToLower(normalized) +} + func newPackageForIndex(name, version string, locations ...file.Location) pkg.Package { + name = normalize(name) + p := pkg.Package{ Name: name, Version: version, @@ -26,6 +37,8 @@ func newPackageForIndex(name, version string, locations ...file.Location) pkg.Pa } func newPackageForIndexWithMetadata(name, version string, metadata interface{}, locations ...file.Location) pkg.Package { + name = normalize(name) + p := pkg.Package{ Name: name, Version: version, @@ -42,6 +55,8 @@ func newPackageForIndexWithMetadata(name, version string, metadata interface{}, } func newPackageForRequirementsWithMetadata(name, version string, metadata pkg.PythonRequirementsEntry, locations ...file.Location) pkg.Package { + name = normalize(name) + p := pkg.Package{ Name: name, Version: version, @@ -87,10 +102,12 @@ func newPackageForPackage(resolver file.Resolver, m parsedData, sources ...file. } } + name := normalize(m.Name) + p := pkg.Package{ - Name: m.Name, + Name: name, Version: m.Version, - PURL: packageURL(m.Name, m.Version, &m.PythonPackage), + PURL: packageURL(name, m.Version, &m.PythonPackage), Locations: file.NewLocationSet(sources...), Licenses: licenseSet, Language: pkg.Python, diff --git a/syft/pkg/cataloger/python/package_test.go b/syft/pkg/cataloger/python/package_test.go index 0b88336a7..a9b9238ab 100644 --- a/syft/pkg/cataloger/python/package_test.go +++ b/syft/pkg/cataloger/python/package_test.go @@ -44,3 +44,21 @@ func Test_packageURL(t *testing.T) { }) } } + +func Test_normalization(t *testing.T) { + normalForm := "friendly-bard" + tests := []string{ + normalForm, + "Friendly-Bard", + "FRIENDLY-BARD", + "friendly.bard", + "friendly_bard", + "friendly--bard", + "FrIeNdLy-._.-bArD", + } + for _, tt := range tests { + t.Run(tt, func(t *testing.T) { + assert.Equal(t, normalForm, normalize(tt)) + }) + } +} diff --git a/syft/pkg/cataloger/python/parse_requirements_test.go b/syft/pkg/cataloger/python/parse_requirements_test.go index fe6d8c343..ebd67549a 100644 --- a/syft/pkg/cataloger/python/parse_requirements_test.go +++ b/syft/pkg/cataloger/python/parse_requirements_test.go @@ -41,9 +41,9 @@ func TestParseRequirementsTxt(t *testing.T) { }, }, { - Name: "SomeProject", + Name: "someproject", Version: "5.4", - PURL: "pkg:pypi/SomeProject@5.4", + PURL: "pkg:pypi/someproject@5.4", Locations: locations, Language: pkg.Python, Type: pkg.PythonPkg, @@ -91,9 +91,9 @@ func TestParseRequirementsTxt(t *testing.T) { }, }, { - Name: "GithubSampleProject", + Name: "githubsampleproject", Version: "3.7.1", - PURL: "pkg:pypi/GithubSampleProject@3.7.1", + PURL: "pkg:pypi/githubsampleproject@3.7.1", Locations: locations, Language: pkg.Python, Type: pkg.PythonPkg, @@ -103,6 +103,18 @@ func TestParseRequirementsTxt(t *testing.T) { URL: "git+https://github.com/owner/repo@releases/tag/v3.7.1", }, }, + { + Name: "friendly-bard", + Version: "1.0.0", + PURL: "pkg:pypi/friendly-bard@1.0.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Metadata: pkg.PythonRequirementsEntry{ + Name: "FrIeNdLy-_-bArD", + VersionConstraint: "== 1.0.0", + }, + }, } var testCases = []struct { @@ -128,9 +140,9 @@ func TestParseRequirementsTxt(t *testing.T) { }, expectedPkgs: append([]pkg.Package{ { - Name: "Mopidy-Dirble", + Name: "mopidy-dirble", Version: "1.1", - PURL: "pkg:pypi/Mopidy-Dirble@1.1", + PURL: "pkg:pypi/mopidy-dirble@1.1", Locations: locations, Language: pkg.Python, Type: pkg.PythonPkg, diff --git a/syft/pkg/cataloger/python/test-fixtures/requires/requirements.txt b/syft/pkg/cataloger/python/test-fixtures/requires/requirements.txt index 188258bb7..15d60947a 100644 --- a/syft/pkg/cataloger/python/test-fixtures/requires/requirements.txt +++ b/syft/pkg/cataloger/python/test-fixtures/requires/requirements.txt @@ -22,3 +22,4 @@ argh==0.26.3 --hash=sha256:a9b3aaa1904eeb78e32394cd46c6f37ac0fb4af6dc488daa58971 celery[redis, pytest] == 4.4.7 # should remove [redis, pytest] requests[security] == 2.8.* ; python_version < "2.7" and sys_platform == "linux" GithubSampleProject == 3.7.1 @ git+https://github.com/owner/repo@releases/tag/v3.7.1 +FrIeNdLy-_-bArD == 1.0.0 From b3848f780f74e45b405053e2e9ec5448aa12faa9 Mon Sep 17 00:00:00 2001 From: mikcl <43545032+Mikcl@users.noreply.github.com> Date: Thu, 25 Jul 2024 18:56:10 +0100 Subject: [PATCH 110/284] python cataloger: allow dots in python package names (#3070) Signed-off-by: mikcl --- syft/pkg/cataloger/python/parse_requirements.go | 2 +- syft/pkg/cataloger/python/parse_requirements_test.go | 12 ++++++++++++ .../python/test-fixtures/requires/requirements.txt | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/syft/pkg/cataloger/python/parse_requirements.go b/syft/pkg/cataloger/python/parse_requirements.go index 7ef49f662..38bbde3e8 100644 --- a/syft/pkg/cataloger/python/parse_requirements.go +++ b/syft/pkg/cataloger/python/parse_requirements.go @@ -26,7 +26,7 @@ const ( // --hash=sha256:e9535b8c84dc9571a48999094fda7f33e63c3f1b74f3e5f3ac0105a58405bb65 # some comment // namePattern matches: requests[security] - namePattern = `(?P\w[\w\[\],\s-_]+)` + namePattern = `(?P\w[\w\[\],\s-_\.]+)` // versionConstraintPattern matches: == 2.8.* versionConstraintPattern = `(?P([^\S\r\n]*[~=>!<]+\s*[0-9a-zA-Z.*]+[^\S\r\n]*,?)+)?(@[^\S\r\n]*(?P[^;]*))?` diff --git a/syft/pkg/cataloger/python/parse_requirements_test.go b/syft/pkg/cataloger/python/parse_requirements_test.go index ebd67549a..139b0b62a 100644 --- a/syft/pkg/cataloger/python/parse_requirements_test.go +++ b/syft/pkg/cataloger/python/parse_requirements_test.go @@ -53,6 +53,18 @@ func TestParseRequirementsTxt(t *testing.T) { Markers: "python_version < '3.8'", }, }, + { + Name: "dots-._allowed", + Version: "1.0.0", + PURL: "pkg:pypi/dots-._allowed@1.0.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Metadata: pkg.PythonRequirementsEntry{ + Name: "dots-._allowed", + VersionConstraint: "== 1.0.0", + }, + }, { Name: "argh", Version: "0.26.2", diff --git a/syft/pkg/cataloger/python/test-fixtures/requires/requirements.txt b/syft/pkg/cataloger/python/test-fixtures/requires/requirements.txt index 15d60947a..a238ccdcf 100644 --- a/syft/pkg/cataloger/python/test-fixtures/requires/requirements.txt +++ b/syft/pkg/cataloger/python/test-fixtures/requires/requirements.txt @@ -8,6 +8,7 @@ bar >= 1.0.0, <= 2.0.0, \ -r other-requirements.txt --requirements super-secretrequirements.txt SomeProject ==5.4 ; python_version < '3.8' +dots-._allowed == 1.0.0 coverage != 3.5 # Version Exclusion. Anything except version 3.5 numpyNew; sys_platform == 'win32' numpy >= 3.4.1; sys_platform == 'win32' From 4882d2e8ce73657100bc1f464f8e6bf6f8a96d07 Mon Sep 17 00:00:00 2001 From: Laurent Goderre Date: Thu, 25 Jul 2024 13:56:55 -0400 Subject: [PATCH 111/284] Only match ldflag version if it matches the main module or targets main.version (#3062) Signed-off-by: Laurent Goderre --- syft/pkg/cataloger/golang/parse_go_binary.go | 7 +-- .../cataloger/golang/parse_go_binary_test.go | 51 +++++++++++++++---- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/syft/pkg/cataloger/golang/parse_go_binary.go b/syft/pkg/cataloger/golang/parse_go_binary.go index 4b4962830..7f186ecba 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary.go +++ b/syft/pkg/cataloger/golang/parse_go_binary.go @@ -208,7 +208,7 @@ func (c *goBinaryCataloger) findMainModuleVersion(metadata *pkg.GolangBinaryBuil // version of the package. ldflags, _ = metadata.BuildSettings.Get("-ldflags") - majorVersion, fullVersion = extractVersionFromLDFlags(ldflags) + majorVersion, fullVersion = extractVersionFromLDFlags(ldflags, metadata.MainModule) if fullVersion != "" { return fullVersion } @@ -258,13 +258,14 @@ func extractVersionFromContents(reader io.Reader) string { return "" } -func extractVersionFromLDFlags(ldflags string) (majorVersion string, fullVersion string) { +func extractVersionFromLDFlags(ldflags string, maimModule string) (majorVersion string, fullVersion string) { if ldflags == "" { return "", "" } for _, pattern := range knownBuildFlagPatterns { - groups := internal.MatchNamedCaptureGroups(pattern, ldflags) + newPattern := regexp.MustCompile(fmt.Sprintf(`(main|%s\/[^\s]*)%s`, strings.ReplaceAll(maimModule, "/", "\\/"), pattern.String())) + groups := internal.MatchNamedCaptureGroups(newPattern, ldflags) v, ok := groups["version"] if !ok { diff --git a/syft/pkg/cataloger/golang/parse_go_binary_test.go b/syft/pkg/cataloger/golang/parse_go_binary_test.go index 8b88b9e12..75659ae65 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary_test.go +++ b/syft/pkg/cataloger/golang/parse_go_binary_test.go @@ -1068,6 +1068,7 @@ func TestBuildGoPkgInfo(t *testing.T) { func Test_extractVersionFromLDFlags(t *testing.T) { tests := []struct { name string + mainModule string ldflags string wantMajorVersion string wantFullVersion string @@ -1078,12 +1079,14 @@ func Test_extractVersionFromLDFlags(t *testing.T) { }, { name: "syft ldflags", + mainModule: "github.com/anchore/syft", ldflags: ` build -ldflags="-w -s -extldflags '-static' -X github.com/anchore/syft/internal/version.version=0.79.0 -X github.com/anchore/syft/internal/version.gitCommit=b2b332e8b2b66af0905e98b54ebd713a922be1a8 -X github.com/anchore/syft/internal/version.buildDate=2023-04-21T16:20:25Z -X github.com/anchore/syft/internal/version.gitDescription=v0.79.0 "`, wantMajorVersion: "0", wantFullVersion: "v0.79.0", }, { - name: "kubectl ldflags", + name: "kubectl ldflags", + mainModule: "k8s.io/kubernetes/vendor/k8s.io/client-go", ldflags: ` build -asmflags=all=-trimpath=/workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes build -compiler=gc build -gcflags="all=-trimpath=/workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes " @@ -1093,24 +1096,28 @@ func Test_extractVersionFromLDFlags(t *testing.T) { }, { name: "nerdctl ldflags", + mainModule: "github.com/containerd/nerdctl", ldflags: ` build -ldflags="-s -w -X github.com/containerd/nerdctl/pkg/version.Version=v1.3.1 -X github.com/containerd/nerdctl/pkg/version.Revision=b224b280ff3086516763c7335fc0e0997aca617a"`, wantMajorVersion: "1", wantFullVersion: "v1.3.1", }, { name: "limactl ldflags", + mainModule: "github.com/lima-vm/lima", ldflags: ` build -ldflags="-s -w -X github.com/lima-vm/lima/pkg/version.Version=v0.15.1"`, wantMajorVersion: "0", wantFullVersion: "v0.15.1", }, { name: "terraform ldflags", + mainModule: "github.com/hashicorp/terraform", ldflags: ` build -ldflags="-w -s -X 'github.com/hashicorp/terraform/version.Version=1.4.6' -X 'github.com/hashicorp/terraform/version.Prerelease='"`, wantMajorVersion: "1", wantFullVersion: "v1.4.6", }, { - name: "kube-apiserver ldflags", + name: "kube-apiserver ldflags", + mainModule: "k8s.io/kubernetes/vendor/k8s.io/client-go", ldflags: ` build -asmflags=all=-trimpath=/workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes build -buildmode=exe build -compiler=gc @@ -1120,14 +1127,16 @@ func Test_extractVersionFromLDFlags(t *testing.T) { wantFullVersion: "v1.27.1", }, { - name: "prometheus ldflags", + name: "prometheus ldflags", + mainModule: "github.com/prometheus/common", ldflags: ` build -ldflags="-X github.com/prometheus/common/version.Version=2.44.0 -X github.com/prometheus/common/version.Revision=1ac5131f698ebc60f13fe2727f89b115a41f6558 -X github.com/prometheus/common/version.Branch=HEAD -X github.com/prometheus/common/version.BuildUser=root@739e8181c5db -X github.com/prometheus/common/version.BuildDate=20230514-06:18:11 -extldflags '-static'" build -tags=netgo,builtinassets,stringlabels`, wantMajorVersion: "2", wantFullVersion: "v2.44.0", }, { - name: "influxdb ldflags", + name: "influxdb ldflags", + mainModule: "github.com/influxdata/influxdb-client-go/v2", ldflags: ` build -ldflags="-s -w -X main.version=v2.7.1 -X main.commit=407fa622e9 -X main.date=2023-04-28T13:24:27Z -linkmode=external -extld=/musl/x86_64/bin/musl-gcc -extldflags '-fno-PIC -static-pie -Wl,-z,stack-size=8388608'" build -tags=assets,sqlite_foreign_keys,sqlite_json,static_build,noasm`, wantMajorVersion: "2", @@ -1135,48 +1144,56 @@ func Test_extractVersionFromLDFlags(t *testing.T) { }, { name: "gitea ldflags", + mainModule: "code.gitea.io/gitea", ldflags: ` build -ldflags=" -X \"main.MakeVersion=GNU Make 4.1\" -X \"main.Version=1.19.3\" -X \"main.Tags=bindata sqlite sqlite_unlock_notify\" "`, wantMajorVersion: "1", wantFullVersion: "v1.19.3", }, { name: "docker sbom cli ldflags", + mainModule: "github.com/docker/sbom-cli-plugin", ldflags: ` build -ldflags="-w -s -extldflags '-static' -X github.com/docker/sbom-cli-plugin/internal/version.version=0.6.1-SNAPSHOT-02cf1c8 -X github.com/docker/sbom-cli-plugin/internal/version.gitCommit=02cf1c888ad6662109ac6e3be618392514a56316 -X github.com/docker/sbom-cli-plugin/internal/version.gitDescription=v0.6.1-dirty "`, wantMajorVersion: "0", wantFullVersion: "v0.6.1-SNAPSHOT-02cf1c8", }, { name: "docker scout ldflags", + mainModule: "github.com/docker/scout-cli-plugin", ldflags: ` build -ldflags="-w -s -extldflags '-static' -X github.com/docker/scout-cli-plugin/internal.version=0.10.0 "`, wantMajorVersion: "0", wantFullVersion: "v0.10.0", }, { name: "influx telegraf ldflags", + mainModule: "github.com/influxdata/telegraf", ldflags: ` build -ldflags="-w -s -X github.com/influxdata/telegraf/internal.Commit=a3a884a1 -X github.com/influxdata/telegraf/internal.Branch=HEAD -X github.com/influxdata/telegraf/internal.Version=1.26.2"`, wantMajorVersion: "1", wantFullVersion: "v1.26.2", }, { name: "argocd ldflags", + mainModule: "github.com/argoproj/argo-cd/v2", ldflags: ` build -ldflags="-X github.com/argoproj/argo-cd/v2/common.version=2.7.2 -X github.com/argoproj/argo-cd/v2/common.buildDate=2023-05-12T14:06:49Z -X github.com/argoproj/argo-cd/v2/common.gitCommit=cbee7e6011407ed2d1066c482db74e97e0cc6bdb -X github.com/argoproj/argo-cd/v2/common.gitTreeState=clean -X github.com/argoproj/argo-cd/v2/common.kubectlVersion=v0.24.2 -extldflags=\"-static\""`, wantMajorVersion: "2", wantFullVersion: "v2.7.2", }, { name: "kustomize ldflags", + mainModule: "sigs.k8s.io/kustomize/api", ldflags: ` build -ldflags="-s -X sigs.k8s.io/kustomize/api/provenance.version=kustomize/v4.5.7 -X sigs.k8s.io/kustomize/api/provenance.gitCommit=56d82a8378dfc8dc3b3b1085e5a6e67b82966bd7 -X sigs.k8s.io/kustomize/api/provenance.buildDate=2022-08-02T16:35:54Z "`, wantMajorVersion: "4", wantFullVersion: "v4.5.7", }, { name: "TiDB 7.5.0 ldflags", + mainModule: "github.com/pingcap/tidb", ldflags: `build -ldflags="-X \"github.com/pingcap/tidb/pkg/parser/mysql.TiDBReleaseVersion=v7.5.0\" -X \"github.com/pingcap/tidb/pkg/util/versioninfo.TiDBBuildTS=2023-11-24 08:51:04\" -X \"github.com/pingcap/tidb/pkg/util/versioninfo.TiDBGitHash=069631e2ecfedc000ffb92c67207bea81380f020\" -X \"github.com/pingcap/tidb/pkg/util/versioninfo.TiDBGitBranch=heads/refs/tags/v7.5.0\" -X \"github.com/pingcap/tidb/pkg/util/versioninfo.TiDBEdition=Community\" "`, wantMajorVersion: "7", wantFullVersion: "v7.5.0", }, { name: "TiDB 6.1.7 ldflags", + mainModule: "github.com/pingcap/tidb", ldflags: `build -ldflags="-X \"github.com/pingcap/tidb/parser/mysql.TiDBReleaseVersion=v6.1.7\" -X \"github.com/pingcap/tidb/util/versioninfo.TiDBBuildTS=2023-07-04 12:06:03\" -X \"github.com/pingcap/tidb/util/versioninfo.TiDBGitHash=613ecc5f731b2843e1d53a43915e2cd8da795936\" -X \"github.com/pingcap/tidb/util/versioninfo.TiDBGitBranch=heads/refs/tags/v6.1.7\" -X \"github.com/pingcap/tidb/util/versioninfo.TiDBEdition=Community\" "`, wantMajorVersion: "6", wantFullVersion: "v6.1.7", @@ -1190,31 +1207,43 @@ func Test_extractVersionFromLDFlags(t *testing.T) { ////////////////////////////////////////////////////////////////// // negative cases { - name: "hugo ldflags", - ldflags: ` build -ldflags="-s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio"`, + name: "hugo ldflags", + mainModule: "github.com/gohugoio/hugo", + ldflags: ` build -ldflags="-s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio"`, }, { - name: "ghostunnel ldflags", - ldflags: ` build -ldflags="-X main.version=77d9aaa"`, + name: "ghostunnel ldflags", + mainModule: "github.com/ghostunnel/ghostunnel", + ldflags: ` build -ldflags="-X main.version=77d9aaa"`, }, { - name: "opa ldflags", - ldflags: `build -ldflags=" -X github.com/open-policy-agent/opa/version.Hostname=9549178459bc"`, + name: "opa ldflags", + mainModule: "github.com/open-policy-agent/opa", + ldflags: `build -ldflags=" -X github.com/open-policy-agent/opa/version.Hostname=9549178459bc"`, }, /////////////////////////////////////////////////////////////////// // trickier cases { name: "macvlan plugin for cri-o ldflags", + mainModule: "github.com/containernetworking/plugins", ldflags: ` build -ldflags="-extldflags -static -X github.com/containernetworking/plugins/pkg/utils/buildversion.BuildVersion=v1.2.0"`, wantMajorVersion: "1", wantFullVersion: "v1.2.0", }, { name: "coder ldflags", + mainModule: "github.com/coder/coder", ldflags: ` build -ldflags="-s -w -X 'github.com/coder/coder/buildinfo.tag=0.23.4'"`, wantMajorVersion: "0", wantFullVersion: "v0.23.4", }, + { + name: "hypothetical multiple versions in ldflags", + mainModule: "github.com/foo/baz", + ldflags: ` build -ldflags="-extldflags -static -X github.com/foo/bar/buildversion.BuildVersion=v1.2.0 -X github.com/foo/baz/buildversion.BuildVersion=v2.4.5"`, + wantMajorVersion: "2", + wantFullVersion: "v2.4.5", + }, /////////////////////////////////////////////////////////////////// // don't know how to handle these... yet //{ @@ -1234,7 +1263,7 @@ func Test_extractVersionFromLDFlags(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotMajorVersion, gotFullVersion := extractVersionFromLDFlags(tt.ldflags) + gotMajorVersion, gotFullVersion := extractVersionFromLDFlags(tt.ldflags, tt.mainModule) assert.Equal(t, tt.wantMajorVersion, gotMajorVersion, "unexpected major version") assert.Equal(t, tt.wantFullVersion, gotFullVersion, "unexpected full version") }) From 1cd75b7d685c84f6fcae2db36b7da277425f8098 Mon Sep 17 00:00:00 2001 From: mikcl <43545032+Mikcl@users.noreply.github.com> Date: Thu, 25 Jul 2024 20:45:14 +0100 Subject: [PATCH 112/284] python-cataloger: fix normalization test (#3073) Signed-off-by: mikcl --- syft/pkg/cataloger/python/parse_requirements_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/syft/pkg/cataloger/python/parse_requirements_test.go b/syft/pkg/cataloger/python/parse_requirements_test.go index 139b0b62a..cd796955c 100644 --- a/syft/pkg/cataloger/python/parse_requirements_test.go +++ b/syft/pkg/cataloger/python/parse_requirements_test.go @@ -54,9 +54,9 @@ func TestParseRequirementsTxt(t *testing.T) { }, }, { - Name: "dots-._allowed", + Name: "dots-allowed", Version: "1.0.0", - PURL: "pkg:pypi/dots-._allowed@1.0.0", + PURL: "pkg:pypi/dots-allowed@1.0.0", Locations: locations, Language: pkg.Python, Type: pkg.PythonPkg, From 490e05adb20744ab3d71b745046a9cf65d454952 Mon Sep 17 00:00:00 2001 From: witchcraze <67056980+witchcraze@users.noreply.github.com> Date: Mon, 29 Jul 2024 22:46:51 +0900 Subject: [PATCH 113/284] fix: traefik classifier (#3077) Signed-off-by: witchcraze --- .../pkg/cataloger/binary/classifier_cataloger_test.go | 11 +++++++++++ syft/pkg/cataloger/binary/classifiers.go | 3 ++- syft/pkg/cataloger/binary/test-fixtures/config.yaml | 6 ++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/syft/pkg/cataloger/binary/classifier_cataloger_test.go b/syft/pkg/cataloger/binary/classifier_cataloger_test.go index 978e45755..9876df496 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger_test.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger_test.go @@ -204,6 +204,17 @@ func Test_Cataloger_PositiveCases(t *testing.T) { Metadata: metadata("traefik-binary"), }, }, + { + logicalFixture: "traefik/3.0.4/linux-riscv64", + expected: pkg.Package{ + Name: "traefik", + Version: "3.0.4", + Type: "binary", + PURL: "pkg:generic/traefik@3.0.4", + Locations: locations("traefik"), + Metadata: metadata("traefik-binary"), + }, + }, { logicalFixture: "memcached/1.6.18/linux-amd64", expected: pkg.Package{ diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index e11cd2a7f..e2797b047 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -263,7 +263,8 @@ func DefaultClassifiers() []Classifier { EvidenceMatcher: FileContentsVersionMatcher( // [NUL]v1.7.34[NUL] // [NUL]2.9.6[NUL] - `(?m)(\x00|\x{FFFD})v?(?P[0-9]+\.[0-9]+\.[0-9]+(-alpha[0-9]|-beta[0-9]|-rc[0-9])?)\x00`), + // 3.0.4[NUL] + `(?m)(\x00|\x{FFFD})?v?(?P[0-9]+\.[0-9]+\.[0-9]+(-alpha[0-9]|-beta[0-9]|-rc[0-9])?)\x00`), Package: "traefik", PURL: mustPURL("pkg:generic/traefik@version"), CPEs: singleCPE("cpe:2.3:a:traefik:traefik:*:*:*:*:*:*:*:*"), diff --git a/syft/pkg/cataloger/binary/test-fixtures/config.yaml b/syft/pkg/cataloger/binary/test-fixtures/config.yaml index e14c050c5..b00fd2103 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/config.yaml +++ b/syft/pkg/cataloger/binary/test-fixtures/config.yaml @@ -448,6 +448,12 @@ from-images: paths: - /usr/local/bin/traefik + - version: 3.0.4 + images: + - ref: traefik:3.0.4@sha256:12a7cc4232b5b7fe027673da8c096144525f59a8eabc87e52260aac0ec5a1219 + platform: linux/riscv64 + paths: + - /usr/local/bin/traefik # from the original dynamic fixtures... From 8dd7c9c0b9614a78ecff964a8fb283a97a9a34fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 10:03:35 -0400 Subject: [PATCH 114/284] chore(deps): bump github/codeql-action from 3.25.14 to 3.25.15 (#3083) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.14 to 3.25.15. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/5cf07d8b700b67e235fbb65cbc84f69c0cf10464...afb54ba388a7dca6ecae48f608c4ff05ff4cc77a) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 58c2ae72a..d15a2c997 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@5cf07d8b700b67e235fbb65cbc84f69c0cf10464 #v3.25.14 + uses: github/codeql-action/init@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a #v3.25.15 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@5cf07d8b700b67e235fbb65cbc84f69c0cf10464 #v3.25.14 + uses: github/codeql-action/autobuild@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a #v3.25.15 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@5cf07d8b700b67e235fbb65cbc84f69c0cf10464 #v3.25.14 + uses: github/codeql-action/analyze@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a #v3.25.15 From a35e410c75841dafb4ed1d9c2d89782f936c7fcd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 10:03:44 -0400 Subject: [PATCH 115/284] chore(deps): bump github.com/gkampitakis/go-snaps from 0.5.5 to 0.5.6 (#3082) Bumps [github.com/gkampitakis/go-snaps](https://github.com/gkampitakis/go-snaps) from 0.5.5 to 0.5.6. - [Release notes](https://github.com/gkampitakis/go-snaps/releases) - [Commits](https://github.com/gkampitakis/go-snaps/compare/v0.5.5...v0.5.6) --- updated-dependencies: - dependency-name: github.com/gkampitakis/go-snaps dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ec2085c73..9071bcc2a 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/elliotchance/phpserialize v1.4.0 github.com/facebookincubator/nvdtools v0.1.5 github.com/github/go-spdx/v2 v2.3.1 - github.com/gkampitakis/go-snaps v0.5.5 + github.com/gkampitakis/go-snaps v0.5.6 github.com/go-git/go-billy/v5 v5.5.0 github.com/go-git/go-git/v5 v5.12.0 github.com/go-test/deep v1.1.1 diff --git a/go.sum b/go.sum index c129b300f..7ced08bbe 100644 --- a/go.sum +++ b/go.sum @@ -293,8 +293,8 @@ github.com/gkampitakis/ciinfo v0.3.0 h1:gWZlOC2+RYYttL0hBqcoQhM7h1qNkVqvRCV1fOvp github.com/gkampitakis/ciinfo v0.3.0/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk= -github.com/gkampitakis/go-snaps v0.5.5 h1:FZ01SXOE/uIsD8lZGUjUAxTevz9tf7c1QGIgezv2KNM= -github.com/gkampitakis/go-snaps v0.5.5/go.mod h1:ZABkO14uCuVxBHAXAfKG+bqNz+aa1bGPAg8jkI0Nk8Y= +github.com/gkampitakis/go-snaps v0.5.6 h1:kAal5JbqTycI+6xeS3K0nPqvNDAxqKX5W3dRXKxIJpA= +github.com/gkampitakis/go-snaps v0.5.6/go.mod h1:ZABkO14uCuVxBHAXAfKG+bqNz+aa1bGPAg8jkI0Nk8Y= github.com/glebarez/go-sqlite v1.20.3 h1:89BkqGOXR9oRmG58ZrzgoY/Fhy5x0M+/WV48U5zVrZ4= github.com/glebarez/go-sqlite v1.20.3/go.mod h1:u3N6D/wftiAzIOJtZl6BmedqxmmkDfH3q+ihjqxC9u0= github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= From a2042e629c38d8799d624915d6c4030978f3d7b8 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 10:03:59 -0400 Subject: [PATCH 116/284] chore(deps): update CPE dictionary index (#3079) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: wagoodman <590471+wagoodman@users.noreply.github.com> --- .../dictionary/data/cpe-index.json | 186 +++++++++++++++++- 1 file changed, 180 insertions(+), 6 deletions(-) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index 361a897e2..b7226416a 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -7017,7 +7017,8 @@ "cpe:2.3:a:ab-wp:simple_counter:*:*:*:*:*:wordpress:*:*" ], "academy": [ - "cpe:2.3:a:creativeitem:academy_lms:*:*:*:*:*:*:*:*" + "cpe:2.3:a:creativeitem:academy_lms:*:*:*:*:*:*:*:*", + "cpe:2.3:a:kodezen:academy_lms:*:*:*:*:*:wordpress:*:*" ], "accelerated-mobile-pages": [ "cpe:2.3:a:ampforwp:accelerated_mobile_pages:*:*:*:*:*:wordpress:*:*", @@ -7214,6 +7215,9 @@ "addon-elements-for-elementor-page-builder": [ "cpe:2.3:a:webtechstreet:elementor_addon_elements:*:*:*:*:*:wordpress:*:*" ], + "addons-for-beaver-builder": [ + "cpe:2.3:a:livemesh:livemesh_addons_for_beaver_builder:*:*:*:*:*:wordpress:*:*" + ], "addons-for-elementor": [ "cpe:2.3:a:livemesh:elementor_addons:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:livemeshelementor:addons_for_elementor:*:*:*:*:*:wordpress:*:*" @@ -7441,7 +7445,8 @@ "cpe:2.3:a:alfred24_click_\\\u0026_collect_project:alfred24_click_\\\u0026_collect:*:*:*:*:*:wordpress:*:*" ], "ali2woo-lite": [ - "cpe:2.3:a:ali2woo:ali2woo:*:*:*:*:lite:wordpress:*:*" + "cpe:2.3:a:ali2woo:ali2woo:*:*:*:*:lite:wordpress:*:*", + "cpe:2.3:a:ali2woo:aliexpress_dropshipping_with_alinext:*:*:*:*:lite:wordpress:*:*" ], "alipay": [ "cpe:2.3:a:alipay_project:alipay:*:*:*:*:*:wordpress:*:*" @@ -7800,6 +7805,9 @@ "auxin-elements": [ "cpe:2.3:a:averta:shortcodes_and_extra_features_for_phlox_theme:*:*:*:*:*:wordpress:*:*" ], + "auxin-portfolio": [ + "cpe:2.3:a:averta:auxinportfolio:*:*:*:*:*:wordpress:*:*" + ], "auyautochat-for-wp": [ "cpe:2.3:a:autochat:automatic_conversation:*:*:*:*:*:wordpress:*:*" ], @@ -7913,6 +7921,9 @@ "batch-cat": [ "cpe:2.3:a:batch_cat_project:batch_cat:*:*:*:*:*:wordpress:*:*" ], + "bb-bootstrap-cards": [ + "cpe:2.3:a:brainstormforce:cards_for_beaver_builder:*:*:*:*:*:wordpress:*:*" + ], "bbp-move-topics": [ "cpe:2.3:a:bbpress_move_topics_project:bbpress_move_topics:*:*:*:*:*:wordpress:*:*" ], @@ -7929,9 +7940,15 @@ "bbpress": [ "cpe:2.3:a:bbpress:bbpress:*:*:*:*:*:wordpress:*:*" ], + "bbpress-notify-nospam": [ + "cpe:2.3:a:usestrict:bbpress_notify:*:*:*:*:*:wordpress:*:*" + ], "bcorp-shortcodes": [ "cpe:2.3:a:bcorp_shortcodes_project:bcorp_shortcodes:*:*:*:*:*:wordpress:*:*" ], + "bdthemes-element-pack-lite": [ + "cpe:2.3:a:bdthemes:element_pack_elementor_addons:*:*:*:*:*:wordpress:*:*" + ], "bdvs-password-reset": [ "cpe:2.3:a:bedevious:password_reset_with_code_for_wordpress_rest_api:*:*:*:*:*:wordpress:*:*" ], @@ -8050,12 +8067,18 @@ "blog-in-blog": [ "cpe:2.3:a:blog-in-blog_project:blog-in-blog:*:*:*:*:*:wordpress:*:*" ], + "blog-posts-and-category-for-elementor": [ + "cpe:2.3:a:plugin-devs:blog\\,_posts_and_category_filter_for_elementor:*:*:*:*:*:wordpress:*:*" + ], "blog2social": [ "cpe:2.3:a:adenion:blog2social:*:*:*:*:*:wordpress:*:*" ], "blogger-importer": [ "cpe:2.3:a:wordpress:blogger_importer:*:*:*:*:*:wordpress:*:*" ], + "blogmentor": [ + "cpe:2.3:a:auburnforest:blogmentor:*:*:*:*:*:wordpress:*:*" + ], "blue-admin": [ "cpe:2.3:a:blue-admin_project:blue-admin:*:*:*:*:*:wordpress:*:*" ], @@ -8334,7 +8357,11 @@ "cache-images": [ "cpe:2.3:a:cache_images_project:cache_images:*:*:*:*:*:wordpress:*:*" ], + "caddy": [ + "cpe:2.3:a:madebytribe:caddy:*:*:*:*:*:wordpress:*:*" + ], "cafe-lite": [ + "cpe:2.3:a:clever-soft:clever_addons_for_elementor:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:cleversoft:clever_addons_for_elementor:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:download_clever_addons_for_elementor_project:download_clever_addons_for_elementor:*:*:*:*:*:wordpress:*:*" ], @@ -8382,6 +8409,9 @@ "candidate-application-form": [ "cpe:2.3:a:candidate-application-form_project:candidate-application-form:*:*:*:*:*:wordpress:*:*" ], + "canto": [ + "cpe:2.3:a:canto:canto:*:*:*:*:*:wordpress:*:*" + ], "canvasio3d-light": [ "cpe:2.3:a:virtuellwerk:canvasio3d_light:*:*:*:*:*:wordpress:*:*" ], @@ -8544,6 +8574,9 @@ "chatbot": [ "cpe:2.3:a:quantumcloud:ai_chatbot:*:*:*:*:*:wordpress:*:*" ], + "chatbot-chatgpt": [ + "cpe:2.3:a:kognetics:kognetiks_chatbot:*:*:*:*:*:wordpress:*:*" + ], "chaty": [ "cpe:2.3:a:premio:chaty:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:premio:floating_chat_widget:*:*:*:*:*:wordpress:*:*" @@ -8855,7 +8888,8 @@ "cpe:2.3:a:ciphercoin:contact_form_7_database_addon:*:*:*:*:*:wordpress:*:*" ], "contact-form-entries": [ - "cpe:2.3:a:crmperks:database_for_contact_form_7\\,_wpforms\\,_elementor_forms:*:*:*:*:*:*:*:*" + "cpe:2.3:a:crmperks:database_for_contact_form_7\\,_wpforms\\,_elementor_forms:*:*:*:*:*:*:*:*", + "cpe:2.3:a:crmperks:database_for_contact_form_7\\,_wpforms\\,_elementor_forms:*:*:*:*:*:wordpress:*:*" ], "contact-form-generator": [ "cpe:2.3:a:creative-solutions:contact_form_generator:*:*:*:*:*:wordpress:*:*" @@ -8946,6 +8980,9 @@ "content-views-query-and-display-post-page": [ "cpe:2.3:a:contentviewspro:content_views:*:*:*:*:*:wordpress:*:*" ], + "contentlock": [ + "cpe:2.3:a:adamsolymosi:contentlock:*:*:*:*:*:wordpress:*:*" + ], "contentstudio": [ "cpe:2.3:a:contentstudio:contentstudio:*:*:*:*:*:wordpress:*:*" ], @@ -9031,6 +9068,9 @@ "copy-the-code": [ "cpe:2.3:a:maheshwaghmare:copy_anything_to_clipboard:*:*:*:*:*:wordpress:*:*" ], + "copymatic": [ + "cpe:2.3:a:copymatic:copymatic:*:*:*:*:*:wordpress:*:*" + ], "core-control": [ "cpe:2.3:a:dd32:core_control:*:*:*:*:*:wordpress:*:*" ], @@ -9168,6 +9208,9 @@ "css-javascript-toolbox": [ "cpe:2.3:a:wipeoutmedia:css_\\\u0026_javascript_toolbox:*:*:*:*:*:wordpress:*:*" ], + "cssable-countdown": [ + "cpe:2.3:a:dmonnier:cssable_countdown:*:*:*:*:*:wordpress:*:*" + ], "csv-import-export": [ "cpe:2.3:a:csv-import-export_project:csv-import-export:*:*:*:*:*:wordpress:*:*" ], @@ -9443,6 +9486,9 @@ "delhivery-logistics-courier": [ "cpe:2.3:a:delhivery:logistics_courier:*:*:*:*:*:wordpress:*:*" ], + "delucks-seo": [ + "cpe:2.3:a:delucks:delucks_seo:*:*:*:*:*:wordpress:*:*" + ], "democracy-poll": [ "cpe:2.3:a:wp-kama:democracy_poll:*:*:*:*:*:wordpress:*:*" ], @@ -9460,7 +9506,8 @@ "cpe:2.3:a:depicter:depicter:*:*:*:*:*:wordpress:*:*" ], "dethemekit-for-elementor": [ - "cpe:2.3:a:detheme:dethemekit_for_elementor:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:detheme:dethemekit_for_elementor:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:dethemekit_for_elementor_project:dethemekit_for_elementor:*:*:*:*:*:wordpress:*:*" ], "diary-availability-calendar": [ "cpe:2.3:a:roosty:diary-availability-calendar:*:*:*:*:*:wordpress:*:*" @@ -9480,6 +9527,9 @@ "directorist": [ "cpe:2.3:a:wpwax:directorist:*:*:*:*:*:wordpress:*:*" ], + "directorypress": [ + "cpe:2.3:a:designinvento:directorypress:*:*:*:*:*:wordpress:*:*" + ], "disable-comments": [ "cpe:2.3:a:disable_comments:disable_comments_project:*:*:*:*:*:wordpress:*:*" ], @@ -9531,6 +9581,9 @@ "dokan-lite": [ "cpe:2.3:a:wedevs:dokan:*:*:*:*:*:wordpress:*:*" ], + "dokan-pro": [ + "cpe:2.3:a:dokan:dokan_pro_plugin:*:*:*:*:*:wordpress:*:*" + ], "dologin": [ "cpe:2.3:a:wpdo:dologin_security:*:*:*:*:*:wordpress:*:*" ], @@ -9561,6 +9614,9 @@ "doofinder-for-woocommerce": [ "cpe:2.3:a:doofinder:doofinder:*:*:*:*:*:wordpress:*:*" ], + "dop-shortcodes": [ + "cpe:2.3:a:dotonpaper:dot_on_paper_shortcodes:*:*:*:*:*:wordpress:*:*" + ], "double-opt-in-for-download": [ "cpe:2.3:a:labwebdevelopment:double_opt-in_for_download:*:*:*:*:*:wordpress:*:*" ], @@ -9894,6 +9950,9 @@ "elegant-custom-fonts": [ "cpe:2.3:a:breakdance:elegant_custom_fonts:*:*:*:*:*:wordpress:*:*" ], + "element-ready-lite": [ + "cpe:2.3:a:quomodosoft:elementsready:*:*:*:*:*:wordpress:*:*" + ], "elementor": [ "cpe:2.3:a:elementor:elementor_page_builder:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:elementor:elementor_page_builder:*:*:*:*:pro:wordpress:*:*", @@ -9904,7 +9963,8 @@ "cpe:2.3:a:elementor:elementor_pro:*:*:*:*:*:wordpress:*:*" ], "elementskit-lite": [ - "cpe:2.3:a:wpmet:elements_kit_elementor_addons:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:wpmet:elements_kit_elementor_addons:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpmet:elementskit_elementor_addons:*:*:*:*:*:wordpress:*:*" ], "elespare": [ "cpe:2.3:a:elespare:elespare:*:*:*:*:*:wordpress:*:*" @@ -10175,6 +10235,9 @@ "expand-maker": [ "cpe:2.3:a:edmonsoft:read_more_\\\u0026_accordion:*:*:*:*:*:wordpress:*:*" ], + "expert-invoice": [ + "cpe:2.3:a:expert_invoice_project:expert_invoice:*:*:*:*:*:wordpress:*:*" + ], "export-all-urls": [ "cpe:2.3:a:atlasgondal:export_all_urls:*:*:*:*:*:wordpress:*:*" ], @@ -10355,6 +10418,9 @@ "file-manager-advanced": [ "cpe:2.3:a:advancedfilemanager:advanced_file_manager:*:*:*:*:*:wordpress:*:*" ], + "file-manager-advanced-shortcode-2": [ + "cpe:2.3:a:advancedfilemanager:file_manager_advanced_shortcode:*:*:*:*:*:wordpress:*:*" + ], "filebird": [ "cpe:2.3:a:ninjateam:filebird:*:*:*:*:*:wordpress:*:*" ], @@ -10561,6 +10627,9 @@ "forminator": [ "cpe:2.3:a:incsub:forminator:*:*:*:*:*:wordpress:*:*" ], + "formlift": [ + "cpe:2.3:a:formlift:formlift_for_infusionsoft_web_forms:*:*:*:*:*:wordpress:*:*" + ], "forms-ada-form-builder": [ "cpe:2.3:a:monitorclick:forms_ada:*:*:*:*:*:wordpress:*:*" ], @@ -11058,6 +11127,9 @@ "gutenslider": [ "cpe:2.3:a:gutenslider:gutenslider:*:*:*:*:*:wordpress:*:*" ], + "gutenverse": [ + "cpe:2.3:a:jegstudio:gutenverse:*:*:*:*:*:wordpress:*:*" + ], "gwa-autoresponder": [ "cpe:2.3:a:\\[gwa\\]_autoresponder_project:\\[gwa\\]_autoresponder:*:*:*:*:*:wordpress:*:*" ], @@ -11767,6 +11839,9 @@ "keyword-meta": [ "cpe:2.3:a:keyword_meta_project:keyword_meta:*:*:*:*:*:wordpress:*:*" ], + "kimili-flash-embed": [ + "cpe:2.3:a:kimili:kimili_flash_embed:*:*:*:*:*:wordpress:*:*" + ], "kitestudio-core": [ "cpe:2.3:a:kitestudio:core_plugin_for_kitestudio_themes:*:*:*:*:*:wordpress:*:*" ], @@ -12118,6 +12193,9 @@ "magic-post-thumbnail": [ "cpe:2.3:a:magic-post-thumbnail:magic_post_thumbnail:*:*:*:*:*:wordpress:*:*" ], + "magical-addons-for-elementor": [ + "cpe:2.3:a:wpthemespace:magical_addons_for_elementor:*:*:*:*:*:wordpress:*:*" + ], "mail-control": [ "cpe:2.3:a:instareza:mail_control:*:*:*:*:*:wordpress:*:*" ], @@ -12262,6 +12340,9 @@ "material-design-icons-for-elementor": [ "cpe:2.3:a:material_design_icons_for_page_builders_project:material_design_icons_for_page_builders:*:*:*:*:*:wordpress:*:*" ], + "materialis-companion": [ + "cpe:2.3:a:extendthemes:materialis_companion:*:*:*:*:*:wordpress:*:*" + ], "matrix-pre-loader": [ "cpe:2.3:a:nkb-bd:preloader_matrix:*:*:*:*:*:wordpress:*:*" ], @@ -12324,6 +12405,9 @@ "mega-addons-for-visual-composer": [ "cpe:2.3:a:topdigitaltrends:mega_addons_for_wpbakery_page_builder:*:*:*:*:*:wordpress:*:*" ], + "mega-elements-addons-for-elementor": [ + "cpe:2.3:a:kraftplugins:mega_elements:*:*:*:*:*:wordpress:*:*" + ], "megamenu": [ "cpe:2.3:a:megamenu:max_mega_menu:*:*:*:*:*:wordpress:*:*" ], @@ -12649,6 +12733,9 @@ "my-content-management": [ "cpe:2.3:a:joedolson:my_content_management:*:*:*:*:*:wordpress:*:*" ], + "my-favorites": [ + "cpe:2.3:a:takashimatsuyama:my_favorites:*:*:*:*:*:wordpress:*:*" + ], "my-tickets": [ "cpe:2.3:a:my_tickets_project:my_tickets:*:*:*:*:*:wordpress:*:*" ], @@ -12824,6 +12911,9 @@ "cpe:2.3:a:wpconcern:coming_soon_\\\u0026_maintenance_mode_page:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:wpconcern:nifty_coming_soon_\\\u0026_maintenance_mode_page:*:*:*:*:*:wordpress:*:*" ], + "ninja-beaver-lite-addons-for-beaver-builder": [ + "cpe:2.3:a:ninjateam:ninja_beaver_add-ons_for_beaver_builder:*:*:*:*:*:wordpress:*:*" + ], "ninja-forms": [ "cpe:2.3:a:ninjaforms:contact_form:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:ninjaforms:ninja_forms:*:*:*:*:*:wordpress:*:*" @@ -13058,6 +13148,10 @@ "osmapper": [ "cpe:2.3:a:b4after:osmapper:*:*:*:*:*:wordpress:*:*" ], + "otter-blocks": [ + "cpe:2.3:a:themeisle:otter_blocks:*:*:*:*:*:*:*:*", + "cpe:2.3:a:themeisle:otter_blocks:*:*:*:*:*:wordpress:*:*" + ], "our-team-enhanced": [ "cpe:2.3:a:smartcat:our_team_showcase:*:*:*:*:*:wordpress:*:*" ], @@ -13085,6 +13179,9 @@ "page-builder-by-azexo": [ "cpe:2.3:a:azexo:page_builder_with_image_map_by_azexo:*:*:*:*:*:wordpress:*:*" ], + "page-builder-sandwich": [ + "cpe:2.3:a:pagebuildersandwich:page_builder_sandwich:*:*:*:*:*:wordpress:*:*" + ], "page-generator": [ "cpe:2.3:a:wpzinc:page_generator:*:*:*:*:*:wordpress:*:*" ], @@ -13170,6 +13267,9 @@ "paypal-payment-button-by-vcita": [ "cpe:2.3:a:vcita:online_payments_-_get_paid_with_paypal\\,_square_\\\u0026_stripe:*:*:*:*:*:wordpress:*:*" ], + "payplus-payment-gateway": [ + "cpe:2.3:a:payplus:payplus_payment_gateway:*:*:*:*:*:wordpress:*:*" + ], "paytium": [ "cpe:2.3:a:paytium:paytium:*:*:*:*:*:wordpress:*:*" ], @@ -13849,6 +13949,9 @@ "quotes-collection": [ "cpe:2.3:a:quotes_collection_project:quotes_collection:*:*:*:*:*:wordpress:*:*" ], + "quotes-for-woocommerce": [ + "cpe:2.3:a:technovama:quotes_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], "quotes-llama": [ "cpe:2.3:a:quotes_llama_project:quotes_llama:*:*:*:*:*:wordpress:*:*" ], @@ -14117,6 +14220,9 @@ "restrict-content": [ "cpe:2.3:a:liquidweb:restrict_content:*:*:*:*:*:wordpress:*:*" ], + "restrict-for-elementor": [ + "cpe:2.3:a:tickera:restrict_for_elementor:*:*:*:*:*:wordpress:*:*" + ], "restrict-usernames-emails-characters": [ "cpe:2.3:a:benaceur-php:restrict_usernames_emails_characters:*:*:*:*:*:wordpress:*:*" ], @@ -14336,6 +14442,9 @@ "searchiq": [ "cpe:2.3:a:searchiq:searchiq:*:*:*:*:*:wordpress:*:*" ], + "searchpro": [ + "cpe:2.3:a:berqier:berqwp:*:*:*:*:*:wordpress:*:*" + ], "searchterms-tagging-2": [ "cpe:2.3:a:seo_searchterms_tagging_2_project:seo_searchterms_tagging_2:*:*:*:*:*:wordpress:*:*" ], @@ -14375,6 +14484,12 @@ "sell-media": [ "cpe:2.3:a:graphpaperpress:sell_media:*:*:*:*:*:wordpress:*:*" ], + "sellkit": [ + "cpe:2.3:a:artbees:sellkit:*:*:*:*:*:wordpress:*:*" + ], + "send-emails-with-mandrill": [ + "cpe:2.3:a:millermedia:mandrill:*:*:*:*:*:wordpress:*:*" + ], "send-users-email": [ "cpe:2.3:a:sumanbhattarai:send_users_email:*:*:*:*:*:wordpress:*:*" ], @@ -14860,6 +14975,9 @@ "skaut-bazar": [ "cpe:2.3:a:skaut-bazar_project:skaut-bazar:*:*:*:*:*:wordpress:*:*" ], + "sketchfab-oembed": [ + "cpe:2.3:a:generatewp:sketchfab_embed:*:*:*:*:*:wordpress:*:*" + ], "sliced-invoices": [ "cpe:2.3:a:slicedinvoices:sliced_invoices:*:*:*:*:*:wordpress:*:*" ], @@ -15631,6 +15749,9 @@ "toolbar-to-share": [ "cpe:2.3:a:toolbar_to_share_project:toolbar_to_share:*:*:*:*:*:wordpress:*:*" ], + "tooltip-ck": [ + "cpe:2.3:a:ceikay:tooltip_ck:*:*:*:*:*:wordpress:*:*" + ], "top-10": [ "cpe:2.3:a:top_10_project:top_10:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:webberzone:top_10:*:*:*:*:*:wordpress:*:*" @@ -15677,6 +15798,9 @@ "transbank-webpay-plus-rest": [ "cpe:2.3:a:transbank:transbank_webpay_rest:*:*:*:*:*:wordpress:*:*" ], + "transition-slider-lite": [ + "cpe:2.3:a:creativeinteractivemedia:transition_slider:*:*:*:*:*:wordpress:*:*" + ], "translatepress-multilingual": [ "cpe:2.3:a:cozmoslabs:translatepress:*:*:*:*:*:wordpress:*:*" ], @@ -15765,6 +15889,9 @@ "ucontext-for-amazon": [ "cpe:2.3:a:summitmediaconcepts:ucontext_for_amazon:*:*:*:*:*:wordpress:*:*" ], + "uipress-lite": [ + "cpe:2.3:a:uipress:uipress_lite:*:*:*:*:*:wordpress:*:*" + ], "uji-countdown": [ "cpe:2.3:a:wpmanage:uji_countdown:*:*:*:*:*:wordpress:*:*" ], @@ -16039,6 +16166,9 @@ "vaultpress": [ "cpe:2.3:a:automattic:vaultpress:*:*:*:*:*:wordpress:*:*" ], + "vc-tabs": [ + "cpe:2.3:a:oxilab:responsive_tabs:*:*:*:*:*:wordpress:*:*" + ], "verge3d": [ "cpe:2.3:a:soft8soft:verge3d:*:*:*:*:*:wordpress:*:*" ], @@ -16344,6 +16474,9 @@ "weixin-robot-advanced": [ "cpe:2.3:a:wpjam:wechat_robot:*:*:*:*:premium:wordpress:*:*" ], + "wemail": [ + "cpe:2.3:a:wedevs:wemail:*:*:*:*:*:wordpress:*:*" + ], "wf-cookie-consent": [ "cpe:2.3:a:wunderfarm:wf_cookie_consent:*:*:*:*:*:wordpress:*:*" ], @@ -16851,6 +16984,9 @@ "wp-bitly": [ "cpe:2.3:a:bitly:bitly:*:*:*:*:*:wordpress:*:*" ], + "wp-blog-post-layouts": [ + "cpe:2.3:a:codevibrant:wp_blog_post_layouts:*:*:*:*:*:wordpress:*:*" + ], "wp-blogs-planetarium": [ "cpe:2.3:a:wp-blogs-planetarium_project:wp-blogs-planetarium:*:*:*:*:*:wordpress:*:*" ], @@ -16881,6 +17017,9 @@ "wp-cachecom": [ "cpe:2.3:a:kenthhagstrom:wp-cachecom:*:*:*:*:*:wordpress:*:*" ], + "wp-cafe": [ + "cpe:2.3:a:themewinter:wpcafe:*:*:*:*:*:wordpress:*:*" + ], "wp-calendar": [ "cpe:2.3:a:wp_calendar_project:wp_calendar:*:*:*:*:*:wordpress:*:*" ], @@ -17173,6 +17312,9 @@ "wp-file-manager": [ "cpe:2.3:a:webdesi9:file_manager:*:*:*:*:*:wordpress:*:*" ], + "wp-file-manager-pro": [ + "cpe:2.3:a:filemanagerpro:file_manager_pro:*:*:*:*:*:wordpress:*:*" + ], "wp-file-upload": [ "cpe:2.3:a:iptanus:wordpress_file_upload:*:*:*:*:*:wordpress:*:*" ], @@ -17526,7 +17668,8 @@ ], "wp-photo-album-plus": [ "cpe:2.3:a:wp_photo_album_plus_project:wp_photo_album_plus:*:*:*:*:*:wordpress:*:*", - "cpe:2.3:a:wppa.opajaap:wp-photo-album-plus:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:wppa.opajaap:wp-photo-album-plus:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wppa:wp_photo_album_plus:*:*:*:*:*:wordpress:*:*" ], "wp-photo-text-slider-50": [ "cpe:2.3:a:gopiplus:wp_photo_text_slider_50:*:*:*:*:*:wordpress:*:*" @@ -17571,6 +17714,9 @@ "wp-popups-lite": [ "cpe:2.3:a:timersys:wp_popups:*:*:*:*:*:wordpress:*:*" ], + "wp-post-author": [ + "cpe:2.3:a:afthemes:wp_post_author:*:*:*:*:*:wordpress:*:*" + ], "wp-post-columns": [ "cpe:2.3:a:wp_post_columns_project:wp_post_columns:*:*:*:*:*:wordpress:*:*" ], @@ -17607,6 +17753,9 @@ "wp-reactions-lite": [ "cpe:2.3:a:wpreactions:wp_reactions_lite:*:*:*:*:*:wordpress:*:*" ], + "wp-recall": [ + "cpe:2.3:a:plechevandrey:wp-recall:*:*:*:*:*:wordpress:*:*" + ], "wp-recipe-maker": [ "cpe:2.3:a:bootstrapped:wp_recipe_maker:*:*:*:*:*:wordpress:*:*" ], @@ -17961,6 +18110,9 @@ "wp-whois-domain": [ "cpe:2.3:a:netattingo:wp-whois-domain:*:*:*:*:*:wordpress:*:*" ], + "wp-widget-bundle": [ + "cpe:2.3:a:devnath_verma:widget_bundle:*:*:*:*:*:wordpress:*:*" + ], "wp-woocommerce-quickbooks": [ "cpe:2.3:a:crmperks:integration_for_woocommerce_and_quickbooks:*:*:*:*:*:wordpress:*:*" ], @@ -18270,6 +18422,9 @@ "yith-desktop-notifications-for-woocommerce": [ "cpe:2.3:a:yithemes:yith_desktop_notifications_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], + "yith-essential-kit-for-woocommerce-1": [ + "cpe:2.3:a:yithemes:yith_essential_kit_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], "yith-maintenance-mode": [ "cpe:2.3:a:yithemes:yith_maintenance_mode:*:*:*:*:*:wordpress:*:*" ], @@ -18396,6 +18551,9 @@ "zoho-forms": [ "cpe:2.3:a:zohocorp:zoho_forms:*:*:*:*:*:wordpress:*:*" ], + "zoho-marketinghub": [ + "cpe:2.3:a:zoho:zoho_marketing_automation:*:*:*:*:*:wordpress:*:*" + ], "zoho-salesiq": [ "cpe:2.3:a:zoho:salesiq:*:*:*:*:*:wordpress:*:*" ], @@ -18449,6 +18607,9 @@ "auberge": [ "cpe:2.3:a:webmandesign:auberge_theme:*:*:*:*:*:wordpress:*:*" ], + "author": [ + "cpe:2.3:a:sinatrateam:sinatra:*:*:*:*:*:wordpress:*:*" + ], "big-store": [ "cpe:2.3:a:themehunk:big_store:*:*:*:*:*:wordpress:*:*" ], @@ -18483,6 +18644,9 @@ "construction-lite": [ "cpe:2.3:a:accesspressthemes:construction_lite:*:*:*:*:*:wordpress:*:*" ], + "cozipress": [ + "cpe:2.3:a:burgersoftwares:cozipress:*:*:*:*:*:wordpress:*:*" + ], "customizr": [ "cpe:2.3:a:presscustomizr:customizr:*:*:*:*:*:wordpress:*:*" ], @@ -18507,6 +18671,10 @@ "enlighten": [ "cpe:2.3:a:accesspressthemes:enlighten:*:*:*:*:*:wordpress:*:*" ], + "esteem": [ + "cpe:2.3:a:themegrill:esteem:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:themegrill:esteem:*:*:*:*:free:wordpress:*:*" + ], "everest-news": [ "cpe:2.3:a:everestthemes:everest_news:*:*:*:*:*:wordpress:*:*" ], @@ -18591,12 +18759,18 @@ "responsive": [ "cpe:2.3:a:cyberchimps:responsive:*:*:*:*:*:wordpress:*:*" ], + "rife-free": [ + "cpe:2.3:a:apollo13themes:rife_free:*:*:*:*:*:wordpress:*:*" + ], "royal-elementor-kit": [ "cpe:2.3:a:royal-elementor-addons:royal_elementor_kit:*:*:*:*:*:wordpress:*:*" ], "shapely": [ "cpe:2.3:a:colorlib:shapely:*:*:*:*:*:wordpress:*:*" ], + "sinatra": [ + "cpe:2.3:a:sinatrateam:sinatra:*:*:*:*:*:wordpress:*:*" + ], "sparkling": [ "cpe:2.3:a:colorlib:sparklinkg:*:*:*:*:*:wordpress:*:*" ], From 06526e29315a87b2016c52d0e6f01e351ba1f2be Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 10:04:46 -0400 Subject: [PATCH 117/284] chore(deps): update stereoscope to 50ce3be7aa1fb8829234ae648215e7907196bfa5 (#3075) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: kzantow <3009477+kzantow@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9071bcc2a..82cea45b0 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f - github.com/anchore/stereoscope v0.0.3-0.20240711134149-487b11e5ba26 + github.com/anchore/stereoscope v0.0.3-0.20240725180315-50ce3be7aa1f github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // we are hinting brotli to latest due to warning when installing archiver v3: // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption diff --git a/go.sum b/go.sum index 7ced08bbe..bd5319c94 100644 --- a/go.sum +++ b/go.sum @@ -113,8 +113,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f h1:B/E9ixKNCasntpoch61NDaQyGPDXLEJlL+B9B/PbdbA= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.3-0.20240711134149-487b11e5ba26 h1:nOTfmXionIzGtg487nREmvDNr7QbR9vf6HbC2Z6n1ZE= -github.com/anchore/stereoscope v0.0.3-0.20240711134149-487b11e5ba26/go.mod h1:DcQdMes8SwpFli3rDH0v+Vd9qU9Jariq7JSHNJV5X/A= +github.com/anchore/stereoscope v0.0.3-0.20240725180315-50ce3be7aa1f h1:xuBvotcht1Ns8IdaC4UuYV1U8MFln9c5ELeo5bzDEO8= +github.com/anchore/stereoscope v0.0.3-0.20240725180315-50ce3be7aa1f/go.mod h1:DcQdMes8SwpFli3rDH0v+Vd9qU9Jariq7JSHNJV5X/A= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= From a4b5dcd0df80f6a58c8610e25104647710c1da5d Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Tue, 30 Jul 2024 12:02:52 -0400 Subject: [PATCH 118/284] fix: improve determinism in java archive identification (#3085) Signed-off-by: Keith Zantow --- go.mod | 2 +- syft/pkg/cataloger/java/archive_parser.go | 8 +++- .../pkg/cataloger/java/archive_parser_test.go | 38 +++++++++++++++++++ .../java/test-fixtures/jar-metadata/Makefile | 4 ++ .../META-INF/MANIFEST.MF | 2 + .../multiple-matching-1/pom.properties | 3 ++ .../org.multiple/multiple-matching-1/pom.xml | 8 ++++ .../multiple-matching-2/pom.properties | 3 ++ .../org.multiple/multiple-matching-2/pom.xml | 8 ++++ .../multiple-matching-3/pom.properties | 3 ++ .../org.multiple/multiple-matching-3/pom.xml | 8 ++++ 11 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/MANIFEST.MF create mode 100644 syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-1/pom.properties create mode 100644 syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-1/pom.xml create mode 100644 syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-2/pom.properties create mode 100644 syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-2/pom.xml create mode 100644 syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-3/pom.properties create mode 100644 syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-3/pom.xml diff --git a/go.mod b/go.mod index 82cea45b0..87692a0f3 100644 --- a/go.mod +++ b/go.mod @@ -90,6 +90,7 @@ require ( github.com/BurntSushi/toml v1.4.0 github.com/adrg/xdg v0.5.0 github.com/magiconair/properties v1.8.7 + golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 ) require ( @@ -230,7 +231,6 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/crypto v0.25.0 // indirect - golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.22.0 // indirect golang.org/x/term v0.22.0 // indirect diff --git a/syft/pkg/cataloger/java/archive_parser.go b/syft/pkg/cataloger/java/archive_parser.go index 134e8f18a..2262d79fb 100644 --- a/syft/pkg/cataloger/java/archive_parser.go +++ b/syft/pkg/cataloger/java/archive_parser.go @@ -6,8 +6,11 @@ import ( "fmt" "os" "path" + "slices" "strings" + "golang.org/x/exp/maps" + intFile "github.com/anchore/syft/internal/file" "github.com/anchore/syft/internal/licenses" "github.com/anchore/syft/internal/log" @@ -298,7 +301,10 @@ func (j *archiveParser) guessMainPackageNameAndVersionFromPomInfo(ctx context.Co properties, _ := pomPropertiesByParentPath(j.archivePath, j.location, pomPropertyMatches) projects, _ := pomProjectByParentPath(j.archivePath, j.location, pomMatches) - for parentPath, propertiesObj := range properties { + parentPaths := maps.Keys(properties) + slices.Sort(parentPaths) + for _, parentPath := range parentPaths { + propertiesObj := properties[parentPath] if artifactIDMatchesFilename(propertiesObj.ArtifactID, j.fileInfo.name) { pomPropertiesObject = propertiesObj if proj, exists := projects[parentPath]; exists { diff --git a/syft/pkg/cataloger/java/archive_parser_test.go b/syft/pkg/cataloger/java/archive_parser_test.go index 7d7164196..968be8578 100644 --- a/syft/pkg/cataloger/java/archive_parser_test.go +++ b/syft/pkg/cataloger/java/archive_parser_test.go @@ -1386,6 +1386,44 @@ func Test_parseJavaArchive_regressions(t *testing.T) { } } +func Test_deterministicMatchingPomProperties(t *testing.T) { + tests := []struct { + fixture string + expectedName string + expectedVersion string + }{ + { + fixture: "multiple-matching-2.11.5", + expectedName: "multiple-matching-1", + expectedVersion: "2.11.5", + }, + } + + for _, test := range tests { + t.Run(test.fixture, func(t *testing.T) { + fixturePath := generateJavaMetadataJarFixture(t, test.fixture) + + for i := 0; i < 5; i++ { + func() { + fixture, err := os.Open(fixturePath) + require.NoError(t, err) + + parser, cleanupFn, err := newJavaArchiveParser(file.LocationReadCloser{ + Location: file.NewLocation(fixture.Name()), + ReadCloser: fixture, + }, false, ArchiveCatalogerConfig{UseNetwork: false}) + defer cleanupFn() + require.NoError(t, err) + + name, version, _ := parser.guessMainPackageNameAndVersionFromPomInfo(context.TODO()) + require.Equal(t, test.expectedName, name) + require.Equal(t, test.expectedVersion, version) + }() + } + }) + } +} + func assignParent(parent *pkg.Package, childPackages ...pkg.Package) { for i, jp := range childPackages { if v, ok := jp.Metadata.(pkg.JavaArchive); ok { diff --git a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/Makefile b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/Makefile index b6533f147..c5d3c52a3 100644 --- a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/Makefile +++ b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/Makefile @@ -6,6 +6,7 @@ SBT_JACKSON_CORE = com.fasterxml.jackson.core.jackson-core-2.15.2 OPENSAML_CORE = opensaml-core-3.4.6 API_ALL_SOURCES = api-all-2.0.0-sources SPRING_INSTRUMENTATION = spring-instrumentation-4.3.0-1.0 +MULTIPLE_MATCHING = multiple-matching-2.11.5 $(CACHE_DIR): mkdir -p $(CACHE_DIR) @@ -24,3 +25,6 @@ $(CACHE_DIR)/$(API_ALL_SOURCES).jar: $(CACHE_DIR) $(CACHE_DIR)/$(SPRING_INSTRUMENTATION).jar: $(CACHE_DIR) cd $(SPRING_INSTRUMENTATION) && zip -r $(CACHE_PATH)/$(SPRING_INSTRUMENTATION).jar . + +$(CACHE_DIR)/$(MULTIPLE_MATCHING).jar: $(CACHE_DIR) + cd $(MULTIPLE_MATCHING) && zip -r $(CACHE_PATH)/$(MULTIPLE_MATCHING).jar . diff --git a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/MANIFEST.MF b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/MANIFEST.MF new file mode 100644 index 000000000..525109c73 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 +Created-By: Multi diff --git a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-1/pom.properties b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-1/pom.properties new file mode 100644 index 000000000..43e0d811b --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-1/pom.properties @@ -0,0 +1,3 @@ +version=2.11.5 +groupId=org.multiple +artifactId=multiple-matching-1 diff --git a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-1/pom.xml b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-1/pom.xml new file mode 100644 index 000000000..1c359dd9a --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-1/pom.xml @@ -0,0 +1,8 @@ + + + 4.0.0 + + org.multiple + multiple-matching-1 + 2.11.5 + diff --git a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-2/pom.properties b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-2/pom.properties new file mode 100644 index 000000000..6be2acfbd --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-2/pom.properties @@ -0,0 +1,3 @@ +version=2.11.5 +groupId=org.multiple +artifactId=multiple-matching-2 \ No newline at end of file diff --git a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-2/pom.xml b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-2/pom.xml new file mode 100644 index 000000000..343c49d30 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-2/pom.xml @@ -0,0 +1,8 @@ + + + 4.0.0 + + org.multiple + multiple-matching-2 + 2.11.5 + diff --git a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-3/pom.properties b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-3/pom.properties new file mode 100644 index 000000000..187215b29 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-3/pom.properties @@ -0,0 +1,3 @@ +version=2.11.5 +groupId=org.multiple +artifactId=multiple-matching-3 diff --git a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-3/pom.xml b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-3/pom.xml new file mode 100644 index 000000000..b428bd69b --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/multiple-matching-2.11.5/META-INF/maven/org.multiple/multiple-matching-3/pom.xml @@ -0,0 +1,8 @@ + + + 4.0.0 + + org.multiple + multiple-matching-3 + 2.11.5 + From 92d63df6f55cf875204ccce9a7bdb27f23a40f64 Mon Sep 17 00:00:00 2001 From: Laurent Goderre Date: Wed, 31 Jul 2024 16:13:26 -0400 Subject: [PATCH 119/284] Added the SWI Prolog (swipl) ecosystem (#3076) * Add binary classifier for swipl Signed-off-by: Laurent Goderre * Added cataloger for SWI Prolog Pack packages Signed-off-by: Laurent Goderre --------- Signed-off-by: Laurent Goderre --- .../catalog_packages_cases_test.go | 8 + .../test/integration/catalog_packages_test.go | 2 + .../image-pkg-coverage/swipl/pack/hdt/pack.pl | 10 + internal/constants.go | 2 +- internal/task/package_tasks.go | 2 + schema/json/schema-16.0.15.json | 2582 +++++++++++++++++ schema/json/schema-latest.json | 47 +- .../spdxutil/helpers/originator_supplier.go | 6 + .../helpers/originator_supplier_test.go | 14 + .../internal/spdxutil/helpers/source_info.go | 2 + .../spdxutil/helpers/source_info_test.go | 8 + syft/internal/packagemetadata/generated.go | 1 + syft/internal/packagemetadata/names.go | 1 + syft/internal/packagemetadata/names_test.go | 6 - .../binary/classifier_cataloger_test.go | 11 + syft/pkg/cataloger/binary/classifiers.go | 10 + .../snippets/erlang/27.0/linux-amd64/beam.smp | 9 + .../snippets/swipl/9.3.8/linux-amd64/swipl | Bin 0 -> 347 bytes .../binary/test-fixtures/config.yaml | 7 + syft/pkg/cataloger/swipl/cataloger.go | 15 + syft/pkg/cataloger/swipl/cataloger_test.go | 32 + syft/pkg/cataloger/swipl/package.go | 38 + syft/pkg/cataloger/swipl/package_test.go | 33 + syft/pkg/cataloger/swipl/parse_pack.go | 70 + syft/pkg/cataloger/swipl/parse_pack_test.go | 39 + .../swipl/test-fixtures/glob-paths/pack.pl | 1 + .../pkg/cataloger/swipl/test-fixtures/pack.pl | 10 + syft/pkg/language.go | 4 + syft/pkg/language_test.go | 8 + syft/pkg/swipl.go | 12 + syft/pkg/type.go | 6 + syft/pkg/type_test.go | 4 + 32 files changed, 2992 insertions(+), 8 deletions(-) create mode 100644 cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/swipl/pack/hdt/pack.pl create mode 100644 schema/json/schema-16.0.15.json create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/erlang/27.0/linux-amd64/beam.smp create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/swipl/9.3.8/linux-amd64/swipl create mode 100644 syft/pkg/cataloger/swipl/cataloger.go create mode 100644 syft/pkg/cataloger/swipl/cataloger_test.go create mode 100644 syft/pkg/cataloger/swipl/package.go create mode 100644 syft/pkg/cataloger/swipl/package_test.go create mode 100644 syft/pkg/cataloger/swipl/parse_pack.go create mode 100644 syft/pkg/cataloger/swipl/parse_pack_test.go create mode 100644 syft/pkg/cataloger/swipl/test-fixtures/glob-paths/pack.pl create mode 100644 syft/pkg/cataloger/swipl/test-fixtures/pack.pl create mode 100644 syft/pkg/swipl.go diff --git a/cmd/syft/internal/test/integration/catalog_packages_cases_test.go b/cmd/syft/internal/test/integration/catalog_packages_cases_test.go index ff21bd1c1..55822043e 100644 --- a/cmd/syft/internal/test/integration/catalog_packages_cases_test.go +++ b/cmd/syft/internal/test/integration/catalog_packages_cases_test.go @@ -388,6 +388,14 @@ var dirOnlyTestCases = []testCase{ "swift-numerics": "1.0.2", }, }, + { + name: "find swipl pack package manager packages", + pkgType: pkg.SwiplPackPkg, + pkgLanguage: pkg.Swipl, + pkgInfo: map[string]string{ + "hdt": "0.5.2", + }, + }, { name: "find github action packages (from usage in workflow files and composite actions)", pkgType: pkg.GithubActionPkg, diff --git a/cmd/syft/internal/test/integration/catalog_packages_test.go b/cmd/syft/internal/test/integration/catalog_packages_test.go index 4ba5e3b52..e84d57839 100644 --- a/cmd/syft/internal/test/integration/catalog_packages_test.go +++ b/cmd/syft/internal/test/integration/catalog_packages_test.go @@ -51,6 +51,7 @@ func TestPkgCoverageImage(t *testing.T) { definedLanguages.Remove(pkg.Rust.String()) definedLanguages.Remove(pkg.Dart.String()) definedLanguages.Remove(pkg.Swift.String()) + definedLanguages.Remove(pkg.Swipl.String()) definedLanguages.Remove(pkg.CPP.String()) definedLanguages.Remove(pkg.Haskell.String()) definedLanguages.Remove(pkg.Elixir.String()) @@ -76,6 +77,7 @@ func TestPkgCoverageImage(t *testing.T) { definedPkgs.Remove(string(pkg.LinuxKernelPkg)) definedPkgs.Remove(string(pkg.LinuxKernelModulePkg)) definedPkgs.Remove(string(pkg.SwiftPkg)) + definedPkgs.Remove(string(pkg.SwiplPackPkg)) definedPkgs.Remove(string(pkg.GithubActionPkg)) definedPkgs.Remove(string(pkg.GithubActionWorkflowPkg)) diff --git a/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/swipl/pack/hdt/pack.pl b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/swipl/pack/hdt/pack.pl new file mode 100644 index 000000000..5e706f8d0 --- /dev/null +++ b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/swipl/pack/hdt/pack.pl @@ -0,0 +1,10 @@ +name(hdt). +version('0.5.2'). +% TODO: swipl_version([90121]). +title('Access RDF HDT files'). +keywords(['RDF']). +author( 'Jan Wielemaker', 'J.Wielemaker@vu.nl' ). +packager( 'Jan Wielemaker', 'J.Wielemaker@vu.nl' ). +maintainer( 'Jan Wielemaker', 'J.Wielemaker@vu.nl' ). +home( 'https://github.com/JanWielemaker/hdt' ). +download( 'https://github.com/JanWielemaker/hdt/archive/V*.zip' ). diff --git a/internal/constants.go b/internal/constants.go index 478556fdb..6d1dd1974 100644 --- a/internal/constants.go +++ b/internal/constants.go @@ -3,5 +3,5 @@ package internal const ( // JSONSchemaVersion is the current schema version output by the JSON encoder // This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment. - JSONSchemaVersion = "16.0.14" + JSONSchemaVersion = "16.0.15" ) diff --git a/internal/task/package_tasks.go b/internal/task/package_tasks.go index d9eca298f..88ce35345 100644 --- a/internal/task/package_tasks.go +++ b/internal/task/package_tasks.go @@ -29,6 +29,7 @@ import ( "github.com/anchore/syft/syft/pkg/cataloger/rust" sbomCataloger "github.com/anchore/syft/syft/pkg/cataloger/sbom" "github.com/anchore/syft/syft/pkg/cataloger/swift" + "github.com/anchore/syft/syft/pkg/cataloger/swipl" "github.com/anchore/syft/syft/pkg/cataloger/wordpress" ) @@ -93,6 +94,7 @@ func DefaultPackageTaskFactories() PackageTaskFactories { newSimplePackageTaskFactory(rust.NewCargoLockCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "rust", "cargo"), newSimplePackageTaskFactory(swift.NewCocoapodsCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "swift", "cocoapods"), newSimplePackageTaskFactory(swift.NewSwiftPackageManagerCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "swift", "spm"), + newSimplePackageTaskFactory(swipl.NewSwiplPackCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "swipl", "pack"), // language-specific package for both image and directory scans (but not necessarily declared) //////////////////////////////////////// newSimplePackageTaskFactory(dotnet.NewDotnetPortableExecutableCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, "dotnet", "c#", "binary"), diff --git a/schema/json/schema-16.0.15.json b/schema/json/schema-16.0.15.json new file mode 100644 index 000000000..1bab78aa6 --- /dev/null +++ b/schema/json/schema-16.0.15.json @@ -0,0 +1,2582 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "anchore.io/schema/syft/json/16.0.15/document", + "$ref": "#/$defs/Document", + "$defs": { + "AlpmDbEntry": { + "properties": { + "basepackage": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "packager": { + "type": "string" + }, + "url": { + "type": "string" + }, + "validation": { + "type": "string" + }, + "reason": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "backup": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "basepackage", + "package", + "version", + "description", + "architecture", + "size", + "packager", + "url", + "validation", + "reason", + "files", + "backup" + ] + }, + "AlpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "type": { + "type": "string" + }, + "uid": { + "type": "string" + }, + "gid": { + "type": "string" + }, + "time": { + "type": "string", + "format": "date-time" + }, + "size": { + "type": "string" + }, + "link": { + "type": "string" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object" + }, + "ApkDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "originPackage": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "version": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "url": { + "type": "string" + }, + "description": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "installedSize": { + "type": "integer" + }, + "pullDependencies": { + "items": { + "type": "string" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "pullChecksum": { + "type": "string" + }, + "gitCommitOfApkPort": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/ApkFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "originPackage", + "maintainer", + "version", + "architecture", + "url", + "description", + "size", + "installedSize", + "pullDependencies", + "provides", + "pullChecksum", + "gitCommitOfApkPort", + "files" + ] + }, + "ApkFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "ownerUid": { + "type": "string" + }, + "ownerGid": { + "type": "string" + }, + "permissions": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "BinarySignature": { + "properties": { + "matches": { + "items": { + "$ref": "#/$defs/ClassifierMatch" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "matches" + ] + }, + "CConanFileEntry": { + "properties": { + "ref": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanInfoEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "build_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "py_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "options": { + "$ref": "#/$defs/KeyValues" + }, + "path": { + "type": "string" + }, + "context": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockV2Entry": { + "properties": { + "ref": { + "type": "string" + }, + "packageID": { + "type": "string" + }, + "username": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "recipeRevision": { + "type": "string" + }, + "packageRevision": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CPE": { + "properties": { + "cpe": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "cpe" + ] + }, + "ClassifierMatch": { + "properties": { + "classifier": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Location" + } + }, + "type": "object", + "required": [ + "classifier", + "location" + ] + }, + "CocoaPodfileLockEntry": { + "properties": { + "checksum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "checksum" + ] + }, + "Coordinates": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "DartPubspecLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hosted_url": { + "type": "string" + }, + "vcs_url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Descriptor": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "configuration": true + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Digest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "Document": { + "properties": { + "artifacts": { + "items": { + "$ref": "#/$defs/Package" + }, + "type": "array" + }, + "artifactRelationships": { + "items": { + "$ref": "#/$defs/Relationship" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/File" + }, + "type": "array" + }, + "source": { + "$ref": "#/$defs/Source" + }, + "distro": { + "$ref": "#/$defs/LinuxRelease" + }, + "descriptor": { + "$ref": "#/$defs/Descriptor" + }, + "schema": { + "$ref": "#/$defs/Schema" + } + }, + "type": "object", + "required": [ + "artifacts", + "artifactRelationships", + "source", + "distro", + "descriptor", + "schema" + ] + }, + "DotnetDepsEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "path": { + "type": "string" + }, + "sha512": { + "type": "string" + }, + "hashPath": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "path", + "sha512", + "hashPath" + ] + }, + "DotnetPortableExecutableEntry": { + "properties": { + "assemblyVersion": { + "type": "string" + }, + "legalCopyright": { + "type": "string" + }, + "comments": { + "type": "string" + }, + "internalName": { + "type": "string" + }, + "companyName": { + "type": "string" + }, + "productName": { + "type": "string" + }, + "productVersion": { + "type": "string" + } + }, + "type": "object", + "required": [ + "assemblyVersion", + "legalCopyright", + "companyName", + "productName", + "productVersion" + ] + }, + "DpkgDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ] + }, + "DpkgFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "isConfigFile": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "path", + "isConfigFile" + ] + }, + "ELFSecurityFeatures": { + "properties": { + "symbolTableStripped": { + "type": "boolean" + }, + "stackCanary": { + "type": "boolean" + }, + "nx": { + "type": "boolean" + }, + "relRO": { + "type": "string" + }, + "pie": { + "type": "boolean" + }, + "dso": { + "type": "boolean" + }, + "safeStack": { + "type": "boolean" + }, + "cfi": { + "type": "boolean" + }, + "fortify": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "symbolTableStripped", + "nx", + "relRO", + "pie", + "dso" + ] + }, + "ElfBinaryPackageNoteJsonPayload": { + "properties": { + "type": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "osCPE": { + "type": "string" + }, + "os": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "system": { + "type": "string" + }, + "vendor": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "commit": { + "type": "string" + } + }, + "type": "object" + }, + "ElixirMixLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "ErlangRebarLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "Executable": { + "properties": { + "format": { + "type": "string" + }, + "hasExports": { + "type": "boolean" + }, + "hasEntrypoint": { + "type": "boolean" + }, + "importedLibraries": { + "items": { + "type": "string" + }, + "type": "array" + }, + "elfSecurityFeatures": { + "$ref": "#/$defs/ELFSecurityFeatures" + } + }, + "type": "object", + "required": [ + "format", + "hasExports", + "hasEntrypoint", + "importedLibraries" + ] + }, + "File": { + "properties": { + "id": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Coordinates" + }, + "metadata": { + "$ref": "#/$defs/FileMetadataEntry" + }, + "contents": { + "type": "string" + }, + "digests": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/FileLicense" + }, + "type": "array" + }, + "executable": { + "$ref": "#/$defs/Executable" + } + }, + "type": "object", + "required": [ + "id", + "location" + ] + }, + "FileLicense": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "evidence": { + "$ref": "#/$defs/FileLicenseEvidence" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type" + ] + }, + "FileLicenseEvidence": { + "properties": { + "confidence": { + "type": "integer" + }, + "offset": { + "type": "integer" + }, + "extent": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "confidence", + "offset", + "extent" + ] + }, + "FileMetadataEntry": { + "properties": { + "mode": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "linkDestination": { + "type": "string" + }, + "userID": { + "type": "integer" + }, + "groupID": { + "type": "integer" + }, + "mimeType": { + "type": "string" + }, + "size": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "mode", + "type", + "userID", + "groupID", + "mimeType", + "size" + ] + }, + "GoModuleBuildinfoEntry": { + "properties": { + "goBuildSettings": { + "$ref": "#/$defs/KeyValues" + }, + "goCompiledVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "h1Digest": { + "type": "string" + }, + "mainModule": { + "type": "string" + }, + "goCryptoSettings": { + "items": { + "type": "string" + }, + "type": "array" + }, + "goExperiments": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "goCompiledVersion", + "architecture" + ] + }, + "GoModuleEntry": { + "properties": { + "h1Digest": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackEntry": { + "properties": { + "pkgHash": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackLockEntry": { + "properties": { + "pkgHash": { + "type": "string" + }, + "snapshotURL": { + "type": "string" + } + }, + "type": "object" + }, + "IDLikes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "JavaArchive": { + "properties": { + "virtualPath": { + "type": "string" + }, + "manifest": { + "$ref": "#/$defs/JavaManifest" + }, + "pomProperties": { + "$ref": "#/$defs/JavaPomProperties" + }, + "pomProject": { + "$ref": "#/$defs/JavaPomProject" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "virtualPath" + ] + }, + "JavaManifest": { + "properties": { + "main": { + "$ref": "#/$defs/KeyValues" + }, + "sections": { + "items": { + "$ref": "#/$defs/KeyValues" + }, + "type": "array" + } + }, + "type": "object" + }, + "JavaPomParent": { + "properties": { + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object", + "required": [ + "groupId", + "artifactId", + "version" + ] + }, + "JavaPomProject": { + "properties": { + "path": { + "type": "string" + }, + "parent": { + "$ref": "#/$defs/JavaPomParent" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "groupId", + "artifactId", + "version", + "name" + ] + }, + "JavaPomProperties": { + "properties": { + "path": { + "type": "string" + }, + "name": { + "type": "string" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "extraFields": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "name", + "groupId", + "artifactId", + "version" + ] + }, + "JavascriptNpmPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "private": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "homepage", + "description", + "url", + "private" + ] + }, + "JavascriptNpmPackageLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "JavascriptYarnLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "KeyValue": { + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "key", + "value" + ] + }, + "KeyValues": { + "items": { + "$ref": "#/$defs/KeyValue" + }, + "type": "array" + }, + "License": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "urls": { + "items": { + "type": "string" + }, + "type": "array" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type", + "urls", + "locations" + ] + }, + "LinuxKernelArchive": { + "properties": { + "name": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "version": { + "type": "string" + }, + "extendedVersion": { + "type": "string" + }, + "buildTime": { + "type": "string" + }, + "author": { + "type": "string" + }, + "format": { + "type": "string" + }, + "rwRootFS": { + "type": "boolean" + }, + "swapDevice": { + "type": "integer" + }, + "rootDevice": { + "type": "integer" + }, + "videoMode": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "architecture", + "version" + ] + }, + "LinuxKernelModule": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "path": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "license": { + "type": "string" + }, + "kernelVersion": { + "type": "string" + }, + "versionMagic": { + "type": "string" + }, + "parameters": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/LinuxKernelModuleParameter" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "LinuxKernelModuleParameter": { + "properties": { + "type": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "type": "object" + }, + "LinuxRelease": { + "properties": { + "prettyName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" + }, + "idLike": { + "$ref": "#/$defs/IDLikes" + }, + "version": { + "type": "string" + }, + "versionID": { + "type": "string" + }, + "versionCodename": { + "type": "string" + }, + "buildID": { + "type": "string" + }, + "imageID": { + "type": "string" + }, + "imageVersion": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "variantID": { + "type": "string" + }, + "homeURL": { + "type": "string" + }, + "supportURL": { + "type": "string" + }, + "bugReportURL": { + "type": "string" + }, + "privacyPolicyURL": { + "type": "string" + }, + "cpeName": { + "type": "string" + }, + "supportEnd": { + "type": "string" + } + }, + "type": "object" + }, + "Location": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + }, + "accessPath": { + "type": "string" + }, + "annotations": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "accessPath" + ] + }, + "LuarocksPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "dependencies": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "name", + "version", + "license", + "homepage", + "description", + "url", + "dependencies" + ] + }, + "MicrosoftKbPatch": { + "properties": { + "product_id": { + "type": "string" + }, + "kb": { + "type": "string" + } + }, + "type": "object", + "required": [ + "product_id", + "kb" + ] + }, + "NixStoreEntry": { + "properties": { + "outputHash": { + "type": "string" + }, + "output": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "outputHash", + "files" + ] + }, + "Package": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "foundBy": { + "type": "string" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "licenses": { + "$ref": "#/$defs/licenses" + }, + "language": { + "type": "string" + }, + "cpes": { + "$ref": "#/$defs/cpes" + }, + "purl": { + "type": "string" + }, + "metadataType": { + "type": "string" + }, + "metadata": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/AlpmDbEntry" + }, + { + "$ref": "#/$defs/ApkDbEntry" + }, + { + "$ref": "#/$defs/BinarySignature" + }, + { + "$ref": "#/$defs/CConanFileEntry" + }, + { + "$ref": "#/$defs/CConanInfoEntry" + }, + { + "$ref": "#/$defs/CConanLockEntry" + }, + { + "$ref": "#/$defs/CConanLockV2Entry" + }, + { + "$ref": "#/$defs/CocoaPodfileLockEntry" + }, + { + "$ref": "#/$defs/DartPubspecLockEntry" + }, + { + "$ref": "#/$defs/DotnetDepsEntry" + }, + { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + }, + { + "$ref": "#/$defs/DpkgDbEntry" + }, + { + "$ref": "#/$defs/ElfBinaryPackageNoteJsonPayload" + }, + { + "$ref": "#/$defs/ElixirMixLockEntry" + }, + { + "$ref": "#/$defs/ErlangRebarLockEntry" + }, + { + "$ref": "#/$defs/GoModuleBuildinfoEntry" + }, + { + "$ref": "#/$defs/GoModuleEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackLockEntry" + }, + { + "$ref": "#/$defs/JavaArchive" + }, + { + "$ref": "#/$defs/JavascriptNpmPackage" + }, + { + "$ref": "#/$defs/JavascriptNpmPackageLockEntry" + }, + { + "$ref": "#/$defs/JavascriptYarnLockEntry" + }, + { + "$ref": "#/$defs/LinuxKernelArchive" + }, + { + "$ref": "#/$defs/LinuxKernelModule" + }, + { + "$ref": "#/$defs/LuarocksPackage" + }, + { + "$ref": "#/$defs/MicrosoftKbPatch" + }, + { + "$ref": "#/$defs/NixStoreEntry" + }, + { + "$ref": "#/$defs/PhpComposerInstalledEntry" + }, + { + "$ref": "#/$defs/PhpComposerLockEntry" + }, + { + "$ref": "#/$defs/PhpPeclEntry" + }, + { + "$ref": "#/$defs/PortageDbEntry" + }, + { + "$ref": "#/$defs/PythonPackage" + }, + { + "$ref": "#/$defs/PythonPipRequirementsEntry" + }, + { + "$ref": "#/$defs/PythonPipfileLockEntry" + }, + { + "$ref": "#/$defs/PythonPoetryLockEntry" + }, + { + "$ref": "#/$defs/RDescription" + }, + { + "$ref": "#/$defs/RpmArchive" + }, + { + "$ref": "#/$defs/RpmDbEntry" + }, + { + "$ref": "#/$defs/RubyGemspec" + }, + { + "$ref": "#/$defs/RustCargoAuditEntry" + }, + { + "$ref": "#/$defs/RustCargoLockEntry" + }, + { + "$ref": "#/$defs/SwiftPackageManagerLockEntry" + }, + { + "$ref": "#/$defs/SwiplpackPackage" + }, + { + "$ref": "#/$defs/WordpressPluginEntry" + } + ] + } + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "foundBy", + "locations", + "licenses", + "language", + "cpes", + "purl" + ] + }, + "PhpComposerAuthors": { + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name" + ] + }, + "PhpComposerExternalReference": { + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "shasum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "type", + "url", + "reference" + ] + }, + "PhpComposerInstalledEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpComposerLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpPeclEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "PortageDbEntry": { + "properties": { + "installedSize": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/PortageFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "installedSize", + "files" + ] + }, + "PortageFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonDirectURLOriginInfo": { + "properties": { + "url": { + "type": "string" + }, + "commitId": { + "type": "string" + }, + "vcs": { + "type": "string" + } + }, + "type": "object", + "required": [ + "url" + ] + }, + "PythonFileDigest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "PythonFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/PythonFileDigest" + }, + "size": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/PythonFileRecord" + }, + "type": "array" + }, + "sitePackagesRootPath": { + "type": "string" + }, + "topLevelPackages": { + "items": { + "type": "string" + }, + "type": "array" + }, + "directUrlOrigin": { + "$ref": "#/$defs/PythonDirectURLOriginInfo" + }, + "requiresPython": { + "type": "string" + }, + "requiresDist": { + "items": { + "type": "string" + }, + "type": "array" + }, + "providesExtra": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "platform", + "sitePackagesRootPath" + ] + }, + "PythonPipRequirementsEntry": { + "properties": { + "name": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + }, + "versionConstraint": { + "type": "string" + }, + "url": { + "type": "string" + }, + "markers": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "versionConstraint" + ] + }, + "PythonPipfileLockEntry": { + "properties": { + "hashes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "index": { + "type": "string" + } + }, + "type": "object", + "required": [ + "hashes", + "index" + ] + }, + "PythonPoetryLockDependencyEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "optional": { + "type": "boolean" + }, + "markers": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "optional" + ] + }, + "PythonPoetryLockEntry": { + "properties": { + "index": { + "type": "string" + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonPoetryLockDependencyEntry" + }, + "type": "array" + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonPoetryLockExtraEntry" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ] + }, + "PythonPoetryLockExtraEntry": { + "properties": { + "name": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ] + }, + "RDescription": { + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "url": { + "items": { + "type": "string" + }, + "type": "array" + }, + "repository": { + "type": "string" + }, + "built": { + "type": "string" + }, + "needsCompilation": { + "type": "boolean" + }, + "imports": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "suggests": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "Relationship": { + "properties": { + "parent": { + "type": "string" + }, + "child": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "parent", + "child", + "type" + ] + }, + "RpmArchive": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmDbEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "mode": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "userName": { + "type": "string" + }, + "groupName": { + "type": "string" + }, + "flags": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "mode", + "size", + "digest", + "userName", + "groupName", + "flags" + ] + }, + "RubyGemspec": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "RustCargoAuditEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source" + ] + }, + "RustCargoLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + }, + "checksum": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "checksum", + "dependencies" + ] + }, + "Schema": { + "properties": { + "version": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "version", + "url" + ] + }, + "Source": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "metadata" + ] + }, + "SwiftPackageManagerLockEntry": { + "properties": { + "revision": { + "type": "string" + } + }, + "type": "object", + "required": [ + "revision" + ] + }, + "SwiplpackPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "packager": { + "type": "string" + }, + "packagerEmail": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "packager", + "packagerEmail", + "homepage", + "dependencies" + ] + }, + "WordpressPluginEntry": { + "properties": { + "pluginInstallDirectory": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorUri": { + "type": "string" + } + }, + "type": "object", + "required": [ + "pluginInstallDirectory" + ] + }, + "cpes": { + "items": { + "$ref": "#/$defs/CPE" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/License" + }, + "type": "array" + } + } +} diff --git a/schema/json/schema-latest.json b/schema/json/schema-latest.json index 028f3004b..1bab78aa6 100644 --- a/schema/json/schema-latest.json +++ b/schema/json/schema-latest.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "anchore.io/schema/syft/json/16.0.14/document", + "$id": "anchore.io/schema/syft/json/16.0.15/document", "$ref": "#/$defs/Document", "$defs": { "AlpmDbEntry": { @@ -1608,6 +1608,9 @@ { "$ref": "#/$defs/SwiftPackageManagerLockEntry" }, + { + "$ref": "#/$defs/SwiplpackPackage" + }, { "$ref": "#/$defs/WordpressPluginEntry" } @@ -2504,6 +2507,48 @@ "revision" ] }, + "SwiplpackPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "packager": { + "type": "string" + }, + "packagerEmail": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "packager", + "packagerEmail", + "homepage", + "dependencies" + ] + }, "WordpressPluginEntry": { "properties": { "pluginInstallDirectory": { diff --git a/syft/format/internal/spdxutil/helpers/originator_supplier.go b/syft/format/internal/spdxutil/helpers/originator_supplier.go index 5840b6bae..61ebf3675 100644 --- a/syft/format/internal/spdxutil/helpers/originator_supplier.go +++ b/syft/format/internal/spdxutil/helpers/originator_supplier.go @@ -103,6 +103,8 @@ func Originator(p pkg.Package) (typ string, author string) { // nolint: funlen // it seems that the vast majority of the time the author is an org, not a person typ = orgType author = metadata.Author + case pkg.SwiplPackEntry: + author = formatPersonOrOrg(metadata.Author, metadata.AuthorEmail) } if typ == "" && author != "" { @@ -144,6 +146,10 @@ func Supplier(p pkg.Package) (typ string, author string) { author = metadata.Packager } + if metadata, ok := p.Metadata.(pkg.SwiplPackEntry); ok { + author = formatPersonOrOrg(metadata.Packager, metadata.PackagerEmail) + } + if author == "" { // TODO: this uses the Originator function for now until a better distinction can be made for supplier return Originator(p) diff --git a/syft/format/internal/spdxutil/helpers/originator_supplier_test.go b/syft/format/internal/spdxutil/helpers/originator_supplier_test.go index 705d0ab98..5c46685f2 100644 --- a/syft/format/internal/spdxutil/helpers/originator_supplier_test.go +++ b/syft/format/internal/spdxutil/helpers/originator_supplier_test.go @@ -40,6 +40,7 @@ func Test_OriginatorSupplier(t *testing.T) { pkg.RustBinaryAuditEntry{}, pkg.RustCargoLockEntry{}, pkg.SwiftPackageManagerResolvedEntry{}, + pkg.SwiplPackEntry{}, pkg.YarnLockEntry{}, ) tests := []struct { @@ -336,6 +337,19 @@ func Test_OriginatorSupplier(t *testing.T) { originator: "Organization: auth", supplier: "Organization: auth", }, + { + name: "from swipl pack", + input: pkg.Package{ + Metadata: pkg.SwiplPackEntry{ + Author: "auth", + AuthorEmail: "auth@auth.gov", + Packager: "me", + PackagerEmail: "me@auth.com", + }, + }, + originator: "Person: auth (auth@auth.gov)", + supplier: "Person: me (me@auth.com)", + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { diff --git a/syft/format/internal/spdxutil/helpers/source_info.go b/syft/format/internal/spdxutil/helpers/source_info.go index a4970943a..770577112 100644 --- a/syft/format/internal/spdxutil/helpers/source_info.go +++ b/syft/format/internal/spdxutil/helpers/source_info.go @@ -62,6 +62,8 @@ func SourceInfo(p pkg.Package) string { answer = "acquired package info from Rockspec package file" case pkg.SwiftPkg: answer = "acquired package info from resolved Swift package manifest" + case pkg.SwiplPackPkg: + answer = "acquired package info from SWI Prolo pack package file" case pkg.GithubActionPkg, pkg.GithubActionWorkflowPkg: answer = "acquired package info from GitHub Actions workflow file or composite action file" case pkg.WordpressPluginPkg: diff --git a/syft/format/internal/spdxutil/helpers/source_info_test.go b/syft/format/internal/spdxutil/helpers/source_info_test.go index 82f89a0ea..df76ac7eb 100644 --- a/syft/format/internal/spdxutil/helpers/source_info_test.go +++ b/syft/format/internal/spdxutil/helpers/source_info_test.go @@ -263,6 +263,14 @@ func Test_SourceInfo(t *testing.T) { "from resolved Swift package manifest", }, }, + { + input: pkg.Package{ + Type: pkg.SwiplPackPkg, + }, + expected: []string{ + "acquired package info from SWI Prolo pack package file", + }, + }, { input: pkg.Package{ Type: pkg.GithubActionPkg, diff --git a/syft/internal/packagemetadata/generated.go b/syft/internal/packagemetadata/generated.go index 07d534744..db843261c 100644 --- a/syft/internal/packagemetadata/generated.go +++ b/syft/internal/packagemetadata/generated.go @@ -49,6 +49,7 @@ func AllTypes() []any { pkg.RustBinaryAuditEntry{}, pkg.RustCargoLockEntry{}, pkg.SwiftPackageManagerResolvedEntry{}, + pkg.SwiplPackEntry{}, pkg.WordpressPluginEntry{}, pkg.YarnLockEntry{}, } diff --git a/syft/internal/packagemetadata/names.go b/syft/internal/packagemetadata/names.go index 97ba0a958..52deebce0 100644 --- a/syft/internal/packagemetadata/names.go +++ b/syft/internal/packagemetadata/names.go @@ -102,6 +102,7 @@ var jsonTypes = makeJSONTypes( jsonNames(pkg.RpmDBEntry{}, "rpm-db-entry", "RpmMetadata", "RpmdbMetadata"), jsonNamesWithoutLookup(pkg.RpmArchive{}, "rpm-archive", "RpmMetadata"), // the legacy value is split into two types, where the other is preferred jsonNames(pkg.SwiftPackageManagerResolvedEntry{}, "swift-package-manager-lock-entry", "SwiftPackageManagerMetadata"), + jsonNames(pkg.SwiplPackEntry{}, "swiplpack-package"), jsonNames(pkg.RustCargoLockEntry{}, "rust-cargo-lock-entry", "RustCargoPackageMetadata"), jsonNamesWithoutLookup(pkg.RustBinaryAuditEntry{}, "rust-cargo-audit-entry", "RustCargoPackageMetadata"), // the legacy value is split into two types, where the other is preferred jsonNames(pkg.WordpressPluginEntry{}, "wordpress-plugin-entry", "WordpressMetadata"), diff --git a/syft/internal/packagemetadata/names_test.go b/syft/internal/packagemetadata/names_test.go index 72bd3b790..ee73d8437 100644 --- a/syft/internal/packagemetadata/names_test.go +++ b/syft/internal/packagemetadata/names_test.go @@ -473,12 +473,6 @@ func Test_JSONName_JSONLegacyName(t *testing.T) { expectedJSONName: "rpm-archive", expectedLegacyName: "RpmMetadata", // note: conflicts with <=v11.x schema for "rpm-db-entry" metadata type }, - { - name: "SwiftPackageManagerMetadata", - metadata: pkg.SwiftPackageManagerResolvedEntry{}, - expectedJSONName: "swift-package-manager-lock-entry", - expectedLegacyName: "SwiftPackageManagerMetadata", - }, { name: "CargoPackageMetadata", metadata: pkg.RustCargoLockEntry{}, diff --git a/syft/pkg/cataloger/binary/classifier_cataloger_test.go b/syft/pkg/cataloger/binary/classifier_cataloger_test.go index 9876df496..dcc9849c6 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger_test.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger_test.go @@ -929,6 +929,17 @@ func Test_Cataloger_PositiveCases(t *testing.T) { Metadata: metadata("erlang-alpine-binary"), }, }, + { + logicalFixture: "swipl/9.3.8/linux-amd64", + expected: pkg.Package{ + Name: "swipl", + Version: "9.3.8", + Type: "binary", + PURL: "pkg:generic/swipl@9.3.8", + Locations: locations("swipl"), + Metadata: metadata("swipl-binary"), + }, + }, { logicalFixture: "nginx/1.25.1/linux-amd64", expected: pkg.Package{ diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index e2797b047..0d491f25f 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -428,6 +428,16 @@ func DefaultClassifiers() []Classifier { PURL: mustPURL("pkg:generic/erlang@version"), CPEs: singleCPE("cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*"), }, + { + Class: "swipl-binary", + FileGlob: "**/swipl", + EvidenceMatcher: FileContentsVersionMatcher( + `(?m)swipl-(?P[0-9]+\.[0-9]+\.[0-9]+)\/`, + ), + Package: "swipl", + PURL: mustPURL("pkg:generic/swipl@version"), + CPEs: singleCPE("cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*"), + }, { Class: "consul-binary", FileGlob: "**/consul", diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/erlang/27.0/linux-amd64/beam.smp b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/erlang/27.0/linux-amd64/beam.smp new file mode 100644 index 000000000..473d28684 --- /dev/null +++ b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/erlang/27.0/linux-amd64/beam.smp @@ -0,0 +1,9 @@ +name: beam.smp +offset: 6378906 +length: 140 +snippetSha256: 186c882decc4160bfcfbdddaee08e8364675c795d3e85697422fbd7218452ee2 +fileSha256: f84f0ffc2e397abcf5f081b865e241017b1793c2ec38f5136bff4e5e21ffdad7 + +### byte snippet to follow ### +ied by configure */ +#define ERTS_EMU_CMDLINE_FLAGS " -fno-strict-aliasing -fno-common -g -O2 -I/usr/src/otp_src_27.0/erts/x86_64-pc-linux-mu \ No newline at end of file diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/swipl/9.3.8/linux-amd64/swipl b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/swipl/9.3.8/linux-amd64/swipl new file mode 100644 index 0000000000000000000000000000000000000000..422996cd32bf2ea9a46480c03d54fab76b510b29 GIT binary patch literal 347 zcmZvXO=`n15Jqk2O3c(&*hf+NaC{ s-*<=R;6J%i>wH!HKxIw*4W*CjM5OK>-_Y($KdkrtX;_suf5rcFA8K=BVgLXD literal 0 HcmV?d00001 diff --git a/syft/pkg/cataloger/binary/test-fixtures/config.yaml b/syft/pkg/cataloger/binary/test-fixtures/config.yaml index b00fd2103..50dd6bcc8 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/config.yaml +++ b/syft/pkg/cataloger/binary/test-fixtures/config.yaml @@ -71,6 +71,13 @@ from-images: paths: - /usr/local/lib/erlang/erts-15.0/bin/beam.smp + - version: 9.3.8 + images: + - ref: swipl:9.3.8@sha256:6a15e6a03afe943228924a5502ba763e653ff28d9b3391e2b3e1fc3e991f37d4 + platform: linux/amd64 + paths: + - /usr/lib/swipl/bin/x86_64-linux/swipl + - version: 1.21.3 images: - ref: golang:1.21.3@sha256:3ce8313c3513515040870c55e0c041a2b94f3576a58cfd3948633604214aa811 diff --git a/syft/pkg/cataloger/swipl/cataloger.go b/syft/pkg/cataloger/swipl/cataloger.go new file mode 100644 index 000000000..be714e3c6 --- /dev/null +++ b/syft/pkg/cataloger/swipl/cataloger.go @@ -0,0 +1,15 @@ +/* +Package swipl provides a Cataloger implementation relating to packages within the SWI Prolog language ecosystem. +*/ +package swipl + +import ( + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/generic" +) + +// NewSwiplPackCataloger returns a new SWI Prolog Pack package manager cataloger object. +func NewSwiplPackCataloger() pkg.Cataloger { + return generic.NewCataloger("swipl-pack-cataloger"). + WithParserByGlobs(parsePackPackage, "**/pack.pl") +} diff --git a/syft/pkg/cataloger/swipl/cataloger_test.go b/syft/pkg/cataloger/swipl/cataloger_test.go new file mode 100644 index 000000000..dbe53b4f0 --- /dev/null +++ b/syft/pkg/cataloger/swipl/cataloger_test.go @@ -0,0 +1,32 @@ +package swipl + +import ( + "testing" + + "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" +) + +func Test_Cataloger_Globs(t *testing.T) { + tests := []struct { + name string + fixture string + expected []string + }{ + { + name: "obtain swipl pack files", + fixture: "test-fixtures/glob-paths", + expected: []string{ + "pack.pl", + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + pkgtest.NewCatalogTester(). + FromDirectory(t, test.fixture). + ExpectsResolverContentQueries(test.expected). + TestCataloger(t, NewSwiplPackCataloger()) + }) + } +} diff --git a/syft/pkg/cataloger/swipl/package.go b/syft/pkg/cataloger/swipl/package.go new file mode 100644 index 000000000..252dda56b --- /dev/null +++ b/syft/pkg/cataloger/swipl/package.go @@ -0,0 +1,38 @@ +package swipl + +import ( + // "strings" + + "github.com/anchore/packageurl-go" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" +) + +func newSwiplPackPackage(m pkg.SwiplPackEntry, locations ...file.Location) pkg.Package { + p := pkg.Package{ + Name: m.Name, + Version: m.Version, + PURL: swiplpackPackageURL(m.Name, m.Version), + Locations: file.NewLocationSet(locations...), + Type: pkg.SwiplPackPkg, + Language: pkg.Swipl, + Metadata: m, + } + + p.SetID() + + return p +} + +func swiplpackPackageURL(name, version string) string { + var qualifiers packageurl.Qualifiers + + return packageurl.NewPackageURL( + "swiplpack", + "", + name, + version, + qualifiers, + "", + ).ToString() +} diff --git a/syft/pkg/cataloger/swipl/package_test.go b/syft/pkg/cataloger/swipl/package_test.go new file mode 100644 index 000000000..a4bd0ae2d --- /dev/null +++ b/syft/pkg/cataloger/swipl/package_test.go @@ -0,0 +1,33 @@ +package swipl + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_swiplpackPackageURL(t *testing.T) { + type args struct { + name string + version string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "go case", + args: args{ + name: "name", + version: "v0.1.0", + }, + want: "pkg:swiplpack/name@v0.1.0", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.want, swiplpackPackageURL(tt.args.name, tt.args.version)) + }) + } +} diff --git a/syft/pkg/cataloger/swipl/parse_pack.go b/syft/pkg/cataloger/swipl/parse_pack.go new file mode 100644 index 000000000..e062da963 --- /dev/null +++ b/syft/pkg/cataloger/swipl/parse_pack.go @@ -0,0 +1,70 @@ +package swipl + +import ( + "context" + "io" + "regexp" + + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/generic" +) + +func parsePackPackage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { + var pkgs []pkg.Package + + nameRe := regexp.MustCompile(`name\(\s*'?([^')]+)'?\s*\)`) + versionRe := regexp.MustCompile(`version\('([^']+)'\)`) + homeRe := regexp.MustCompile(`home\(\s*'([^']+)'\s*\)`) + authorRe := regexp.MustCompile(`(author|packager)\(\s*'([^']+)'\s*(?:,\s*'([^']+)'\s*)?\)`) + + data, err := io.ReadAll(reader) + if err != nil { + log.WithFields("error", err).Trace("unable to parse Rockspec app") + return nil, nil, nil + } + + name := nameRe.FindSubmatch(data) + version := versionRe.FindSubmatch(data) + + if name == nil || version == nil { + log.Debugf("encountered pack.pl file without a name and/or version field, ignoring (path=%q)", reader.Path()) + return nil, nil, nil + } + + entry := pkg.SwiplPackEntry{ + Name: string(name[1]), + Version: string(version[1]), + } + + home := homeRe.FindSubmatch(data) + + if home != nil { + entry.Homepage = string(home[1]) + } + + authors := authorRe.FindAllSubmatch(data, -1) + + for _, a := range authors { + switch string(a[1]) { + case "author": + entry.Author = string(a[2]) + entry.AuthorEmail = string(a[3]) + case "packager": + entry.Packager = string(a[2]) + entry.PackagerEmail = string(a[3]) + } + } + + pkgs = append( + pkgs, + newSwiplPackPackage( + entry, + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + ) + + return pkgs, nil, nil +} diff --git a/syft/pkg/cataloger/swipl/parse_pack_test.go b/syft/pkg/cataloger/swipl/parse_pack_test.go new file mode 100644 index 000000000..28feb7690 --- /dev/null +++ b/syft/pkg/cataloger/swipl/parse_pack_test.go @@ -0,0 +1,39 @@ +package swipl + +import ( + "testing" + + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" +) + +func TestParsePackPackage(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, + Metadata: pkg.SwiplPackEntry{ + Name: "hdt", + Version: "0.5.2", + Author: "Jan Wielemaker", + AuthorEmail: "J.Wielemaker@vu.nl", + Packager: "Jan Wielemaker", + PackagerEmail: "J.Wielemaker@vu.nl", + Homepage: "https://github.com/JanWielemaker/hdt", + }, + }, + } + + // TODO: no relationships are under test yet + var expectedRelationships []artifact.Relationship + + pkgtest.TestFileParser(t, fixture, parsePackPackage, expectedPkgs, expectedRelationships) +} diff --git a/syft/pkg/cataloger/swipl/test-fixtures/glob-paths/pack.pl b/syft/pkg/cataloger/swipl/test-fixtures/glob-paths/pack.pl new file mode 100644 index 000000000..882b6040c --- /dev/null +++ b/syft/pkg/cataloger/swipl/test-fixtures/glob-paths/pack.pl @@ -0,0 +1 @@ +bogus \ No newline at end of file diff --git a/syft/pkg/cataloger/swipl/test-fixtures/pack.pl b/syft/pkg/cataloger/swipl/test-fixtures/pack.pl new file mode 100644 index 000000000..5e706f8d0 --- /dev/null +++ b/syft/pkg/cataloger/swipl/test-fixtures/pack.pl @@ -0,0 +1,10 @@ +name(hdt). +version('0.5.2'). +% TODO: swipl_version([90121]). +title('Access RDF HDT files'). +keywords(['RDF']). +author( 'Jan Wielemaker', 'J.Wielemaker@vu.nl' ). +packager( 'Jan Wielemaker', 'J.Wielemaker@vu.nl' ). +maintainer( 'Jan Wielemaker', 'J.Wielemaker@vu.nl' ). +home( 'https://github.com/JanWielemaker/hdt' ). +download( 'https://github.com/JanWielemaker/hdt/archive/V*.zip' ). diff --git a/syft/pkg/language.go b/syft/pkg/language.go index cbde8de35..24e2de35f 100644 --- a/syft/pkg/language.go +++ b/syft/pkg/language.go @@ -28,6 +28,7 @@ const ( Ruby Language = "ruby" Rust Language = "rust" Swift Language = "swift" + Swipl Language = "swipl" ) // AllLanguages is a set of all programming languages detected by syft. @@ -48,6 +49,7 @@ var AllLanguages = []Language{ Ruby, Rust, Swift, + Swipl, } // String returns the string representation of the language. @@ -88,6 +90,8 @@ func LanguageByName(name string) Language { return Dotnet case packageurl.TypeCocoapods, packageurl.TypeSwift, string(CocoapodsPkg): return Swift + case "swipl", string(SwiplPackPkg): + return Swipl case packageurl.TypeConan, string(CPP): return CPP case packageurl.TypeHackage, string(Haskell): diff --git a/syft/pkg/language_test.go b/syft/pkg/language_test.go index 9504c0a55..5519a332b 100644 --- a/syft/pkg/language_test.go +++ b/syft/pkg/language_test.go @@ -78,6 +78,10 @@ func TestLanguageFromPURL(t *testing.T) { purl: "pkg:swift/github.com/apple/swift-numerics/swift-numerics@1.0.2", want: Swift, }, + { + purl: "pkg:swiplpack/conditon@0.1.1", + want: Swipl, + }, { purl: "pkg:luarocks/kong@3.7.0", want: Lua, @@ -219,6 +223,10 @@ func TestLanguageByName(t *testing.T) { name: "swift", language: Swift, }, + { + name: "swiplpack", + language: Swipl, + }, { name: "pod", language: Swift, diff --git a/syft/pkg/swipl.go b/syft/pkg/swipl.go new file mode 100644 index 000000000..b5413afb0 --- /dev/null +++ b/syft/pkg/swipl.go @@ -0,0 +1,12 @@ +package pkg + +type SwiplPackEntry struct { + Name string `toml:"name" json:"name"` + Version string `toml:"version" json:"version"` + Author string `json:"author" mapstruct:"Author"` + AuthorEmail string `json:"authorEmail" mapstruct:"Authoremail"` + Packager string `json:"packager" mapstructure:"Packager"` + PackagerEmail string `json:"packagerEmail" mapstruct:"Packageremail"` + Homepage string `json:"homepage"` + Dependencies []string `toml:"dependencies" json:"dependencies"` +} diff --git a/syft/pkg/type.go b/syft/pkg/type.go index 8b01af08b..cdb063828 100644 --- a/syft/pkg/type.go +++ b/syft/pkg/type.go @@ -42,6 +42,7 @@ const ( RpmPkg Type = "rpm" RustPkg Type = "rust-crate" SwiftPkg Type = "swift" + SwiplPackPkg Type = "swiplpack" WordpressPluginPkg Type = "wordpress-plugin" ) @@ -78,6 +79,7 @@ var AllPkgs = []Type{ RpmPkg, RustPkg, SwiftPkg, + SwiplPackPkg, WordpressPluginPkg, } @@ -141,6 +143,8 @@ func (t Type) PackageURLType() string { return "cargo" case SwiftPkg: return packageurl.TypeSwift + case SwiplPackPkg: + return "swiplpack" case WordpressPluginPkg: return "wordpress-plugin" default: @@ -217,6 +221,8 @@ func TypeByName(name string) Type { return Rpkg case packageurl.TypeSwift: return SwiftPkg + case "swiplpack": + return SwiplPackPkg case "wordpress-plugin": return WordpressPluginPkg default: diff --git a/syft/pkg/type_test.go b/syft/pkg/type_test.go index f1e7b275b..b79ad772d 100644 --- a/syft/pkg/type_test.go +++ b/syft/pkg/type_test.go @@ -111,6 +111,10 @@ func TestTypeFromPURL(t *testing.T) { purl: "pkg:swift/github.com/apple/swift-numerics/swift-numerics@1.0.2", expected: SwiftPkg, }, + { + purl: "pkg:swiplpack/condition@0.1.1", + expected: SwiplPackPkg, + }, } var pkgTypes []string From 05a10e8bed24d924e5e2550a394a0f837940013a Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Wed, 31 Jul 2024 20:10:17 -0400 Subject: [PATCH 120/284] chore: update release script to use gh from binny (#3084) Signed-off-by: Keith Zantow --- .github/scripts/trigger-release.sh | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/.github/scripts/trigger-release.sh b/.github/scripts/trigger-release.sh index c1a5432ef..8684585b7 100755 --- a/.github/scripts/trigger-release.sh +++ b/.github/scripts/trigger-release.sh @@ -4,12 +4,19 @@ set -eu bold=$(tput bold) normal=$(tput sgr0) -if ! [ -x "$(command -v gh)" ]; then - echo "The GitHub CLI could not be found. To continue follow the instructions at https://github.com/cli/cli#installation" +GH_CLI=.tool/gh + +if ! [ -x "$(command -v $GH_CLI)" ]; then + echo "The GitHub CLI could not be found. run: make bootstrap" exit 1 fi -gh auth status +$GH_CLI auth status + +# set the default repo in cases where multiple remotes are defined +$GH_CLI repo set-default anchore/syft + +export GITHUB_TOKEN="${GITHUB_TOKEN-"$($GH_CLI auth token)"}" # we need all of the git state to determine the next version. Since tagging is done by # the release pipeline it is possible to not have all of the tags from previous releases. @@ -37,7 +44,7 @@ done echo "${bold}Kicking off release for ${NEXT_VERSION}${normal}..." echo -gh workflow run release.yaml -f version=${NEXT_VERSION} +$GH_CLI workflow run release.yaml -f version=${NEXT_VERSION} echo echo "${bold}Waiting for release to start...${normal}" @@ -45,6 +52,6 @@ sleep 10 set +e -echo "${bold}Head to the release workflow to monitor the release:${normal} $(gh run list --workflow=release.yaml --limit=1 --json url --jq '.[].url')" -id=$(gh run list --workflow=release.yaml --limit=1 --json databaseId --jq '.[].databaseId') -gh run watch $id --exit-status || (echo ; echo "${bold}Logs of failed step:${normal}" && GH_PAGER="" gh run view $id --log-failed) +echo "${bold}Head to the release workflow to monitor the release:${normal} $($GH_CLI run list --workflow=release.yaml --limit=1 --json url --jq '.[].url')" +id=$($GH_CLI run list --workflow=release.yaml --limit=1 --json databaseId --jq '.[].databaseId') +$GH_CLI run watch $id --exit-status || (echo ; echo "${bold}Logs of failed step:${normal}" && GH_PAGER="" $GH_CLI run view $id --log-failed) From c84cb2cf84f7b442558eb6f6e4c28141fc5f7db3 Mon Sep 17 00:00:00 2001 From: Christopher Angelo Phillips <32073428+spiffcs@users.noreply.github.com> Date: Thu, 1 Aug 2024 11:29:07 -0400 Subject: [PATCH 121/284] fix: update mainModuleVersion function to always prefix `v` to findings (#3087) * chore: basic fix Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> * test: make sure ldflags are prefixed with v --------- Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> --- syft/pkg/cataloger/golang/cataloger_test.go | 24 +++++++++---------- syft/pkg/cataloger/golang/parse_go_binary.go | 11 +++++++++ .../test-fixtures/image-small/Dockerfile | 3 +-- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/syft/pkg/cataloger/golang/cataloger_test.go b/syft/pkg/cataloger/golang/cataloger_test.go index 0e1526658..f958aa657 100644 --- a/syft/pkg/cataloger/golang/cataloger_test.go +++ b/syft/pkg/cataloger/golang/cataloger_test.go @@ -20,7 +20,7 @@ func Test_PackageCataloger_Binary(t *testing.T) { name: "simple module with dependencies", fixture: "image-small", expectedPkgs: []string{ - "anchore.io/not/real @ (devel) (/run-me)", + "anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/andybalholm/brotli @ v1.0.1 (/run-me)", "github.com/dsnet/compress @ v0.0.2-0.20210315054119-f66993602bf5 (/run-me)", "github.com/golang/snappy @ v0.0.2 (/run-me)", @@ -34,17 +34,17 @@ func Test_PackageCataloger_Binary(t *testing.T) { "stdlib @ go1.22.4 (/run-me)", }, expectedRels: []string{ - "github.com/andybalholm/brotli @ v1.0.1 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", - "github.com/dsnet/compress @ v0.0.2-0.20210315054119-f66993602bf5 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", - "github.com/golang/snappy @ v0.0.2 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", - "github.com/klauspost/compress @ v1.11.4 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", - "github.com/klauspost/pgzip @ v1.2.5 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", - "github.com/mholt/archiver/v3 @ v3.5.1 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", - "github.com/nwaples/rardecode @ v1.1.0 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", - "github.com/pierrec/lz4/v4 @ v4.1.2 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", - "github.com/ulikunitz/xz @ v0.5.9 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", - "github.com/xi2/xz @ v0.0.0-20171230120015-48954b6210f8 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", - "stdlib @ go1.22.4 (/run-me) [dependency-of] anchore.io/not/real @ (devel) (/run-me)", + "github.com/andybalholm/brotli @ v1.0.1 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", + "github.com/dsnet/compress @ v0.0.2-0.20210315054119-f66993602bf5 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", + "github.com/golang/snappy @ v0.0.2 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", + "github.com/klauspost/compress @ v1.11.4 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", + "github.com/klauspost/pgzip @ v1.2.5 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", + "github.com/mholt/archiver/v3 @ v3.5.1 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", + "github.com/nwaples/rardecode @ v1.1.0 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", + "github.com/pierrec/lz4/v4 @ v4.1.2 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", + "github.com/ulikunitz/xz @ v0.5.9 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", + "github.com/xi2/xz @ v0.0.0-20171230120015-48954b6210f8 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", + "stdlib @ go1.22.4 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", }, }, { diff --git a/syft/pkg/cataloger/golang/parse_go_binary.go b/syft/pkg/cataloger/golang/parse_go_binary.go index 7f186ecba..3f62ea4d8 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary.go +++ b/syft/pkg/cataloger/golang/parse_go_binary.go @@ -180,6 +180,10 @@ func (c *goBinaryCataloger) makeGoMainPackage(resolver file.Resolver, mod *exten version := c.findMainModuleVersion(metadata, gbs, reader) if version != "" { + // make sure version is prefixed with v as some build systems parsed + // during `findMainModuleVersion` can include incomplete semver + // vx.x.x is correct + version = ensurePrefix(version, "v") main.Version = version main.PURL = packageURL(main.Name, main.Version) @@ -398,3 +402,10 @@ func createMainModuleFromPath(existing *extendedBuildInfo) debug.Module { Version: devel, } } + +func ensurePrefix(s, prefix string) string { + if !strings.HasPrefix(s, prefix) { + return prefix + s + } + return s +} diff --git a/syft/pkg/cataloger/golang/test-fixtures/image-small/Dockerfile b/syft/pkg/cataloger/golang/test-fixtures/image-small/Dockerfile index be8d93780..9bf5794dc 100644 --- a/syft/pkg/cataloger/golang/test-fixtures/image-small/Dockerfile +++ b/syft/pkg/cataloger/golang/test-fixtures/image-small/Dockerfile @@ -7,8 +7,7 @@ COPY go.mod go.sum ./ RUN go mod download COPY main.go main.go -RUN CGO_ENABLED=0 GOOS=linux go build -o run-me . - +RUN CGO_ENABLED=0 GOOS=linux go build -ldflags "-X main.Version=1.0.0" -o run-me . FROM scratch From 48f1e975f05183390d7c01718865f5f66e3f9012 Mon Sep 17 00:00:00 2001 From: Dor Hayun <94103962+dor-hayun@users.noreply.github.com> Date: Thu, 1 Aug 2024 20:47:15 +0300 Subject: [PATCH 122/284] fix: update 'guessMainPackageNameAndVersionFromPomInfo' and 'artifactIDMatchesFilename' (#3054) - Correct retrieval of package name when main POM file exists - Address issue where wrong package name was retrieved for certain jars - Example case: 'jansi' jar containing multiple jars like 'jansi-win32' - Ensure true is returned when filename matches the artifact ID, prevent random retrieval by checking prefix and suffix - Use fallback check with suffix and prefix if no POM properties file matches the exact artifact name Signed-off-by: dor-hayun Co-authored-by: dor-hayun --- syft/pkg/cataloger/java/archive_parser.go | 15 +++++++++++++-- syft/pkg/cataloger/java/archive_parser_test.go | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/syft/pkg/cataloger/java/archive_parser.go b/syft/pkg/cataloger/java/archive_parser.go index 2262d79fb..789b3b9d3 100644 --- a/syft/pkg/cataloger/java/archive_parser.go +++ b/syft/pkg/cataloger/java/archive_parser.go @@ -301,11 +301,17 @@ func (j *archiveParser) guessMainPackageNameAndVersionFromPomInfo(ctx context.Co properties, _ := pomPropertiesByParentPath(j.archivePath, j.location, pomPropertyMatches) projects, _ := pomProjectByParentPath(j.archivePath, j.location, pomMatches) + // map of all the artifacts in the pom properties, in order to chek exact match with the filename + artifactsMap := make(map[string]bool) + for _, propertiesObj := range properties { + artifactsMap[propertiesObj.ArtifactID] = true + } + parentPaths := maps.Keys(properties) slices.Sort(parentPaths) for _, parentPath := range parentPaths { propertiesObj := properties[parentPath] - if artifactIDMatchesFilename(propertiesObj.ArtifactID, j.fileInfo.name) { + if artifactIDMatchesFilename(propertiesObj.ArtifactID, j.fileInfo.name, artifactsMap) { pomPropertiesObject = propertiesObj if proj, exists := projects[parentPath]; exists { pomProjectObject = proj @@ -343,10 +349,15 @@ func (j *archiveParser) guessMainPackageNameAndVersionFromPomInfo(ctx context.Co return name, version, licenses } -func artifactIDMatchesFilename(artifactID, fileName string) bool { +func artifactIDMatchesFilename(artifactID, fileName string, artifactsMap map[string]bool) bool { if artifactID == "" || fileName == "" { return false } + // Ensure true is returned when filename matches the artifact ID, prevent random retrieval by checking prefix and suffix + if _, exists := artifactsMap[fileName]; exists { + return artifactID == fileName + } + // Use fallback check with suffix and prefix if no POM properties file matches the exact artifact name return strings.HasPrefix(artifactID, fileName) || strings.HasSuffix(fileName, artifactID) } diff --git a/syft/pkg/cataloger/java/archive_parser_test.go b/syft/pkg/cataloger/java/archive_parser_test.go index 968be8578..74a2195e3 100644 --- a/syft/pkg/cataloger/java/archive_parser_test.go +++ b/syft/pkg/cataloger/java/archive_parser_test.go @@ -1156,7 +1156,7 @@ func Test_artifactIDMatchesFilename(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.want, artifactIDMatchesFilename(tt.artifactID, tt.fileName)) + assert.Equal(t, tt.want, artifactIDMatchesFilename(tt.artifactID, tt.fileName, nil)) }) } } From 623532e3ed100a4d84022ea2dc94947855f2f270 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Fri, 2 Aug 2024 13:25:09 -0400 Subject: [PATCH 123/284] chore(deps): update tools to latest versions (#3091) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index c5f5aeb43..ac2f4cc10 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -111,7 +111,7 @@ tools: # used for triggering a release - name: gh version: - want: v2.53.0 + want: v2.54.0 method: github-release with: repo: cli/cli From cc15edca622175e89c1675a659bfa021f152cdd4 Mon Sep 17 00:00:00 2001 From: Harippriya Sivapatham <33924695+harippriyas@users.noreply.github.com> Date: Sun, 4 Aug 2024 01:30:55 +0530 Subject: [PATCH 124/284] fix: use organization for package supplier when reading Java vendor fields (#3093) Signed-off-by: Harippriya Sivapatham --- .../internal/spdxutil/helpers/originator_supplier.go | 4 ++++ .../internal/spdxutil/helpers/originator_supplier_test.go | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/syft/format/internal/spdxutil/helpers/originator_supplier.go b/syft/format/internal/spdxutil/helpers/originator_supplier.go index 61ebf3675..d2af96971 100644 --- a/syft/format/internal/spdxutil/helpers/originator_supplier.go +++ b/syft/format/internal/spdxutil/helpers/originator_supplier.go @@ -56,6 +56,10 @@ func Originator(p pkg.Package) (typ string, author string) { // nolint: funlen if author == "" { author = metadata.Manifest.Main.MustGet("Implementation-Vendor") } + // Vendor is specified, hence set 'Organization' as the PackageSupplier + if author != "" { + typ = orgType + } } case pkg.LinuxKernelModule: diff --git a/syft/format/internal/spdxutil/helpers/originator_supplier_test.go b/syft/format/internal/spdxutil/helpers/originator_supplier_test.go index 5c46685f2..51965925d 100644 --- a/syft/format/internal/spdxutil/helpers/originator_supplier_test.go +++ b/syft/format/internal/spdxutil/helpers/originator_supplier_test.go @@ -138,8 +138,8 @@ func Test_OriginatorSupplier(t *testing.T) { }, }, }, - originator: "Person: auth-spec", - supplier: "Person: auth-spec", + originator: "Organization: auth-spec", + supplier: "Organization: auth-spec", }, { name: "from java -- fallback to impl vendor in main manifest section", @@ -155,8 +155,8 @@ func Test_OriginatorSupplier(t *testing.T) { }, }, }, - originator: "Person: auth-impl", - supplier: "Person: auth-impl", + originator: "Organization: auth-impl", + supplier: "Organization: auth-impl", }, { name: "from java -- non-main manifest sections ignored", From 9d40d1152e91fd520602f159e5d02a8736cb16ac Mon Sep 17 00:00:00 2001 From: Gijs Calis <51088038+GijsCalis@users.noreply.github.com> Date: Mon, 5 Aug 2024 17:30:47 +0200 Subject: [PATCH 125/284] feat: improved java maven property resolution (#2769) Signed-off-by: Gijs Calis <51088038+GijsCalis@users.noreply.github.com> Signed-off-by: Keith Zantow Co-authored-by: Keith Zantow --- cmd/syft/internal/options/catalog.go | 3 + cmd/syft/internal/options/java.go | 38 +- syft/file/license.go | 2 +- .../internal/pkgtest/test_generic_parser.go | 5 + syft/pkg/cataloger/java/archive_parser.go | 209 +++-- .../pkg/cataloger/java/archive_parser_test.go | 211 ++--- syft/pkg/cataloger/java/cataloger.go | 7 +- syft/pkg/cataloger/java/config.go | 20 +- syft/pkg/cataloger/java/maven_repo_utils.go | 136 ---- syft/pkg/cataloger/java/maven_resolver.go | 624 +++++++++++++++ .../pkg/cataloger/java/maven_resolver_test.go | 359 +++++++++ syft/pkg/cataloger/java/maven_utils.go | 74 ++ syft/pkg/cataloger/java/maven_utils_test.go | 103 +++ syft/pkg/cataloger/java/parse_pom_xml.go | 313 +++----- syft/pkg/cataloger/java/parse_pom_xml_test.go | 738 ++++++++++-------- .../.m2/settings.xml | 4 + .../test-fixtures/pom/commons-text.pom.xml | 575 -------------- .../test-fixtures/pom/local/child-1/pom.xml | 42 + .../pom/local/commons-text-1.10.0/pom.xml | 263 +++++++ .../pom/local/contains-child-1/pom.xml | 27 + .../example-java-app-maven}/pom.xml | 0 .../test-fixtures/pom/local/parent-1/pom.xml | 51 ++ .../test-fixtures/pom/local/parent-2/pom.xml | 67 ++ .../org/child-one/1.3.6/child-one-1.3.6.pom | 41 + .../org/child-two/2.1.90/child-two-2.1.90.pom | 53 ++ .../parent-one/3.11.0/parent-one-3.11.0.pom | 51 ++ .../parent-two/13.7.8/parent-two-13.7.8.pom | 67 ++ .../parent/7.11.2}/parent-7.11.2.pom | 0 .../commons-parent/54/commons-parent-54.pom | 132 ++++ .../junit/junit-bom/5.9.0/junit-bom-5.9.0.pom | 151 ++++ .../junit/junit-bom/5.9.1/junit-bom-5.9.1.pom | 152 ++++ .../3.4.6}/opensaml-parent-3.4.6.pom | 0 syft/pkg/cataloger/swipl/package.go | 2 - syft/pkg/license.go | 2 +- 34 files changed, 3006 insertions(+), 1516 deletions(-) delete mode 100644 syft/pkg/cataloger/java/maven_repo_utils.go create mode 100644 syft/pkg/cataloger/java/maven_resolver.go create mode 100644 syft/pkg/cataloger/java/maven_resolver_test.go create mode 100644 syft/pkg/cataloger/java/maven_utils.go create mode 100644 syft/pkg/cataloger/java/maven_utils_test.go create mode 100644 syft/pkg/cataloger/java/test-fixtures/local-repository-settings/.m2/settings.xml delete mode 100644 syft/pkg/cataloger/java/test-fixtures/pom/commons-text.pom.xml create mode 100644 syft/pkg/cataloger/java/test-fixtures/pom/local/child-1/pom.xml create mode 100644 syft/pkg/cataloger/java/test-fixtures/pom/local/commons-text-1.10.0/pom.xml create mode 100644 syft/pkg/cataloger/java/test-fixtures/pom/local/contains-child-1/pom.xml rename syft/pkg/cataloger/java/test-fixtures/pom/{ => local/example-java-app-maven}/pom.xml (100%) create mode 100644 syft/pkg/cataloger/java/test-fixtures/pom/local/parent-1/pom.xml create mode 100644 syft/pkg/cataloger/java/test-fixtures/pom/local/parent-2/pom.xml create mode 100644 syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/my/org/child-one/1.3.6/child-one-1.3.6.pom create mode 100644 syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/my/org/child-two/2.1.90/child-two-2.1.90.pom create mode 100644 syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/my/org/parent-one/3.11.0/parent-one-3.11.0.pom create mode 100644 syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/my/org/parent-two/13.7.8/parent-two-13.7.8.pom rename syft/pkg/cataloger/java/test-fixtures/{maven-xml-responses => pom/maven-repo/net/shibboleth/parent/7.11.2}/parent-7.11.2.pom (100%) create mode 100644 syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/org/apache/commons/commons-parent/54/commons-parent-54.pom create mode 100644 syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/org/junit/junit-bom/5.9.0/junit-bom-5.9.0.pom create mode 100644 syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/org/junit/junit-bom/5.9.1/junit-bom-5.9.1.pom rename syft/pkg/cataloger/java/test-fixtures/{maven-xml-responses => pom/maven-repo/org/opensaml/opensaml-parent/3.4.6}/opensaml-parent-3.4.6.pom (100%) diff --git a/cmd/syft/internal/options/catalog.go b/cmd/syft/internal/options/catalog.go index 290a1d28e..99359abec 100644 --- a/cmd/syft/internal/options/catalog.go +++ b/cmd/syft/internal/options/catalog.go @@ -64,6 +64,7 @@ func DefaultCatalog() Catalog { Package: defaultPackageConfig(), LinuxKernel: defaultLinuxKernelConfig(), Golang: defaultGolangConfig(), + Java: defaultJavaConfig(), File: defaultFileConfig(), Relationships: defaultRelationshipsConfig(), Source: defaultSourceConfig(), @@ -150,6 +151,8 @@ func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config { GuessUnpinnedRequirements: cfg.Python.GuessUnpinnedRequirements, }, JavaArchive: java.DefaultArchiveCatalogerConfig(). + WithUseMavenLocalRepository(cfg.Java.UseMavenLocalRepository). + WithMavenLocalRepositoryDir(cfg.Java.MavenLocalRepositoryDir). WithUseNetwork(cfg.Java.UseNetwork). WithMavenBaseURL(cfg.Java.MavenURL). WithArchiveTraversal(archiveSearch, cfg.Java.MaxParentRecursiveDepth), diff --git a/cmd/syft/internal/options/java.go b/cmd/syft/internal/options/java.go index 79b0fd127..8894c760b 100644 --- a/cmd/syft/internal/options/java.go +++ b/cmd/syft/internal/options/java.go @@ -1,24 +1,46 @@ package options -import "github.com/anchore/clio" +import ( + "github.com/anchore/clio" + "github.com/anchore/syft/syft/pkg/cataloger/java" +) type javaConfig struct { UseNetwork bool `yaml:"use-network" json:"use-network" mapstructure:"use-network"` + UseMavenLocalRepository bool `yaml:"use-maven-local-repository" json:"use-maven-local-repository" mapstructure:"use-maven-local-repository"` + MavenLocalRepositoryDir string `yaml:"maven-local-repository-dir" json:"maven-local-repository-dir" mapstructure:"maven-local-repository-dir"` MavenURL string `yaml:"maven-url" json:"maven-url" mapstructure:"maven-url"` MaxParentRecursiveDepth int `yaml:"max-parent-recursive-depth" json:"max-parent-recursive-depth" mapstructure:"max-parent-recursive-depth"` } +func defaultJavaConfig() javaConfig { + def := java.DefaultArchiveCatalogerConfig() + + return javaConfig{ + UseNetwork: def.UseNetwork, + MaxParentRecursiveDepth: def.MaxParentRecursiveDepth, + UseMavenLocalRepository: def.UseMavenLocalRepository, + MavenLocalRepositoryDir: def.MavenLocalRepositoryDir, + MavenURL: def.MavenBaseURL, + } +} + var _ interface { clio.FieldDescriber } = (*javaConfig)(nil) func (o *javaConfig) DescribeFields(descriptions clio.FieldDescriptionSet) { - descriptions.Add(&o.UseNetwork, `enables Syft to use the network to fill in more detailed information about artifacts -currently this enables searching maven-url for license data -when running across pom.xml files that could have more information, syft will -explicitly search maven for license information by querying the online pom when this is true -this option is helpful for when the parent pom has more data, -that is not accessible from within the final built artifact`) + descriptions.Add(&o.UseNetwork, `enables Syft to use the network to fetch version and license information for packages when +a parent or imported pom file is not found in the local maven repository. +the pom files are downloaded from the remote Maven repository at 'maven-url'`) descriptions.Add(&o.MavenURL, `maven repository to use, defaults to Maven central`) - descriptions.Add(&o.MaxParentRecursiveDepth, `depth to recursively resolve parent POMs`) + descriptions.Add(&o.MaxParentRecursiveDepth, `depth to recursively resolve parent POMs, no limit if <= 0`) + descriptions.Add(&o.UseMavenLocalRepository, `use the local Maven repository to retrieve pom files. When Maven is installed and was previously used +for building the software that is being scanned, then most pom files will be available in this +repository on the local file system. this greatly speeds up scans. when all pom files are available +in the local repository, then 'use-network' is not needed. +TIP: If you want to download all required pom files to the local repository without running a full +build, run 'mvn help:effective-pom' before performing the scan with syft.`) + descriptions.Add(&o.MavenLocalRepositoryDir, `override the default location of the local Maven repository. +the default is the subdirectory '.m2/repository' in your home directory`) } diff --git a/syft/file/license.go b/syft/file/license.go index 12d487d54..08d77e052 100644 --- a/syft/file/license.go +++ b/syft/file/license.go @@ -21,7 +21,7 @@ type LicenseEvidence struct { func NewLicense(value string) License { spdxExpression, err := license.ParseExpression(value) if err != nil { - log.Trace("unable to parse license expression: %s, %w", value, err) + log.WithFields("error", err, "value", value).Trace("unable to parse license expression") } return License{ diff --git a/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go b/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go index a3cf11dec..2dcbb7f8b 100644 --- a/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go +++ b/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go @@ -310,6 +310,11 @@ func TestFileParser(t *testing.T, fixturePath string, parser generic.Parser, exp NewCatalogTester().FromFile(t, fixturePath).Expects(expectedPkgs, expectedRelationships).TestParser(t, parser) } +func TestCataloger(t *testing.T, fixtureDir string, cataloger pkg.Cataloger, expectedPkgs []pkg.Package, expectedRelationships []artifact.Relationship) { + t.Helper() + NewCatalogTester().FromDirectory(t, fixtureDir).Expects(expectedPkgs, expectedRelationships).TestCataloger(t, cataloger) +} + func TestFileParserWithEnv(t *testing.T, fixturePath string, parser generic.Parser, env *generic.Environment, expectedPkgs []pkg.Package, expectedRelationships []artifact.Relationship) { t.Helper() diff --git a/syft/pkg/cataloger/java/archive_parser.go b/syft/pkg/cataloger/java/archive_parser.go index 789b3b9d3..663563c61 100644 --- a/syft/pkg/cataloger/java/archive_parser.go +++ b/syft/pkg/cataloger/java/archive_parser.go @@ -9,8 +9,10 @@ import ( "slices" "strings" + "github.com/vifraa/gopom" "golang.org/x/exp/maps" + "github.com/anchore/syft/internal" intFile "github.com/anchore/syft/internal/file" "github.com/anchore/syft/internal/licenses" "github.com/anchore/syft/internal/log" @@ -52,6 +54,7 @@ type archiveParser struct { fileInfo archiveFilename detectNested bool cfg ArchiveCatalogerConfig + maven *mavenResolver } type genericArchiveParserAdapter struct { @@ -106,6 +109,7 @@ func newJavaArchiveParser(reader file.LocationReadCloser, detectNested bool, cfg fileInfo: newJavaArchiveFilename(currentFilepath), detectNested: detectNested, cfg: cfg, + maven: newMavenResolver(nil, cfg), }, cleanupFn, nil } @@ -197,7 +201,7 @@ func (j *archiveParser) discoverMainPackage(ctx context.Context) (*pkg.Package, return nil, err } - licenses, name, version, err := j.parseLicenses(ctx, manifest) + name, version, licenses, err := j.discoverNameVersionLicense(ctx, manifest) if err != nil { return nil, err } @@ -220,7 +224,7 @@ func (j *archiveParser) discoverMainPackage(ctx context.Context) (*pkg.Package, }, nil } -func (j *archiveParser) parseLicenses(ctx context.Context, manifest *pkg.JavaManifest) ([]pkg.License, string, string, error) { +func (j *archiveParser) discoverNameVersionLicense(ctx context.Context, manifest *pkg.JavaManifest) (string, string, []pkg.License, error) { // we use j.location because we want to associate the license declaration with where we discovered the contents in the manifest // TODO: when we support locations of paths within archives we should start passing the specific manifest location object instead of the top jar licenses := pkg.NewLicensesFromLocation(j.location, selectLicenses(manifest)...) @@ -231,24 +235,18 @@ func (j *archiveParser) parseLicenses(ctx context.Context, manifest *pkg.JavaMan 3. manifest 4. filename */ - name, version, pomLicenses := j.guessMainPackageNameAndVersionFromPomInfo(ctx) - if name == "" { - name = selectName(manifest, j.fileInfo) + groupID, artifactID, version, parsedPom := j.discoverMainPackageFromPomInfo(ctx) + if artifactID == "" { + artifactID = selectName(manifest, j.fileInfo) } if version == "" { version = selectVersion(manifest, j.fileInfo) } - if len(licenses) == 0 { - // Today we don't have a way to distinguish between licenses from the manifest and licenses from the pom.xml - // until the file.Location object can support sub-paths (i.e. paths within archives, recursively; issue https://github.com/anchore/syft/issues/2211). - // Until then it's less confusing to use the licenses from the pom.xml only if the manifest did not list any. - licenses = append(licenses, pomLicenses...) - } if len(licenses) == 0 { fileLicenses, err := j.getLicenseFromFileInArchive() if err != nil { - return nil, "", "", err + return "", "", nil, err } if fileLicenses != nil { licenses = append(licenses, fileLicenses...) @@ -256,50 +254,73 @@ func (j *archiveParser) parseLicenses(ctx context.Context, manifest *pkg.JavaMan } // If we didn't find any licenses in the archive so far, we'll try again in Maven Central using groupIDFromJavaMetadata - if len(licenses) == 0 && j.cfg.UseNetwork { - licenses = findLicenseFromJavaMetadata(ctx, name, manifest, version, j, licenses) + if len(licenses) == 0 { + // Today we don't have a way to distinguish between licenses from the manifest and licenses from the pom.xml + // until the file.Location object can support sub-paths (i.e. paths within archives, recursively; issue https://github.com/anchore/syft/issues/2211). + // Until then it's less confusing to use the licenses from the pom.xml only if the manifest did not list any. + licenses = j.findLicenseFromJavaMetadata(ctx, groupID, artifactID, version, parsedPom, manifest) } - return licenses, name, version, nil + return artifactID, version, licenses, nil } -func findLicenseFromJavaMetadata(ctx context.Context, name string, manifest *pkg.JavaManifest, version string, j *archiveParser, licenses []pkg.License) []pkg.License { - var groupID = name - if gID := groupIDFromJavaMetadata(name, pkg.JavaArchive{Manifest: manifest}); gID != "" { - groupID = gID +// findLicenseFromJavaMetadata attempts to find license information from all available maven metadata properties and pom info +func (j *archiveParser) findLicenseFromJavaMetadata(ctx context.Context, groupID, artifactID, version string, parsedPom *parsedPomProject, manifest *pkg.JavaManifest) []pkg.License { + if groupID == "" { + if gID := groupIDFromJavaMetadata(artifactID, pkg.JavaArchive{Manifest: manifest}); gID != "" { + groupID = gID + } + } + + var err error + var pomLicenses []gopom.License + if parsedPom != nil { + pomLicenses, err = j.maven.resolveLicenses(ctx, parsedPom.project) + if err != nil { + log.WithFields("error", err, "mavenID", j.maven.resolveMavenID(ctx, parsedPom.project)).Debug("error attempting to resolve pom licenses") + } + } + + if err == nil && len(pomLicenses) == 0 { + pomLicenses, err = j.maven.findLicenses(ctx, groupID, artifactID, version) + if err != nil { + log.WithFields("error", err, "mavenID", mavenID{groupID, artifactID, version}).Debug("error attempting to find licenses") + } } - pomLicenses := recursivelyFindLicensesFromParentPom(ctx, groupID, name, version, j.cfg) if len(pomLicenses) == 0 { // Try removing the last part of the groupId, as sometimes it duplicates the artifactId packages := strings.Split(groupID, ".") groupID = strings.Join(packages[:len(packages)-1], ".") - pomLicenses = recursivelyFindLicensesFromParentPom(ctx, groupID, name, version, j.cfg) + pomLicenses, err = j.maven.findLicenses(ctx, groupID, artifactID, version) + if err != nil { + log.WithFields("error", err, "mavenID", mavenID{groupID, artifactID, version}).Debug("error attempting to find sub-group licenses") + } } - if len(pomLicenses) > 0 { - pkgLicenses := pkg.NewLicensesFromLocation(j.location, pomLicenses...) - if pkgLicenses != nil { - licenses = append(licenses, pkgLicenses...) - } + return toPkgLicenses(&j.location, pomLicenses) +} + +func toPkgLicenses(location *file.Location, licenses []gopom.License) []pkg.License { + var out []pkg.License + for _, license := range licenses { + out = append(out, pkg.NewLicenseFromFields(deref(license.Name), deref(license.URL), location)) } - return licenses + return out } type parsedPomProject struct { - *pkg.JavaPomProject - Licenses []pkg.License + path string + project *gopom.Project } -func (j *archiveParser) guessMainPackageNameAndVersionFromPomInfo(ctx context.Context) (name, version string, licenses []pkg.License) { - pomPropertyMatches := j.fileManifest.GlobMatch(false, pomPropertiesGlob) - pomMatches := j.fileManifest.GlobMatch(false, pomXMLGlob) - var pomPropertiesObject pkg.JavaPomProperties - var pomProjectObject *parsedPomProject +// discoverMainPackageFromPomInfo attempts to resolve maven groupId, artifactId, version and other info from found pom information +func (j *archiveParser) discoverMainPackageFromPomInfo(ctx context.Context) (group, name, version string, parsedPom *parsedPomProject) { + var pomProperties pkg.JavaPomProperties // Find the pom.properties/pom.xml if the names seem like a plausible match - properties, _ := pomPropertiesByParentPath(j.archivePath, j.location, pomPropertyMatches) - projects, _ := pomProjectByParentPath(j.archivePath, j.location, pomMatches) + properties, _ := pomPropertiesByParentPath(j.archivePath, j.location, j.fileManifest.GlobMatch(false, pomPropertiesGlob)) + projects, _ := pomProjectByParentPath(j.archivePath, j.location, j.fileManifest.GlobMatch(false, pomXMLGlob)) // map of all the artifacts in the pom properties, in order to chek exact match with the filename artifactsMap := make(map[string]bool) @@ -312,41 +333,32 @@ func (j *archiveParser) guessMainPackageNameAndVersionFromPomInfo(ctx context.Co for _, parentPath := range parentPaths { propertiesObj := properties[parentPath] if artifactIDMatchesFilename(propertiesObj.ArtifactID, j.fileInfo.name, artifactsMap) { - pomPropertiesObject = propertiesObj + pomProperties = propertiesObj if proj, exists := projects[parentPath]; exists { - pomProjectObject = proj + parsedPom = proj break } } } - name = pomPropertiesObject.ArtifactID - if name == "" && pomProjectObject != nil { - name = pomProjectObject.ArtifactID - } - version = pomPropertiesObject.Version - if version == "" && pomProjectObject != nil { - version = pomProjectObject.Version - } - if j.cfg.UseNetwork { - if pomProjectObject == nil { - // If we have no pom.xml, check maven central using pom.properties - parentLicenses := recursivelyFindLicensesFromParentPom(ctx, pomPropertiesObject.GroupID, pomPropertiesObject.ArtifactID, pomPropertiesObject.Version, j.cfg) - if len(parentLicenses) > 0 { - for _, licenseName := range parentLicenses { - licenses = append(licenses, pkg.NewLicenseFromFields(licenseName, "", nil)) - } - } - } else { - findPomLicenses(ctx, pomProjectObject, j.cfg) - } - } + group = pomProperties.GroupID + name = pomProperties.ArtifactID + version = pomProperties.Version - if pomProjectObject != nil { - licenses = pomProjectObject.Licenses + if parsedPom != nil && parsedPom.project != nil { + id := j.maven.resolveMavenID(ctx, parsedPom.project) + if group == "" { + group = id.GroupID + } + if name == "" { + name = id.ArtifactID + } + if version == "" { + version = id.Version + } } - return name, version, licenses + return group, name, version, parsedPom } func artifactIDMatchesFilename(artifactID, fileName string, artifactsMap map[string]bool) bool { @@ -361,24 +373,6 @@ func artifactIDMatchesFilename(artifactID, fileName string, artifactsMap map[str return strings.HasPrefix(artifactID, fileName) || strings.HasSuffix(fileName, artifactID) } -func findPomLicenses(ctx context.Context, pomProjectObject *parsedPomProject, cfg ArchiveCatalogerConfig) { - // If we don't have any licenses until now, and if we have a parent Pom, then we'll check the parent pom in maven central for licenses. - if pomProjectObject != nil && pomProjectObject.Parent != nil && len(pomProjectObject.Licenses) == 0 { - parentLicenses := recursivelyFindLicensesFromParentPom( - ctx, - pomProjectObject.Parent.GroupID, - pomProjectObject.Parent.ArtifactID, - pomProjectObject.Parent.Version, - cfg) - - if len(parentLicenses) > 0 { - for _, licenseName := range parentLicenses { - pomProjectObject.Licenses = append(pomProjectObject.Licenses, pkg.NewLicenseFromFields(licenseName, "", nil)) - } - } - } -} - // discoverPkgsFromAllMavenFiles parses Maven POM properties/xml for a given // parent package, returning all listed Java packages found for each pom // properties discovered and potentially updating the given parentPkg with new @@ -403,12 +397,12 @@ func (j *archiveParser) discoverPkgsFromAllMavenFiles(ctx context.Context, paren } for parentPath, propertiesObj := range properties { - var pomProject *parsedPomProject + var parsedPom *parsedPomProject if proj, exists := projects[parentPath]; exists { - pomProject = proj + parsedPom = proj } - pkgFromPom := newPackageFromMavenData(ctx, propertiesObj, pomProject, parentPkg, j.location, j.cfg) + pkgFromPom := newPackageFromMavenData(ctx, j.maven, propertiesObj, parsedPom, parentPkg, j.location) if pkgFromPom != nil { pkgs = append(pkgs, *pkgFromPom) } @@ -422,7 +416,7 @@ func getDigestsFromArchive(archivePath string) ([]file.Digest, error) { if err != nil { return nil, fmt.Errorf("unable to open archive path (%s): %w", archivePath, err) } - defer archiveCloser.Close() + defer internal.CloseAndLogError(archiveCloser, archivePath) // grab and assign digest for the entire archive digests, err := intFile.NewDigestsFromFile(archiveCloser, javaArchiveHashes) @@ -576,30 +570,26 @@ func pomProjectByParentPath(archivePath string, location file.Location, extractP projectByParentPath := make(map[string]*parsedPomProject) for filePath, fileContents := range contentsOfMavenProjectFiles { // TODO: when we support locations of paths within archives we should start passing the specific pom.xml location object instead of the top jar - pomProject, err := parsePomXMLProject(filePath, strings.NewReader(fileContents), location) + pom, err := decodePomXML(strings.NewReader(fileContents)) if err != nil { log.WithFields("contents-path", filePath, "location", location.Path()).Warnf("failed to parse pom.xml: %+v", err) continue } - - if pomProject == nil { + if pom == nil { continue } - // If we don't have a version, then maybe the parent pom has it... - if (pomProject.Parent == nil && pomProject.Version == "") || pomProject.ArtifactID == "" { - // TODO: if there is no parentPkg (no java manifest) one of these poms could be the parent. We should discover the right parent and attach the correct info accordingly to each discovered package - continue + projectByParentPath[path.Dir(filePath)] = &parsedPomProject{ + path: filePath, + project: pom, } - - projectByParentPath[path.Dir(filePath)] = pomProject } return projectByParentPath, nil } // newPackageFromMavenData processes a single Maven POM properties for a given parent package, returning all listed Java packages found and // associating each discovered package to the given parent package. Note the pom.xml is optional, the pom.properties is not. -func newPackageFromMavenData(ctx context.Context, pomProperties pkg.JavaPomProperties, parsedPomProject *parsedPomProject, parentPkg *pkg.Package, location file.Location, cfg ArchiveCatalogerConfig) *pkg.Package { +func newPackageFromMavenData(ctx context.Context, r *mavenResolver, pomProperties pkg.JavaPomProperties, parsedPom *parsedPomProject, parentPkg *pkg.Package, location file.Location) *pkg.Package { // keep the artifact name within the virtual path if this package does not match the parent package vPathSuffix := "" groupID := "" @@ -622,25 +612,24 @@ func newPackageFromMavenData(ctx context.Context, pomProperties pkg.JavaPomPrope virtualPath := location.Path() + vPathSuffix var pkgPomProject *pkg.JavaPomProject - licenses := make([]pkg.License, 0) - if cfg.UseNetwork { - if parsedPomProject == nil { - // If we have no pom.xml, check maven central using pom.properties - parentLicenses := recursivelyFindLicensesFromParentPom(ctx, pomProperties.GroupID, pomProperties.ArtifactID, pomProperties.Version, cfg) - if len(parentLicenses) > 0 { - for _, licenseName := range parentLicenses { - licenses = append(licenses, pkg.NewLicenseFromFields(licenseName, "", nil)) - } - } - } else { - findPomLicenses(ctx, parsedPomProject, cfg) - } + var err error + var pomLicenses []gopom.License + if parsedPom == nil { + // If we have no pom.xml, check maven central using pom.properties + pomLicenses, err = r.findLicenses(ctx, pomProperties.GroupID, pomProperties.ArtifactID, pomProperties.Version) + } else { + pkgPomProject = newPomProject(ctx, r, parsedPom.path, parsedPom.project) + pomLicenses, err = r.resolveLicenses(ctx, parsedPom.project) + } + + if err != nil { + log.WithFields("error", err, "mavenID", mavenID{pomProperties.GroupID, pomProperties.ArtifactID, pomProperties.Version}).Debug("error attempting to resolve licenses") } - if parsedPomProject != nil { - pkgPomProject = parsedPomProject.JavaPomProject - licenses = append(licenses, parsedPomProject.Licenses...) + licenses := make([]pkg.License, 0) + for _, license := range pomLicenses { + licenses = append(licenses, pkg.NewLicenseFromFields(deref(license.Name), deref(license.URL), &location)) } p := pkg.Package{ diff --git a/syft/pkg/cataloger/java/archive_parser_test.go b/syft/pkg/cataloger/java/archive_parser_test.go index 74a2195e3..ccddc8c75 100644 --- a/syft/pkg/cataloger/java/archive_parser_test.go +++ b/syft/pkg/cataloger/java/archive_parser_test.go @@ -5,8 +5,6 @@ import ( "context" "fmt" "io" - "net/http" - "net/http/httptest" "os" "os/exec" "path/filepath" @@ -20,6 +18,7 @@ import ( "github.com/scylladb/go-set/strset" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/vifraa/gopom" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" @@ -28,61 +27,14 @@ import ( "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" ) -func generateJavaBuildFixture(t *testing.T, fixturePath string) { - if _, err := os.Stat(fixturePath); !os.IsNotExist(err) { - // fixture already exists... - return - } - - makeTask := strings.TrimPrefix(fixturePath, "test-fixtures/java-builds/") - t.Logf(color.Bold.Sprintf("Generating Fixture from 'make %s'", makeTask)) - - cwd, err := os.Getwd() - if err != nil { - t.Errorf("unable to get cwd: %+v", err) - } - - cmd := exec.Command("make", makeTask) - cmd.Dir = filepath.Join(cwd, "test-fixtures/java-builds/") - - run(t, cmd) -} - -func generateMockMavenHandler(responseFixture string) func(w http.ResponseWriter, r *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - // Set the Content-Type header to indicate that the response is XML - w.Header().Set("Content-Type", "application/xml") - // Copy the file's content to the response writer - file, err := os.Open(responseFixture) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - defer file.Close() - _, err = io.Copy(w, file) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - } -} - -type handlerPath struct { - path string - handler func(w http.ResponseWriter, r *http.Request) -} - func TestSearchMavenForLicenses(t *testing.T) { - mux, url, teardown := setup() - defer teardown() + url := mockMavenRepo(t) + tests := []struct { name string fixture string detectNested bool config ArchiveCatalogerConfig - requestPath string - requestHandlers []handlerPath expectedLicenses []pkg.License }{ { @@ -91,23 +43,16 @@ func TestSearchMavenForLicenses(t *testing.T) { detectNested: false, config: ArchiveCatalogerConfig{ UseNetwork: true, + UseMavenLocalRepository: false, MavenBaseURL: url, - MaxParentRecursiveDepth: 2, - }, - requestHandlers: []handlerPath{ - { - path: "/org/opensaml/opensaml-parent/3.4.6/opensaml-parent-3.4.6.pom", - handler: generateMockMavenHandler("test-fixtures/maven-xml-responses/opensaml-parent-3.4.6.pom"), - }, - { - path: "/net/shibboleth/parent/7.11.2/parent-7.11.2.pom", - handler: generateMockMavenHandler("test-fixtures/maven-xml-responses/parent-7.11.2.pom"), - }, }, expectedLicenses: []pkg.License{ { - Type: license.Declared, - Value: `The Apache Software License, Version 2.0`, + Type: license.Declared, + Value: `The Apache Software License, Version 2.0`, + URLs: []string{ + "http://www.apache.org/licenses/LICENSE-2.0.txt", + }, SPDXExpression: ``, }, }, @@ -116,11 +61,6 @@ func TestSearchMavenForLicenses(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - // configure maven central requests - for _, hdlr := range tc.requestHandlers { - mux.HandleFunc(hdlr.path, hdlr.handler) - } - // setup metadata fixture; note: // this fixture has a pomProjectObject and has a parent object // it has no licenses on either which is the condition for testing @@ -138,34 +78,9 @@ func TestSearchMavenForLicenses(t *testing.T) { defer cleanupFn() // assert licenses are discovered from upstream - _, _, licenses := ap.guessMainPackageNameAndVersionFromPomInfo(context.Background()) - assert.Equal(t, tc.expectedLicenses, licenses) - }) - } -} - -func TestFormatMavenURL(t *testing.T) { - tests := []struct { - name string - groupID string - artifactID string - version string - expected string - }{ - { - name: "formatMavenURL correctly assembles the pom URL", - groupID: "org.springframework.boot", - artifactID: "spring-boot-starter-test", - version: "3.1.5", - expected: "https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-starter-test/3.1.5/spring-boot-starter-test-3.1.5.pom", - }, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - requestURL, err := formatMavenPomURL(tc.groupID, tc.artifactID, tc.version, mavenBaseURL) - assert.NoError(t, err, "expected no err; got %w", err) - assert.Equal(t, tc.expected, requestURL) + _, _, _, parsedPom := ap.discoverMainPackageFromPomInfo(context.Background()) + licenses, _ := ap.maven.resolveLicenses(context.Background(), parsedPom.project) + assert.Equal(t, tc.expectedLicenses, toPkgLicenses(nil, licenses)) }) } } @@ -424,10 +339,14 @@ func TestParseJar(t *testing.T) { test.expected[k] = p } + cfg := ArchiveCatalogerConfig{ + UseNetwork: false, + UseMavenLocalRepository: false, + } parser, cleanupFn, err := newJavaArchiveParser(file.LocationReadCloser{ Location: file.NewLocation(fixture.Name()), ReadCloser: fixture, - }, false, ArchiveCatalogerConfig{UseNetwork: false}) + }, false, cfg) defer cleanupFn() require.NoError(t, err) @@ -843,26 +762,23 @@ func Test_newPackageFromMavenData(t *testing.T) { Version: "1.0", }, project: &parsedPomProject{ - JavaPomProject: &pkg.JavaPomProject{ - Parent: &pkg.JavaPomParent{ - GroupID: "some-parent-group-id", - ArtifactID: "some-parent-artifact-id", - Version: "1.0-parent", + project: &gopom.Project{ + Parent: &gopom.Parent{ + GroupID: ptr("some-parent-group-id"), + ArtifactID: ptr("some-parent-artifact-id"), + Version: ptr("1.0-parent"), }, - Name: "some-name", - GroupID: "some-group-id", - ArtifactID: "some-artifact-id", - Version: "1.0", - Description: "desc", - URL: "aweso.me", - }, - Licenses: []pkg.License{ - { - Value: "MIT", - SPDXExpression: "MIT", - Type: license.Declared, - URLs: []string{"https://opensource.org/licenses/MIT"}, - Locations: file.NewLocationSet(file.NewLocation("some-license-path")), + Name: ptr("some-name"), + GroupID: ptr("some-group-id"), + ArtifactID: ptr("some-artifact-id"), + Version: ptr("1.0"), + Description: ptr("desc"), + URL: ptr("aweso.me"), + Licenses: &[]gopom.License{ + { + Name: ptr("MIT"), + URL: ptr("https://opensource.org/licenses/MIT"), + }, }, }, }, @@ -898,7 +814,7 @@ func Test_newPackageFromMavenData(t *testing.T) { SPDXExpression: "MIT", Type: license.Declared, URLs: []string{"https://opensource.org/licenses/MIT"}, - Locations: file.NewLocationSet(file.NewLocation("some-license-path")), + Locations: file.NewLocationSet(file.NewLocation("given/virtual/path")), }, ), Metadata: pkg.JavaArchive{ @@ -1122,7 +1038,8 @@ func Test_newPackageFromMavenData(t *testing.T) { } test.expectedParent.Locations = locations - actualPackage := newPackageFromMavenData(context.Background(), test.props, test.project, test.parent, file.NewLocation(virtualPath), DefaultArchiveCatalogerConfig()) + r := newMavenResolver(nil, DefaultArchiveCatalogerConfig()) + actualPackage := newPackageFromMavenData(context.Background(), r, test.props, test.project, test.parent, file.NewLocation(virtualPath)) if test.expectedPackage == nil { require.Nil(t, actualPackage) } else { @@ -1337,6 +1254,8 @@ func Test_parseJavaArchive_regressions(t *testing.T) { PomProject: &pkg.JavaPomProject{ Path: "META-INF/maven/org.apache.directory.api/api-asn1-api/pom.xml", ArtifactID: "api-asn1-api", + GroupID: "org.apache.directory.api", + Version: "2.0.0", Name: "Apache Directory API ASN.1 API", Description: "ASN.1 API", Parent: &pkg.JavaPomParent{ @@ -1388,14 +1307,12 @@ func Test_parseJavaArchive_regressions(t *testing.T) { func Test_deterministicMatchingPomProperties(t *testing.T) { tests := []struct { - fixture string - expectedName string - expectedVersion string + fixture string + expected mavenID }{ { - fixture: "multiple-matching-2.11.5", - expectedName: "multiple-matching-1", - expectedVersion: "2.11.5", + fixture: "multiple-matching-2.11.5", + expected: mavenID{"org.multiple", "multiple-matching-1", "2.11.5"}, }, } @@ -1415,9 +1332,8 @@ func Test_deterministicMatchingPomProperties(t *testing.T) { defer cleanupFn() require.NoError(t, err) - name, version, _ := parser.guessMainPackageNameAndVersionFromPomInfo(context.TODO()) - require.Equal(t, test.expectedName, name) - require.Equal(t, test.expectedVersion, version) + groupID, artifactID, version, _ := parser.discoverMainPackageFromPomInfo(context.TODO()) + require.Equal(t, test.expected, mavenID{groupID, artifactID, version}) }() } }) @@ -1436,6 +1352,26 @@ func assignParent(parent *pkg.Package, childPackages ...pkg.Package) { } } +func generateJavaBuildFixture(t *testing.T, fixturePath string) { + if _, err := os.Stat(fixturePath); !os.IsNotExist(err) { + // fixture already exists... + return + } + + makeTask := strings.TrimPrefix(fixturePath, "test-fixtures/java-builds/") + t.Logf(color.Bold.Sprintf("Generating Fixture from 'make %s'", makeTask)) + + cwd, err := os.Getwd() + if err != nil { + t.Errorf("unable to get cwd: %+v", err) + } + + cmd := exec.Command("make", makeTask) + cmd.Dir = filepath.Join(cwd, "test-fixtures/java-builds/") + + run(t, cmd) +} + func generateJavaMetadataJarFixture(t *testing.T, fixtureName string) string { fixturePath := filepath.Join("test-fixtures/jar-metadata/cache/", fixtureName+".jar") if _, err := os.Stat(fixturePath); !os.IsNotExist(err) { @@ -1504,20 +1440,7 @@ func run(t testing.TB, cmd *exec.Cmd) { } } -// setup sets up a test HTTP server for mocking requests to maven central. -// The returned url is injected into the Config so the client uses the test server. -// Tests should register handlers on mux to simulate the expected request/response structure -func setup() (mux *http.ServeMux, serverURL string, teardown func()) { - // mux is the HTTP request multiplexer used with the test server. - mux = http.NewServeMux() - - // We want to ensure that tests catch mistakes where the endpoint URL is - // specified as absolute rather than relative. It only makes a difference - // when there's a non-empty base URL path. So, use that. See issue #752. - apiHandler := http.NewServeMux() - apiHandler.Handle("/", mux) - // server is a test HTTP server used to provide mock API responses. - server := httptest.NewServer(apiHandler) - - return mux, server.URL, server.Close +// ptr returns a pointer to the given value +func ptr[T any](value T) *T { + return &value } diff --git a/syft/pkg/cataloger/java/cataloger.go b/syft/pkg/cataloger/java/cataloger.go index 9552b142d..11e48b7f5 100644 --- a/syft/pkg/cataloger/java/cataloger.go +++ b/syft/pkg/cataloger/java/cataloger.go @@ -32,10 +32,9 @@ func NewArchiveCataloger(cfg ArchiveCatalogerConfig) pkg.Cataloger { // NewPomCataloger returns a cataloger capable of parsing dependencies from a pom.xml file. // Pom files list dependencies that maybe not be locally installed yet. func NewPomCataloger(cfg ArchiveCatalogerConfig) pkg.Cataloger { - gap := newGenericArchiveParserAdapter(cfg) - - return generic.NewCataloger("java-pom-cataloger"). - WithParserByGlobs(gap.parserPomXML, "**/pom.xml") + return pomXMLCataloger{ + cfg: cfg, + } } // NewGradleLockfileCataloger returns a cataloger capable of parsing dependencies from a gradle.lockfile file. diff --git a/syft/pkg/cataloger/java/config.go b/syft/pkg/cataloger/java/config.go index 14c31d334..29096d59b 100644 --- a/syft/pkg/cataloger/java/config.go +++ b/syft/pkg/cataloger/java/config.go @@ -7,6 +7,8 @@ const mavenBaseURL = "https://repo1.maven.org/maven2" type ArchiveCatalogerConfig struct { cataloging.ArchiveSearchConfig `yaml:",inline" json:"" mapstructure:",squash"` UseNetwork bool `yaml:"use-network" json:"use-network" mapstructure:"use-network"` + UseMavenLocalRepository bool `yaml:"use-maven-localrepository" json:"use-maven-localrepository" mapstructure:"use-maven-localrepository"` + MavenLocalRepositoryDir string `yaml:"maven-localrepository-dir" json:"maven-localrepository-dir" mapstructure:"maven-localrepository-dir"` MavenBaseURL string `yaml:"maven-base-url" json:"maven-base-url" mapstructure:"maven-base-url"` MaxParentRecursiveDepth int `yaml:"max-parent-recursive-depth" json:"max-parent-recursive-depth" mapstructure:"max-parent-recursive-depth"` } @@ -15,8 +17,10 @@ func DefaultArchiveCatalogerConfig() ArchiveCatalogerConfig { return ArchiveCatalogerConfig{ ArchiveSearchConfig: cataloging.DefaultArchiveSearchConfig(), UseNetwork: false, + UseMavenLocalRepository: false, + MavenLocalRepositoryDir: defaultMavenLocalRepoDir(), MavenBaseURL: mavenBaseURL, - MaxParentRecursiveDepth: 5, + MaxParentRecursiveDepth: 0, // unlimited } } @@ -25,6 +29,16 @@ func (j ArchiveCatalogerConfig) WithUseNetwork(input bool) ArchiveCatalogerConfi return j } +func (j ArchiveCatalogerConfig) WithUseMavenLocalRepository(input bool) ArchiveCatalogerConfig { + j.UseMavenLocalRepository = input + return j +} + +func (j ArchiveCatalogerConfig) WithMavenLocalRepositoryDir(input string) ArchiveCatalogerConfig { + j.MavenLocalRepositoryDir = input + return j +} + func (j ArchiveCatalogerConfig) WithMavenBaseURL(input string) ArchiveCatalogerConfig { if input != "" { j.MavenBaseURL = input @@ -33,9 +47,7 @@ func (j ArchiveCatalogerConfig) WithMavenBaseURL(input string) ArchiveCatalogerC } func (j ArchiveCatalogerConfig) WithArchiveTraversal(search cataloging.ArchiveSearchConfig, maxDepth int) ArchiveCatalogerConfig { - if maxDepth > 0 { - j.MaxParentRecursiveDepth = maxDepth - } + j.MaxParentRecursiveDepth = maxDepth j.ArchiveSearchConfig = search return j } diff --git a/syft/pkg/cataloger/java/maven_repo_utils.go b/syft/pkg/cataloger/java/maven_repo_utils.go deleted file mode 100644 index e84db154a..000000000 --- a/syft/pkg/cataloger/java/maven_repo_utils.go +++ /dev/null @@ -1,136 +0,0 @@ -package java - -import ( - "context" - "fmt" - "io" - "net/http" - "net/url" - "strings" - "time" - - "github.com/vifraa/gopom" - - "github.com/anchore/syft/internal/log" -) - -func formatMavenPomURL(groupID, artifactID, version, mavenBaseURL string) (requestURL string, err error) { - // groupID needs to go from maven.org -> maven/org - urlPath := strings.Split(groupID, ".") - artifactPom := fmt.Sprintf("%s-%s.pom", artifactID, version) - urlPath = append(urlPath, artifactID, version, artifactPom) - - // ex:"https://repo1.maven.org/maven2/groupID/artifactID/artifactPom - requestURL, err = url.JoinPath(mavenBaseURL, urlPath...) - if err != nil { - return requestURL, fmt.Errorf("could not construct maven url: %w", err) - } - return requestURL, err -} - -// An artifact can have its version defined in a parent's DependencyManagement section -func recursivelyFindVersionFromParentPom(ctx context.Context, groupID, artifactID, parentGroupID, parentArtifactID, parentVersion string, cfg ArchiveCatalogerConfig) string { - // As there can be nested parent poms, we'll recursively check for the version until we reach the max depth - for i := 0; i < cfg.MaxParentRecursiveDepth; i++ { - parentPom, err := getPomFromMavenRepo(ctx, parentGroupID, parentArtifactID, parentVersion, cfg.MavenBaseURL) - if err != nil { - // We don't want to abort here as the parent pom might not exist in Maven Central, we'll just log the error - log.Tracef("unable to get parent pom from Maven central: %v", err) - break - } - if parentPom != nil && parentPom.DependencyManagement != nil { - for _, dependency := range *parentPom.DependencyManagement.Dependencies { - if groupID == *dependency.GroupID && artifactID == *dependency.ArtifactID && dependency.Version != nil { - return *dependency.Version - } - } - } - if parentPom == nil || parentPom.Parent == nil { - break - } - parentGroupID = *parentPom.Parent.GroupID - parentArtifactID = *parentPom.Parent.ArtifactID - parentVersion = *parentPom.Parent.Version - } - return "" -} - -func recursivelyFindLicensesFromParentPom(ctx context.Context, groupID, artifactID, version string, cfg ArchiveCatalogerConfig) []string { - var licenses []string - // As there can be nested parent poms, we'll recursively check for licenses until we reach the max depth - for i := 0; i < cfg.MaxParentRecursiveDepth; i++ { - parentPom, err := getPomFromMavenRepo(ctx, groupID, artifactID, version, cfg.MavenBaseURL) - if err != nil { - // We don't want to abort here as the parent pom might not exist in Maven Central, we'll just log the error - log.Tracef("unable to get parent pom from Maven central: %v", err) - return []string{} - } - parentLicenses := parseLicensesFromPom(parentPom) - if len(parentLicenses) > 0 || parentPom == nil || parentPom.Parent == nil { - licenses = parentLicenses - break - } - - groupID = *parentPom.Parent.GroupID - artifactID = *parentPom.Parent.ArtifactID - version = *parentPom.Parent.Version - } - - return licenses -} - -func getPomFromMavenRepo(ctx context.Context, groupID, artifactID, version, mavenBaseURL string) (*gopom.Project, error) { - requestURL, err := formatMavenPomURL(groupID, artifactID, version, mavenBaseURL) - if err != nil { - return nil, err - } - log.Tracef("trying to fetch parent pom from Maven central %s", requestURL) - - mavenRequest, err := http.NewRequest(http.MethodGet, requestURL, nil) - if err != nil { - return nil, fmt.Errorf("unable to format request for Maven central: %w", err) - } - - httpClient := &http.Client{ - Timeout: time.Second * 10, - } - - mavenRequest = mavenRequest.WithContext(ctx) - - resp, err := httpClient.Do(mavenRequest) - if err != nil { - return nil, fmt.Errorf("unable to get pom from Maven central: %w", err) - } - defer func() { - if err := resp.Body.Close(); err != nil { - log.Errorf("unable to close body: %+v", err) - } - }() - - bytes, err := io.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("unable to parse pom from Maven central: %w", err) - } - - pom, err := decodePomXML(strings.NewReader(string(bytes))) - if err != nil { - return nil, fmt.Errorf("unable to parse pom from Maven central: %w", err) - } - - return &pom, nil -} - -func parseLicensesFromPom(pom *gopom.Project) []string { - var licenses []string - if pom != nil && pom.Licenses != nil { - for _, license := range *pom.Licenses { - if license.Name != nil { - licenses = append(licenses, *license.Name) - } else if license.URL != nil { - licenses = append(licenses, *license.URL) - } - } - } - - return licenses -} diff --git a/syft/pkg/cataloger/java/maven_resolver.go b/syft/pkg/cataloger/java/maven_resolver.go new file mode 100644 index 000000000..5fddccc31 --- /dev/null +++ b/syft/pkg/cataloger/java/maven_resolver.go @@ -0,0 +1,624 @@ +package java + +import ( + "bytes" + "context" + "errors" + "fmt" + "io" + "net/http" + "os" + "path" + "path/filepath" + "reflect" + "regexp" + "slices" + "strings" + "time" + + "github.com/vifraa/gopom" + + "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/cache" + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/syft/file" +) + +// mavenID is the unique identifier for a package in Maven +type mavenID struct { + GroupID string + ArtifactID string + Version string +} + +func (m mavenID) String() string { + return fmt.Sprintf("(groupId: %s artifactId: %s version: %s)", m.GroupID, m.ArtifactID, m.Version) +} + +var expressionMatcher = regexp.MustCompile("[$][{][^}]+[}]") + +// mavenResolver is a short-lived utility to resolve maven poms from multiple sources, including: +// the scanned filesystem, local maven cache directories, remote maven repositories, and the syft cache +type mavenResolver struct { + cfg ArchiveCatalogerConfig + cache cache.Cache + resolved map[mavenID]*gopom.Project + remoteRequestTimeout time.Duration + checkedLocalRepo bool + // fileResolver and pomLocations are used to resolve parent poms by relativePath + fileResolver file.Resolver + pomLocations map[*gopom.Project]file.Location +} + +// newMavenResolver constructs a new mavenResolver with the given configuration. +// NOTE: the fileResolver is optional and if provided will be used to resolve parent poms by relative path +func newMavenResolver(fileResolver file.Resolver, cfg ArchiveCatalogerConfig) *mavenResolver { + return &mavenResolver{ + cfg: cfg, + cache: cache.GetManager().GetCache("java/maven/repo", "v1"), + resolved: map[mavenID]*gopom.Project{}, + remoteRequestTimeout: time.Second * 10, + fileResolver: fileResolver, + pomLocations: map[*gopom.Project]file.Location{}, + } +} + +// getPropertyValue gets property values by emulating maven property resolution logic, looking in the project's variables +// as well as supporting the project expressions like ${project.parent.groupId}. +// Properties which are not resolved result in empty string "" +func (r *mavenResolver) getPropertyValue(ctx context.Context, propertyValue *string, resolutionContext ...*gopom.Project) string { + if propertyValue == nil { + return "" + } + resolved, err := r.resolveExpression(ctx, resolutionContext, *propertyValue, nil) + if err != nil { + log.WithFields("error", err, "propertyValue", *propertyValue).Debug("error resolving maven property") + return "" + } + return resolved +} + +// resolveExpression resolves an expression, which may be a plain string or a string with ${ property.references } +func (r *mavenResolver) resolveExpression(ctx context.Context, resolutionContext []*gopom.Project, expression string, resolving []string) (string, error) { + var err error + return expressionMatcher.ReplaceAllStringFunc(expression, func(match string) string { + propertyExpression := strings.TrimSpace(match[2 : len(match)-1]) // remove leading ${ and trailing } + resolved, e := r.resolveProperty(ctx, resolutionContext, propertyExpression, resolving) + if e != nil { + err = errors.Join(err, e) + return "" + } + return resolved + }), err +} + +// resolveProperty resolves properties recursively from the root project +func (r *mavenResolver) resolveProperty(ctx context.Context, resolutionContext []*gopom.Project, propertyExpression string, resolving []string) (string, error) { + // prevent cycles + if slices.Contains(resolving, propertyExpression) { + return "", fmt.Errorf("cycle detected resolving: %s", propertyExpression) + } + if len(resolutionContext) == 0 { + return "", fmt.Errorf("no project variable resolution context provided for expression: '%s'", propertyExpression) + } + resolving = append(resolving, propertyExpression) + + // only resolve project. properties in the context of the current project pom + value, err := r.resolveProjectProperty(ctx, resolutionContext, resolutionContext[len(resolutionContext)-1], propertyExpression, resolving) + if err != nil { + return value, err + } + if value != "" { + return value, nil + } + + for _, pom := range resolutionContext { + current := pom + for parentDepth := 0; current != nil; parentDepth++ { + if r.cfg.MaxParentRecursiveDepth > 0 && parentDepth > r.cfg.MaxParentRecursiveDepth { + return "", fmt.Errorf("maximum parent recursive depth (%v) reached resolving property: %v", r.cfg.MaxParentRecursiveDepth, propertyExpression) + } + if current.Properties != nil && current.Properties.Entries != nil { + if value, ok := current.Properties.Entries[propertyExpression]; ok { + return r.resolveExpression(ctx, resolutionContext, value, resolving) // property values can contain expressions + } + } + current, err = r.resolveParent(ctx, current) + if err != nil { + return "", err + } + } + } + + return "", fmt.Errorf("unable to resolve property: %s", propertyExpression) +} + +// resolveProjectProperty resolves properties on the project +// +//nolint:gocognit +func (r *mavenResolver) resolveProjectProperty(ctx context.Context, resolutionContext []*gopom.Project, pom *gopom.Project, propertyExpression string, resolving []string) (string, error) { + // see if we have a project.x expression and process this based + // on the xml tags in gopom + parts := strings.Split(propertyExpression, ".") + numParts := len(parts) + if numParts > 1 && strings.TrimSpace(parts[0]) == "project" { + pomValue := reflect.ValueOf(pom).Elem() + pomValueType := pomValue.Type() + for partNum := 1; partNum < numParts; partNum++ { + if pomValueType.Kind() != reflect.Struct { + break + } + + part := parts[partNum] + // these two fields are directly inherited from the pom parent values + if partNum == 1 && pom.Parent != nil { + switch part { + case "version": + if pom.Version == nil && pom.Parent.Version != nil { + return r.resolveExpression(ctx, resolutionContext, *pom.Parent.Version, resolving) + } + case "groupID": + if pom.GroupID == nil && pom.Parent.GroupID != nil { + return r.resolveExpression(ctx, resolutionContext, *pom.Parent.GroupID, resolving) + } + } + } + for fieldNum := 0; fieldNum < pomValueType.NumField(); fieldNum++ { + f := pomValueType.Field(fieldNum) + tag := f.Tag.Get("xml") + tag = strings.Split(tag, ",")[0] + // a segment of the property name matches the xml tag for the field, + // so we need to recurse down the nested structs or return a match + // if we're done. + if part != tag { + continue + } + + pomValue = pomValue.Field(fieldNum) + pomValueType = pomValue.Type() + if pomValueType.Kind() == reflect.Ptr { + // we were recursing down the nested structs, but one of the steps + // we need to take is a nil pointer, so give up + if pomValue.IsNil() { + return "", fmt.Errorf("property undefined: %s", propertyExpression) + } + pomValue = pomValue.Elem() + if !pomValue.IsZero() { + // we found a non-zero value whose tag matches this part of the property name + pomValueType = pomValue.Type() + } + } + // If this was the last part of the property name, return the value + if partNum == numParts-1 { + value := fmt.Sprintf("%v", pomValue.Interface()) + return r.resolveExpression(ctx, resolutionContext, value, resolving) + } + break + } + } + } + return "", nil +} + +// resolveMavenID creates a new mavenID from a pom, resolving parent information as necessary +func (r *mavenResolver) resolveMavenID(ctx context.Context, pom *gopom.Project) mavenID { + if pom == nil { + return mavenID{} + } + groupID := r.getPropertyValue(ctx, pom.GroupID, pom) + artifactID := r.getPropertyValue(ctx, pom.ArtifactID, pom) + version := r.getPropertyValue(ctx, pom.Version, pom) + if pom.Parent != nil { + if groupID == "" { + groupID = r.getPropertyValue(ctx, pom.Parent.GroupID, pom) + } + if artifactID == "" { + artifactID = r.getPropertyValue(ctx, pom.Parent.ArtifactID, pom) + } + if version == "" { + version = r.getPropertyValue(ctx, pom.Parent.Version, pom) + } + } + return mavenID{groupID, artifactID, version} +} + +// resolveDependencyID creates a new mavenID from a dependency element in a pom, resolving information as necessary +func (r *mavenResolver) resolveDependencyID(ctx context.Context, pom *gopom.Project, dep gopom.Dependency) mavenID { + if pom == nil { + return mavenID{} + } + + groupID := r.getPropertyValue(ctx, dep.GroupID, pom) + artifactID := r.getPropertyValue(ctx, dep.ArtifactID, pom) + version := r.getPropertyValue(ctx, dep.Version, pom) + + var err error + if version == "" { + version, err = r.findInheritedVersion(ctx, pom, groupID, artifactID) + } + + depID := mavenID{groupID, artifactID, version} + + if err != nil { + log.WithFields("error", err, "mavenID", r.resolveMavenID(ctx, pom), "dependencyID", depID) + } + + return depID +} + +// findPom gets a pom from cache, local repository, or from a remote Maven repository depending on configuration +func (r *mavenResolver) findPom(ctx context.Context, groupID, artifactID, version string) (*gopom.Project, error) { + if groupID == "" || artifactID == "" || version == "" { + return nil, fmt.Errorf("invalid maven pom specification, require non-empty values for groupID: '%s', artifactID: '%s', version: '%s'", groupID, artifactID, version) + } + + id := mavenID{groupID, artifactID, version} + pom := r.resolved[id] + + if pom != nil { + return pom, nil + } + + var errs error + + // try to resolve first from local maven repo + if r.cfg.UseMavenLocalRepository { + pom, err := r.findPomInLocalRepository(groupID, artifactID, version) + if pom != nil { + r.resolved[id] = pom + return pom, nil + } + errs = errors.Join(errs, err) + } + + // resolve via network maven repository + if pom == nil && r.cfg.UseNetwork { + pom, err := r.findPomInRemoteRepository(ctx, groupID, artifactID, version) + if pom != nil { + r.resolved[id] = pom + return pom, nil + } + errs = errors.Join(errs, err) + } + + return nil, fmt.Errorf("unable to resolve pom %s %s %s: %w", groupID, artifactID, version, errs) +} + +// findPomInLocalRepository attempts to get the POM from the users local maven repository +func (r *mavenResolver) findPomInLocalRepository(groupID, artifactID, version string) (*gopom.Project, error) { + groupPath := filepath.Join(strings.Split(groupID, ".")...) + pomFilePath := filepath.Join(r.cfg.MavenLocalRepositoryDir, groupPath, artifactID, version, artifactID+"-"+version+".pom") + pomFile, err := os.Open(pomFilePath) + if err != nil { + if !r.checkedLocalRepo && errors.Is(err, os.ErrNotExist) { + r.checkedLocalRepo = true + // check if the directory exists at all, and if not just stop trying to resolve local maven files + fi, err := os.Stat(r.cfg.MavenLocalRepositoryDir) + if errors.Is(err, os.ErrNotExist) || !fi.IsDir() { + log.WithFields("error", err, "repositoryDir", r.cfg.MavenLocalRepositoryDir). + Info("local maven repository is not a readable directory, stopping local resolution") + r.cfg.UseMavenLocalRepository = false + } + } + return nil, err + } + defer internal.CloseAndLogError(pomFile, pomFilePath) + + return decodePomXML(pomFile) +} + +// findPomInRemoteRepository download the pom file from a (remote) Maven repository over HTTP +func (r *mavenResolver) findPomInRemoteRepository(ctx context.Context, groupID, artifactID, version string) (*gopom.Project, error) { + if groupID == "" || artifactID == "" || version == "" { + return nil, fmt.Errorf("missing/incomplete maven artifact coordinates -- groupId: '%s' artifactId: '%s', version: '%s'", groupID, artifactID, version) + } + + requestURL, err := remotePomURL(r.cfg.MavenBaseURL, groupID, artifactID, version) + if err != nil { + return nil, fmt.Errorf("unable to find pom in remote due to: %w", err) + } + + // Downloading snapshots requires additional steps to determine the latest snapshot version. + // See: https://maven.apache.org/ref/3-LATEST/maven-repository-metadata/ + if strings.HasSuffix(version, "-SNAPSHOT") { + return nil, fmt.Errorf("downloading snapshot artifacts is not supported, got: %s", requestURL) + } + + cacheKey := strings.TrimPrefix(strings.TrimPrefix(requestURL, "http://"), "https://") + reader, err := r.cacheResolveReader(cacheKey, func() (io.ReadCloser, error) { + if err != nil { + return nil, err + } + log.WithFields("url", requestURL).Info("fetching parent pom from remote maven repository") + + req, err := http.NewRequest(http.MethodGet, requestURL, nil) + if err != nil { + return nil, fmt.Errorf("unable to create request for Maven central: %w", err) + } + + req = req.WithContext(ctx) + + client := http.Client{ + Timeout: r.remoteRequestTimeout, + } + + resp, err := client.Do(req) //nolint:bodyclose + if err != nil { + return nil, fmt.Errorf("unable to get pom from Maven repository %v: %w", requestURL, err) + } + if resp.StatusCode == http.StatusNotFound { + return nil, fmt.Errorf("pom not found in Maven repository at: %v", requestURL) + } + return resp.Body, err + }) + if err != nil { + return nil, err + } + if reader, ok := reader.(io.Closer); ok { + defer internal.CloseAndLogError(reader, requestURL) + } + pom, err := decodePomXML(reader) + if err != nil { + return nil, fmt.Errorf("unable to parse pom from Maven repository url %v: %w", requestURL, err) + } + return pom, nil +} + +// cacheResolveReader attempts to get a reader from cache, otherwise caches the contents of the resolve() function. +// this function is guaranteed to return an unread reader for the correct contents. +// NOTE: this could be promoted to the internal cache package as a specialized version of the cache.Resolver +// if there are more users of this functionality +func (r *mavenResolver) cacheResolveReader(key string, resolve func() (io.ReadCloser, error)) (io.Reader, error) { + reader, err := r.cache.Read(key) + if err == nil && reader != nil { + return reader, err + } + + contentReader, err := resolve() + if err != nil { + return nil, err + } + defer internal.CloseAndLogError(contentReader, key) + + // store the contents to return a new reader with the same content + contents, err := io.ReadAll(contentReader) + if err != nil { + return nil, err + } + err = r.cache.Write(key, bytes.NewBuffer(contents)) + return bytes.NewBuffer(contents), err +} + +// resolveParent attempts to resolve the parent for the given pom +func (r *mavenResolver) resolveParent(ctx context.Context, pom *gopom.Project) (*gopom.Project, error) { + if pom == nil || pom.Parent == nil { + return nil, nil + } + parent := pom.Parent + pomWithoutParent := *pom + pomWithoutParent.Parent = nil + groupID := r.getPropertyValue(ctx, parent.GroupID, &pomWithoutParent) + artifactID := r.getPropertyValue(ctx, parent.ArtifactID, &pomWithoutParent) + version := r.getPropertyValue(ctx, parent.Version, &pomWithoutParent) + + // check cache before resolving + parentID := mavenID{groupID, artifactID, version} + if resolvedParent, ok := r.resolved[parentID]; ok { + return resolvedParent, nil + } + + // check if the pom exists in the fileResolver + parentPom := r.findParentPomByRelativePath(ctx, pom, parentID) + if parentPom != nil { + return parentPom, nil + } + + // find POM normally + return r.findPom(ctx, groupID, artifactID, version) +} + +// findInheritedVersion attempts to find the version of a dependency (groupID, artifactID) by searching all parent poms and imported managed dependencies +// +//nolint:gocognit,funlen +func (r *mavenResolver) findInheritedVersion(ctx context.Context, pom *gopom.Project, groupID, artifactID string, resolutionContext ...*gopom.Project) (string, error) { + if pom == nil { + return "", fmt.Errorf("nil pom provided to findInheritedVersion") + } + if r.cfg.MaxParentRecursiveDepth > 0 && len(resolutionContext) > r.cfg.MaxParentRecursiveDepth { + return "", fmt.Errorf("maximum depth reached attempting to resolve version for: %s:%s at: %v", groupID, artifactID, r.resolveMavenID(ctx, pom)) + } + if slices.Contains(resolutionContext, pom) { + return "", fmt.Errorf("cycle detected attempting to resolve version for: %s:%s at: %v", groupID, artifactID, r.resolveMavenID(ctx, pom)) + } + resolutionContext = append(resolutionContext, pom) + + var err error + var version string + + // check for entries in dependencyManagement first + for _, dep := range pomManagedDependencies(pom) { + depGroupID := r.getPropertyValue(ctx, dep.GroupID, resolutionContext...) + depArtifactID := r.getPropertyValue(ctx, dep.ArtifactID, resolutionContext...) + if depGroupID == groupID && depArtifactID == artifactID { + version = r.getPropertyValue(ctx, dep.Version, resolutionContext...) + if version != "" { + return version, nil + } + } + + // imported pom files should be treated just like parent poms, they are used to define versions of dependencies + if deref(dep.Type) == "pom" && deref(dep.Scope) == "import" { + depVersion := r.getPropertyValue(ctx, dep.Version, resolutionContext...) + + depPom, err := r.findPom(ctx, depGroupID, depArtifactID, depVersion) + if err != nil || depPom == nil { + log.WithFields("error", err, "mavenID", r.resolveMavenID(ctx, pom), "dependencyID", mavenID{depGroupID, depArtifactID, depVersion}). + Debug("unable to find imported pom looking for managed dependencies") + continue + } + version, err = r.findInheritedVersion(ctx, depPom, groupID, artifactID, resolutionContext...) + if err != nil { + log.WithFields("error", err, "mavenID", r.resolveMavenID(ctx, pom), "dependencyID", mavenID{depGroupID, depArtifactID, depVersion}). + Debug("error during findInheritedVersion") + } + if version != "" { + return version, nil + } + } + } + + // recursively check parents + parent, err := r.resolveParent(ctx, pom) + if err != nil { + return "", err + } + if parent != nil { + version, err = r.findInheritedVersion(ctx, parent, groupID, artifactID, resolutionContext...) + if err != nil { + return "", err + } + if version != "" { + return version, nil + } + } + + // check for inherited dependencies + for _, dep := range pomDependencies(pom) { + depGroupID := r.getPropertyValue(ctx, dep.GroupID, resolutionContext...) + depArtifactID := r.getPropertyValue(ctx, dep.ArtifactID, resolutionContext...) + if depGroupID == groupID && depArtifactID == artifactID { + version = r.getPropertyValue(ctx, dep.Version, resolutionContext...) + if version != "" { + return version, nil + } + } + } + + return "", nil +} + +// findLicenses search pom for license, traversing parent poms if needed +func (r *mavenResolver) findLicenses(ctx context.Context, groupID, artifactID, version string) ([]gopom.License, error) { + pom, err := r.findPom(ctx, groupID, artifactID, version) + if pom == nil || err != nil { + return nil, err + } + return r.resolveLicenses(ctx, pom) +} + +// resolveLicenses searches the pom for license, traversing parent poms if needed +func (r *mavenResolver) resolveLicenses(ctx context.Context, pom *gopom.Project, processing ...mavenID) ([]gopom.License, error) { + id := r.resolveMavenID(ctx, pom) + if slices.Contains(processing, id) { + return nil, fmt.Errorf("cycle detected resolving licenses for: %v", id) + } + if r.cfg.MaxParentRecursiveDepth > 0 && len(processing) > r.cfg.MaxParentRecursiveDepth { + return nil, fmt.Errorf("maximum parent recursive depth (%v) reached: %v", r.cfg.MaxParentRecursiveDepth, processing) + } + + directLicenses := r.pomLicenses(ctx, pom) + if len(directLicenses) > 0 { + return directLicenses, nil + } + + parent, err := r.resolveParent(ctx, pom) + if err != nil { + return nil, err + } + if parent == nil { + return nil, nil + } + return r.resolveLicenses(ctx, parent, append(processing, id)...) +} + +// pomLicenses appends the directly specified licenses with non-empty name or url +func (r *mavenResolver) pomLicenses(ctx context.Context, pom *gopom.Project) []gopom.License { + var out []gopom.License + for _, license := range deref(pom.Licenses) { + // if we find non-empty licenses, return them + name := r.getPropertyValue(ctx, license.Name, pom) + url := r.getPropertyValue(ctx, license.URL, pom) + if name != "" || url != "" { + out = append(out, license) + } + } + return out +} + +func (r *mavenResolver) findParentPomByRelativePath(ctx context.Context, pom *gopom.Project, parentID mavenID) *gopom.Project { + // don't resolve if no resolver + if r.fileResolver == nil { + return nil + } + + pomLocation, hasPomLocation := r.pomLocations[pom] + if !hasPomLocation || pom == nil || pom.Parent == nil { + return nil + } + relativePath := r.getPropertyValue(ctx, pom.Parent.RelativePath, pom) + if relativePath == "" { + return nil + } + p := pomLocation.Path() + p = path.Dir(p) + p = path.Join(p, relativePath) + p = path.Clean(p) + parentLocations, err := r.fileResolver.FilesByPath(p) + if err != nil || len(parentLocations) == 0 { + log.WithFields("error", err, "mavenID", r.resolveMavenID(ctx, pom), "parentID", parentID, "relativePath", relativePath). + Trace("parent pom not found by relative path") + return nil + } + parentLocation := parentLocations[0] + + parentContents, err := r.fileResolver.FileContentsByLocation(parentLocation) + if err != nil || parentContents == nil { + log.WithFields("error", err, "mavenID", r.resolveMavenID(ctx, pom), "parentID", parentID, "parentLocation", parentLocation). + Debug("unable to get contents of parent pom by relative path") + return nil + } + defer internal.CloseAndLogError(parentContents, parentLocation.RealPath) + parentPom, err := decodePomXML(parentContents) + if err != nil || parentPom == nil { + log.WithFields("error", err, "mavenID", r.resolveMavenID(ctx, pom), "parentID", parentID, "parentLocation", parentLocation). + Debug("unable to parse parent pom") + return nil + } + // ensure parent matches + newParentID := r.resolveMavenID(ctx, parentPom) + if newParentID.ArtifactID != parentID.ArtifactID { + log.WithFields("newParentID", newParentID, "mavenID", r.resolveMavenID(ctx, pom), "parentID", parentID, "parentLocation", parentLocation). + Debug("parent IDs do not match resolving parent by relative path") + return nil + } + + r.resolved[parentID] = parentPom + r.pomLocations[parentPom] = parentLocation // for any future parent relativepath lookups + + return parentPom +} + +// pomDependencies returns all dependencies directly defined in a project, including all defined in profiles. +// does not resolve parent dependencies +func pomDependencies(pom *gopom.Project) []gopom.Dependency { + dependencies := deref(pom.Dependencies) + for _, profile := range deref(pom.Profiles) { + dependencies = append(dependencies, deref(profile.Dependencies)...) + } + return dependencies +} + +// pomManagedDependencies returns all directly defined managed dependencies in a project pom, including all defined in profiles. +// does not resolve parent managed dependencies +func pomManagedDependencies(pom *gopom.Project) []gopom.Dependency { + var dependencies []gopom.Dependency + if pom.DependencyManagement != nil { + dependencies = append(dependencies, deref(pom.DependencyManagement.Dependencies)...) + } + for _, profile := range deref(pom.Profiles) { + if profile.DependencyManagement != nil { + dependencies = append(dependencies, deref(profile.DependencyManagement.Dependencies)...) + } + } + return dependencies +} diff --git a/syft/pkg/cataloger/java/maven_resolver_test.go b/syft/pkg/cataloger/java/maven_resolver_test.go new file mode 100644 index 000000000..d778efb69 --- /dev/null +++ b/syft/pkg/cataloger/java/maven_resolver_test.go @@ -0,0 +1,359 @@ +package java + +import ( + "context" + "io" + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "testing" + + "github.com/bmatcuk/doublestar/v4" + "github.com/stretchr/testify/require" + "github.com/vifraa/gopom" + + "github.com/anchore/syft/internal" + "github.com/anchore/syft/syft/internal/fileresolver" +) + +func Test_resolveProperty(t *testing.T) { + tests := []struct { + name string + property string + pom gopom.Project + expected string + }{ + { + name: "property", + property: "${version.number}", + pom: gopom.Project{ + Properties: &gopom.Properties{ + Entries: map[string]string{ + "version.number": "12.5.0", + }, + }, + }, + expected: "12.5.0", + }, + { + name: "groupId", + property: "${project.groupId}", + pom: gopom.Project{ + GroupID: ptr("org.some.group"), + }, + expected: "org.some.group", + }, + { + name: "parent groupId", + property: "${project.parent.groupId}", + pom: gopom.Project{ + Parent: &gopom.Parent{ + GroupID: ptr("org.some.parent"), + }, + }, + expected: "org.some.parent", + }, + { + name: "nil pointer halts search", + property: "${project.parent.groupId}", + pom: gopom.Project{ + Parent: nil, + }, + expected: "", + }, + { + name: "nil string pointer halts search", + property: "${project.parent.groupId}", + pom: gopom.Project{ + Parent: &gopom.Parent{ + GroupID: nil, + }, + }, + expected: "", + }, + { + name: "double dereference", + property: "${springboot.version}", + pom: gopom.Project{ + Parent: &gopom.Parent{ + Version: ptr("1.2.3"), + }, + Properties: &gopom.Properties{ + Entries: map[string]string{ + "springboot.version": "${project.parent.version}", + }, + }, + }, + expected: "1.2.3", + }, + { + name: "map missing stops double dereference", + property: "${springboot.version}", + pom: gopom.Project{ + Parent: &gopom.Parent{ + Version: ptr("1.2.3"), + }, + }, + expected: "", + }, + { + name: "resolution halts even if it resolves to a variable", + property: "${springboot.version}", + pom: gopom.Project{ + Parent: &gopom.Parent{ + Version: ptr("${undefined.version}"), + }, + Properties: &gopom.Properties{ + Entries: map[string]string{ + "springboot.version": "${project.parent.version}", + }, + }, + }, + expected: "", + }, + { + name: "resolution halts even if cyclic", + property: "${springboot.version}", + pom: gopom.Project{ + Properties: &gopom.Properties{ + Entries: map[string]string{ + "springboot.version": "${springboot.version}", + }, + }, + }, + expected: "", + }, + { + name: "resolution halts even if cyclic more steps", + property: "${cyclic.version}", + pom: gopom.Project{ + Properties: &gopom.Properties{ + Entries: map[string]string{ + "other.version": "${cyclic.version}", + "springboot.version": "${other.version}", + "cyclic.version": "${springboot.version}", + }, + }, + }, + expected: "", + }, + { + name: "resolution halts even if cyclic involving parent", + property: "${cyclic.version}", + pom: gopom.Project{ + Parent: &gopom.Parent{ + Version: ptr("${cyclic.version}"), + }, + Properties: &gopom.Properties{ + Entries: map[string]string{ + "other.version": "${parent.version}", + "springboot.version": "${other.version}", + "cyclic.version": "${springboot.version}", + }, + }, + }, + expected: "", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + r := newMavenResolver(nil, DefaultArchiveCatalogerConfig()) + resolved := r.getPropertyValue(context.Background(), ptr(test.property), &test.pom) + require.Equal(t, test.expected, resolved) + }) + } +} + +func Test_mavenResolverLocal(t *testing.T) { + dir, err := filepath.Abs("test-fixtures/pom/maven-repo") + require.NoError(t, err) + + tests := []struct { + name string + groupID string + artifactID string + version string + maxDepth int + expression string + expected string + wantErr require.ErrorAssertionFunc + }{ + { + name: "artifact id with variable from 2nd parent", + groupID: "my.org", + artifactID: "child-one", + version: "1.3.6", + expression: "${project.one}", + expected: "1", + }, + { + name: "depth limited large enough", + groupID: "my.org", + artifactID: "child-one", + version: "1.3.6", + expression: "${project.one}", + expected: "1", + maxDepth: 2, + }, + { + name: "depth limited should not resolve", + groupID: "my.org", + artifactID: "child-one", + version: "1.3.6", + expression: "${project.one}", + expected: "", + maxDepth: 1, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ctx := context.Background() + r := newMavenResolver(nil, ArchiveCatalogerConfig{ + UseNetwork: false, + UseMavenLocalRepository: true, + MavenLocalRepositoryDir: dir, + MaxParentRecursiveDepth: test.maxDepth, + }) + pom, err := r.findPom(ctx, test.groupID, test.artifactID, test.version) + if test.wantErr != nil { + test.wantErr(t, err) + } else { + require.NoError(t, err) + } + got := r.getPropertyValue(context.Background(), &test.expression, pom) + require.Equal(t, test.expected, got) + }) + } +} + +func Test_mavenResolverRemote(t *testing.T) { + url := mockMavenRepo(t) + + tests := []struct { + groupID string + artifactID string + version string + expression string + expected string + wantErr require.ErrorAssertionFunc + }{ + { + groupID: "my.org", + artifactID: "child-one", + version: "1.3.6", + expression: "${project.one}", + expected: "1", + }, + } + + for _, test := range tests { + t.Run(test.artifactID, func(t *testing.T) { + ctx := context.Background() + r := newMavenResolver(nil, ArchiveCatalogerConfig{ + UseNetwork: true, + UseMavenLocalRepository: false, + MavenBaseURL: url, + }) + pom, err := r.findPom(ctx, test.groupID, test.artifactID, test.version) + if test.wantErr != nil { + test.wantErr(t, err) + } else { + require.NoError(t, err) + } + got := r.getPropertyValue(context.Background(), &test.expression, pom) + require.Equal(t, test.expected, got) + }) + } +} + +func Test_relativePathParent(t *testing.T) { + resolver, err := fileresolver.NewFromDirectory("test-fixtures/pom/local", "") + require.NoError(t, err) + + r := newMavenResolver(resolver, DefaultArchiveCatalogerConfig()) + locs, err := resolver.FilesByPath("child-1/pom.xml") + require.NoError(t, err) + require.Len(t, locs, 1) + + loc := locs[0] + contents, err := resolver.FileContentsByLocation(loc) + require.NoError(t, err) + defer internal.CloseAndLogError(contents, loc.RealPath) + + pom, err := decodePomXML(contents) + require.NoError(t, err) + + r.pomLocations[pom] = loc + + ctx := context.Background() + parent, err := r.resolveParent(ctx, pom) + require.NoError(t, err) + require.Contains(t, r.pomLocations, parent) + + parent, err = r.resolveParent(ctx, parent) + require.NoError(t, err) + require.Contains(t, r.pomLocations, parent) + + got := r.getPropertyValue(ctx, ptr("${commons-exec_subversion}"), pom) + require.Equal(t, "3", got) +} + +// mockMavenRepo starts a remote maven repo serving all the pom files found in test-fixtures/pom/maven-repo +func mockMavenRepo(t *testing.T) (url string) { + t.Helper() + + return mockMavenRepoAt(t, "test-fixtures/pom/maven-repo") +} + +// mockMavenRepoAt starts a remote maven repo serving all the pom files found in the given directory +func mockMavenRepoAt(t *testing.T, dir string) (url string) { + t.Helper() + + // mux is the HTTP request multiplexer used with the test server. + mux := http.NewServeMux() + + // We want to ensure that tests catch mistakes where the endpoint URL is + // specified as absolute rather than relative. It only makes a difference + // when there's a non-empty base URL path. So, use that. See issue #752. + apiHandler := http.NewServeMux() + apiHandler.Handle("/", mux) + // server is a test HTTP server used to provide mock API responses. + server := httptest.NewServer(apiHandler) + + t.Cleanup(server.Close) + + matches, err := doublestar.Glob(os.DirFS(dir), filepath.Join("**", "*.pom")) + require.NoError(t, err) + + for _, match := range matches { + fullPath, err := filepath.Abs(filepath.Join(dir, match)) + require.NoError(t, err) + match = "/" + filepath.ToSlash(match) + mux.HandleFunc(match, mockMavenHandler(fullPath)) + } + + return server.URL +} + +func mockMavenHandler(responseFixture string) func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + // Set the Content-Type header to indicate that the response is XML + w.Header().Set("Content-Type", "application/xml") + // Copy the file's content to the response writer + f, err := os.Open(responseFixture) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + defer internal.CloseAndLogError(f, responseFixture) + _, err = io.Copy(w, f) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + } +} diff --git a/syft/pkg/cataloger/java/maven_utils.go b/syft/pkg/cataloger/java/maven_utils.go new file mode 100644 index 000000000..9d365e151 --- /dev/null +++ b/syft/pkg/cataloger/java/maven_utils.go @@ -0,0 +1,74 @@ +package java + +import ( + "encoding/xml" + "fmt" + "io" + "net/url" + "os" + "path/filepath" + "strings" + + "github.com/mitchellh/go-homedir" + + "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/log" +) + +// defaultMavenLocalRepoDir gets default location of the Maven local repository, generally at /.m2/repository +func defaultMavenLocalRepoDir() string { + homeDir, err := homedir.Dir() + if err != nil { + return "" + } + + mavenHome := filepath.Join(homeDir, ".m2") + + settingsXML := filepath.Join(mavenHome, "settings.xml") + settings, err := os.Open(settingsXML) + if err == nil && settings != nil { + defer internal.CloseAndLogError(settings, settingsXML) + localRepository := getSettingsXMLLocalRepository(settings) + if localRepository != "" { + return localRepository + } + } + return filepath.Join(mavenHome, "repository") +} + +// getSettingsXMLLocalRepository reads the provided settings.xml and parses the localRepository, if present +func getSettingsXMLLocalRepository(settingsXML io.Reader) string { + type settings struct { + LocalRepository string `xml:"localRepository"` + } + s := settings{} + err := xml.NewDecoder(settingsXML).Decode(&s) + if err != nil { + log.WithFields("error", err).Debug("unable to read maven settings.xml") + } + return s.LocalRepository +} + +// deref dereferences ptr if not nil, or returns the type default value if ptr is nil +func deref[T any](ptr *T) T { + if ptr == nil { + var t T + return t + } + return *ptr +} + +// remotePomURL returns a URL to download a POM from a remote repository +func remotePomURL(repoURL, groupID, artifactID, version string) (requestURL string, err error) { + // groupID needs to go from maven.org -> maven/org + urlPath := strings.Split(groupID, ".") + artifactPom := fmt.Sprintf("%s-%s.pom", artifactID, version) + urlPath = append(urlPath, artifactID, version, artifactPom) + + // ex: https://repo1.maven.org/maven2/groupID/artifactID/artifactPom + requestURL, err = url.JoinPath(repoURL, urlPath...) + if err != nil { + return requestURL, fmt.Errorf("could not construct maven url: %w", err) + } + return requestURL, err +} diff --git a/syft/pkg/cataloger/java/maven_utils_test.go b/syft/pkg/cataloger/java/maven_utils_test.go new file mode 100644 index 000000000..8d599b501 --- /dev/null +++ b/syft/pkg/cataloger/java/maven_utils_test.go @@ -0,0 +1,103 @@ +package java + +import ( + "os" + "path/filepath" + "testing" + + "github.com/mitchellh/go-homedir" + "github.com/stretchr/testify/require" +) + +func Test_defaultMavenLocalRepoDir(t *testing.T) { + home, err := homedir.Dir() + require.NoError(t, err) + + fixtures, err := filepath.Abs("test-fixtures") + require.NoError(t, err) + + tests := []struct { + name string + home string + expected string + }{ + { + name: "default", + expected: filepath.Join(home, ".m2", "repository"), + home: "", + }, + { + name: "alternate dir", + expected: "/some/other/repo", + home: "test-fixtures/local-repository-settings", + }, + { + name: "explicit home", + expected: filepath.Join(fixtures, ".m2", "repository"), + home: "test-fixtures", + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + homedir.Reset() + defer homedir.Reset() + if test.home != "" { + home, err := filepath.Abs(test.home) + require.NoError(t, err) + t.Setenv("HOME", home) + } + got := defaultMavenLocalRepoDir() + require.Equal(t, test.expected, got) + }) + } +} + +func Test_getSettingsXmlLocalRepository(t *testing.T) { + tests := []struct { + file string + expected string + }{ + { + expected: "/some/other/repo", + file: "test-fixtures/local-repository-settings/.m2/settings.xml", + }, + { + expected: "", + file: "invalid", + }, + } + for _, test := range tests { + t.Run(test.expected, func(t *testing.T) { + f, _ := os.Open(test.file) + defer f.Close() + got := getSettingsXMLLocalRepository(f) + require.Equal(t, test.expected, got) + }) + } +} + +func Test_remotePomURL(t *testing.T) { + tests := []struct { + name string + groupID string + artifactID string + version string + expected string + }{ + { + name: "formatMavenURL correctly assembles the pom URL", + groupID: "org.springframework.boot", + artifactID: "spring-boot-starter-test", + version: "3.1.5", + expected: "https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-starter-test/3.1.5/spring-boot-starter-test-3.1.5.pom", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + requestURL, err := remotePomURL(mavenBaseURL, tc.groupID, tc.artifactID, tc.version) + require.NoError(t, err, "expected no err; got %w", err) + require.Equal(t, tc.expected, requestURL) + }) + } +} diff --git a/syft/pkg/cataloger/java/parse_pom_xml.go b/syft/pkg/cataloger/java/parse_pom_xml.go index 5fe1f34d1..d9fe4b2c2 100644 --- a/syft/pkg/cataloger/java/parse_pom_xml.go +++ b/syft/pkg/cataloger/java/parse_pom_xml.go @@ -4,164 +4,175 @@ import ( "bytes" "context" "encoding/xml" + "errors" "fmt" "io" - "reflect" - "regexp" "strings" "github.com/saintfish/chardet" "github.com/vifraa/gopom" "golang.org/x/net/html/charset" + "github.com/anchore/syft/internal" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" - "github.com/anchore/syft/syft/pkg/cataloger/generic" ) -const pomXMLGlob = "*pom.xml" +const ( + pomXMLGlob = "*pom.xml" + pomCatalogerName = "java-pom-cataloger" +) + +type pomXMLCataloger struct { + cfg ArchiveCatalogerConfig +} -var propertyMatcher = regexp.MustCompile("[$][{][^}]+[}]") +func (p pomXMLCataloger) Name() string { + return pomCatalogerName +} -func (gap genericArchiveParserAdapter) parserPomXML(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { - pom, err := decodePomXML(reader) +func (p pomXMLCataloger) Catalog(ctx context.Context, fileResolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) { + locations, err := fileResolver.FilesByGlob("**/pom.xml") if err != nil { return nil, nil, err } - var pkgs []pkg.Package - if pom.Dependencies != nil { - for _, dep := range *pom.Dependencies { - p := newPackageFromPom( - ctx, - pom, - dep, - gap.cfg, - reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), - ) - if p.Name == "" { - continue - } + r := newMavenResolver(fileResolver, p.cfg) - pkgs = append(pkgs, p) + var poms []*gopom.Project + for _, pomLocation := range locations { + pom, err := readPomFromLocation(fileResolver, pomLocation) + if err != nil || pom == nil { + log.WithFields("error", err, "pomLocation", pomLocation).Debug("error while reading pom") + continue } + + poms = append(poms, pom) + + // store information about this pom for future lookups + r.pomLocations[pom] = pomLocation + r.resolved[r.resolveMavenID(ctx, pom)] = pom } + var pkgs []pkg.Package + for _, pom := range poms { + pkgs = append(pkgs, processPomXML(ctx, r, pom, r.pomLocations[pom])...) + } return pkgs, nil, nil } -func parsePomXMLProject(path string, reader io.Reader, location file.Location) (*parsedPomProject, error) { - project, err := decodePomXML(reader) +func readPomFromLocation(fileResolver file.Resolver, pomLocation file.Location) (*gopom.Project, error) { + contents, err := fileResolver.FileContentsByLocation(pomLocation) if err != nil { return nil, err } - return newPomProject(path, project, location), nil + defer internal.CloseAndLogError(contents, pomLocation.RealPath) + return decodePomXML(contents) } -func newPomProject(path string, p gopom.Project, location file.Location) *parsedPomProject { - artifactID := safeString(p.ArtifactID) - name := safeString(p.Name) - projectURL := safeString(p.URL) - - var licenses []pkg.License - if p.Licenses != nil { - for _, license := range *p.Licenses { - var licenseName, licenseURL string - if license.Name != nil { - licenseName = *license.Name - } - if license.URL != nil { - licenseURL = *license.URL - } - - if licenseName == "" && licenseURL == "" { - continue - } +func processPomXML(ctx context.Context, r *mavenResolver, pom *gopom.Project, loc file.Location) []pkg.Package { + var pkgs []pkg.Package - licenses = append(licenses, pkg.NewLicenseFromFields(licenseName, licenseURL, &location)) + pomID := r.resolveMavenID(ctx, pom) + for _, dep := range pomDependencies(pom) { + depID := r.resolveDependencyID(ctx, pom, dep) + log.WithFields("pomLocation", loc, "mavenID", pomID, "dependencyID", depID).Trace("adding maven pom dependency") + + p, err := newPackageFromDependency( + ctx, + r, + pom, + dep, + loc.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ) + if err != nil { + log.WithFields("error", err, "pomLocation", loc, "mavenID", pomID, "dependencyID", depID).Debugf("error adding dependency") + } + if p == nil { + continue } + pkgs = append(pkgs, *p) } - log.WithFields("path", path, "artifactID", artifactID, "name", name, "projectURL", projectURL).Trace("parsing pom.xml") - return &parsedPomProject{ - JavaPomProject: &pkg.JavaPomProject{ - Path: path, - Parent: pomParent(p, p.Parent), - GroupID: resolveProperty(p, p.GroupID, "groupId"), - ArtifactID: artifactID, - Version: resolveProperty(p, p.Version, "version"), - Name: name, - Description: cleanDescription(p.Description), - URL: projectURL, - }, - Licenses: licenses, + return pkgs +} + +func newPomProject(ctx context.Context, r *mavenResolver, path string, pom *gopom.Project) *pkg.JavaPomProject { + id := r.resolveMavenID(ctx, pom) + name := r.getPropertyValue(ctx, pom.Name, pom) + projectURL := r.getPropertyValue(ctx, pom.URL, pom) + + log.WithFields("path", path, "artifactID", id.ArtifactID, "name", name, "projectURL", projectURL).Trace("parsing pom.xml") + return &pkg.JavaPomProject{ + Path: path, + Parent: pomParent(ctx, r, pom), + GroupID: id.GroupID, + ArtifactID: id.ArtifactID, + Version: id.Version, + Name: name, + Description: cleanDescription(r.getPropertyValue(ctx, pom.Description, pom)), + URL: projectURL, } } -func newPackageFromPom(ctx context.Context, pom gopom.Project, dep gopom.Dependency, cfg ArchiveCatalogerConfig, locations ...file.Location) pkg.Package { +func newPackageFromDependency(ctx context.Context, r *mavenResolver, pom *gopom.Project, dep gopom.Dependency, locations ...file.Location) (*pkg.Package, error) { + id := r.resolveDependencyID(ctx, pom, dep) + m := pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ - GroupID: resolveProperty(pom, dep.GroupID, "groupId"), - ArtifactID: resolveProperty(pom, dep.ArtifactID, "artifactId"), - Scope: resolveProperty(pom, dep.Scope, "scope"), + GroupID: id.GroupID, + ArtifactID: id.ArtifactID, + Scope: r.getPropertyValue(ctx, dep.Scope, pom), }, } - name := safeString(dep.ArtifactID) - version := resolveProperty(pom, dep.Version, "version") + var err error + var licenses []pkg.License + dependencyPom, depErr := r.findPom(ctx, id.GroupID, id.ArtifactID, id.Version) + if depErr != nil { + err = errors.Join(err, depErr) + } - licenses := make([]pkg.License, 0) - if cfg.UseNetwork { - if version == "" { - // If we have no version then let's try to get it from a parent pom DependencyManagement section - version = recursivelyFindVersionFromParentPom(ctx, *dep.GroupID, *dep.ArtifactID, *pom.Parent.GroupID, *pom.Parent.ArtifactID, *pom.Parent.Version, cfg) - } - if version != "" { - parentLicenses := recursivelyFindLicensesFromParentPom( - ctx, - m.PomProperties.GroupID, - m.PomProperties.ArtifactID, - version, - cfg) - - if len(parentLicenses) > 0 { - for _, licenseName := range parentLicenses { - licenses = append(licenses, pkg.NewLicenseFromFields(licenseName, "", nil)) - } - } + if dependencyPom != nil { + depLicenses, _ := r.resolveLicenses(ctx, dependencyPom) + for _, license := range depLicenses { + licenses = append(licenses, pkg.NewLicenseFromFields(deref(license.Name), deref(license.URL), nil)) } } - p := pkg.Package{ - Name: name, - Version: version, + p := &pkg.Package{ + Name: id.ArtifactID, + Version: id.Version, Locations: file.NewLocationSet(locations...), Licenses: pkg.NewLicenseSet(licenses...), - PURL: packageURL(name, version, m), + PURL: packageURL(id.ArtifactID, id.Version, m), 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, } p.SetID() - return p + return p, err } -func decodePomXML(content io.Reader) (project gopom.Project, err error) { +// decodePomXML decodes a pom XML file, detecting and converting non-UTF-8 charsets. this DOES NOT perform any logic to resolve properties such as groupID, artifactID, and version +func decodePomXML(content io.Reader) (project *gopom.Project, err error) { inputReader, err := getUtf8Reader(content) if err != nil { - return project, fmt.Errorf("unable to read pom.xml: %w", err) + return nil, fmt.Errorf("unable to read pom.xml: %w", err) } decoder := xml.NewDecoder(inputReader) // when an xml file has a character set declaration (e.g. '') read that and use the correct decoder decoder.CharsetReader = charset.NewReaderLabel - if err := decoder.Decode(&project); err != nil { - return project, fmt.Errorf("unable to unmarshal pom.xml: %w", err) + project = &gopom.Project{} + if err := decoder.Decode(project); err != nil { + return nil, fmt.Errorf("unable to unmarshal pom.xml: %w", err) } return project, nil @@ -194,29 +205,28 @@ func getUtf8Reader(content io.Reader) (io.Reader, error) { return inputReader, nil } -func pomParent(pom gopom.Project, parent *gopom.Parent) (result *pkg.JavaPomParent) { - if parent == nil { +func pomParent(ctx context.Context, r *mavenResolver, pom *gopom.Project) *pkg.JavaPomParent { + if pom == nil || pom.Parent == nil { return nil } - artifactID := safeString(parent.ArtifactID) - result = &pkg.JavaPomParent{ - GroupID: resolveProperty(pom, parent.GroupID, "groupId"), - ArtifactID: artifactID, - Version: resolveProperty(pom, parent.Version, "version"), - } + groupID := r.getPropertyValue(ctx, pom.Parent.GroupID, pom) + artifactID := r.getPropertyValue(ctx, pom.Parent.ArtifactID, pom) + version := r.getPropertyValue(ctx, pom.Parent.Version, pom) - if result.GroupID == "" && result.ArtifactID == "" && result.Version == "" { + if groupID == "" && artifactID == "" && version == "" { return nil } - return result -} -func cleanDescription(original *string) (cleaned string) { - if original == nil { - return "" + return &pkg.JavaPomParent{ + GroupID: groupID, + ArtifactID: artifactID, + Version: version, } - descriptionLines := strings.Split(*original, "\n") +} + +func cleanDescription(original string) (cleaned string) { + descriptionLines := strings.Split(original, "\n") for _, line := range descriptionLines { line = strings.TrimSpace(line) if len(line) == 0 { @@ -226,94 +236,3 @@ func cleanDescription(original *string) (cleaned string) { } return strings.TrimSpace(cleaned) } - -// resolveProperty emulates some maven property resolution logic by looking in the project's variables -// as well as supporting the project expressions like ${project.parent.groupId}. -// If no match is found, the entire expression including ${} is returned -func resolveProperty(pom gopom.Project, property *string, propertyName string) string { - propertyCase := safeString(property) - log.WithFields("existingPropertyValue", propertyCase, "propertyName", propertyName).Trace("resolving property") - seenBeforePropertyNames := map[string]struct{}{ - propertyName: {}, - } - result := recursiveResolveProperty(pom, propertyCase, seenBeforePropertyNames) - if propertyMatcher.MatchString(result) { - return "" // dereferencing variable failed; fall back to empty string - } - return result -} - -//nolint:gocognit -func recursiveResolveProperty(pom gopom.Project, propertyCase string, seenPropertyNames map[string]struct{}) string { - return propertyMatcher.ReplaceAllStringFunc(propertyCase, func(match string) string { - propertyName := strings.TrimSpace(match[2 : len(match)-1]) // remove leading ${ and trailing } - if _, seen := seenPropertyNames[propertyName]; seen { - return propertyCase - } - entries := pomProperties(pom) - if value, ok := entries[propertyName]; ok { - seenPropertyNames[propertyName] = struct{}{} - return recursiveResolveProperty(pom, value, seenPropertyNames) // recursively resolve in case a variable points to a variable. - } - - // if we don't find anything directly in the pom properties, - // see if we have a project.x expression and process this based - // on the xml tags in gopom - parts := strings.Split(propertyName, ".") - numParts := len(parts) - if numParts > 1 && strings.TrimSpace(parts[0]) == "project" { - pomValue := reflect.ValueOf(pom) - pomValueType := pomValue.Type() - for partNum := 1; partNum < numParts; partNum++ { - if pomValueType.Kind() != reflect.Struct { - break - } - part := parts[partNum] - for fieldNum := 0; fieldNum < pomValueType.NumField(); fieldNum++ { - f := pomValueType.Field(fieldNum) - tag := f.Tag.Get("xml") - tag = strings.Split(tag, ",")[0] - // a segment of the property name matches the xml tag for the field, - // so we need to recurse down the nested structs or return a match - // if we're done. - if part == tag { - pomValue = pomValue.Field(fieldNum) - pomValueType = pomValue.Type() - if pomValueType.Kind() == reflect.Ptr { - // we were recursing down the nested structs, but one of the steps - // we need to take is a nil pointer, so give up and return the original match - if pomValue.IsNil() { - return match - } - pomValue = pomValue.Elem() - if !pomValue.IsZero() { - // we found a non-zero value whose tag matches this part of the property name - pomValueType = pomValue.Type() - } - } - // If this was the last part of the property name, return the value - if partNum == numParts-1 { - return fmt.Sprintf("%v", pomValue.Interface()) - } - break - } - } - } - } - return match - }) -} - -func pomProperties(p gopom.Project) map[string]string { - if p.Properties != nil { - return p.Properties.Entries - } - return map[string]string{} -} - -func safeString(s *string) string { - if s == nil { - return "" - } - return *s -} diff --git a/syft/pkg/cataloger/java/parse_pom_xml_test.go b/syft/pkg/cataloger/java/parse_pom_xml_test.go index 66ebb5216..456500490 100644 --- a/syft/pkg/cataloger/java/parse_pom_xml_test.go +++ b/syft/pkg/cataloger/java/parse_pom_xml_test.go @@ -1,6 +1,7 @@ package java import ( + "context" "encoding/base64" "io" "os" @@ -16,15 +17,17 @@ import ( "github.com/anchore/syft/syft/license" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" + "github.com/anchore/syft/syft/source" + "github.com/anchore/syft/syft/source/directorysource" ) -func Test_parserPomXML(t *testing.T) { +func Test_parsePomXML(t *testing.T) { tests := []struct { - input string + dir string expected []pkg.Package }{ { - input: "test-fixtures/pom/pom.xml", + dir: "test-fixtures/pom/local/example-java-app-maven", expected: []pkg.Package{ { Name: "joda-time", @@ -32,6 +35,7 @@ func Test_parserPomXML(t *testing.T) { PURL: "pkg:maven/com.joda/joda-time@2.9.2", Language: pkg.Java, Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "com.joda", @@ -45,6 +49,7 @@ func Test_parserPomXML(t *testing.T) { PURL: "pkg:maven/junit/junit@4.12", Language: pkg.Java, Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "junit", @@ -58,19 +63,19 @@ func Test_parserPomXML(t *testing.T) { } for _, test := range tests { - t.Run(test.input, func(t *testing.T) { + t.Run(test.dir, func(t *testing.T) { for i := range test.expected { - test.expected[i].Locations.Add(file.NewLocation(test.input)) + test.expected[i].Locations.Add(file.NewLocation("pom.xml")) } - gap := newGenericArchiveParserAdapter(ArchiveCatalogerConfig{ + cat := NewPomCataloger(ArchiveCatalogerConfig{ ArchiveSearchConfig: cataloging.ArchiveSearchConfig{ IncludeIndexedArchives: true, IncludeUnindexedArchives: true, }, }) - pkgtest.TestFileParser(t, test.input, gap.parserPomXML, test.expected, nil) + pkgtest.TestCataloger(t, test.dir, cat, test.expected, nil) }) } } @@ -131,168 +136,129 @@ func Test_decodePomXML_surviveNonUtf8Encoding(t *testing.T) { func Test_parseCommonsTextPomXMLProject(t *testing.T) { tests := []struct { - input string + dir string expected []pkg.Package }{ { - input: "test-fixtures/pom/commons-text.pom.xml", - expected: []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, - Metadata: pkg.JavaArchive{ - PomProperties: &pkg.JavaPomProperties{ - GroupID: "org.apache.commons", - ArtifactID: "commons-lang3", - }, - }, - }, - { - Name: "junit-jupiter", - Version: "", - PURL: "pkg:maven/org.junit.jupiter/junit-jupiter", - Language: pkg.Java, - Type: pkg.JavaPkg, - Metadata: pkg.JavaArchive{ - PomProperties: &pkg.JavaPomProperties{ - GroupID: "org.junit.jupiter", - ArtifactID: "junit-jupiter", - Scope: "test", - }, - }, - }, - { - Name: "assertj-core", - Version: "3.23.1", - PURL: "pkg:maven/org.assertj/assertj-core@3.23.1", - Language: pkg.Java, - Type: pkg.JavaPkg, - Metadata: pkg.JavaArchive{ - PomProperties: &pkg.JavaPomProperties{ - GroupID: "org.assertj", - ArtifactID: "assertj-core", - Scope: "test", - }, - }, - }, - { - Name: "commons-io", - Version: "2.11.0", - PURL: "pkg:maven/commons-io/commons-io@2.11.0", - Language: pkg.Java, - Type: pkg.JavaPkg, - Metadata: pkg.JavaArchive{ - PomProperties: &pkg.JavaPomProperties{ - GroupID: "commons-io", - ArtifactID: "commons-io", - Scope: "test", - }, - }, - }, - { - Name: "mockito-inline", - Version: "4.8.0", - PURL: "pkg:maven/org.mockito/mockito-inline@4.8.0", - Language: pkg.Java, - Type: pkg.JavaPkg, - Metadata: pkg.JavaArchive{ - PomProperties: &pkg.JavaPomProperties{ - GroupID: "org.mockito", - ArtifactID: "mockito-inline", - Scope: "test", - }, - }, - }, - { - Name: "js", - Version: "22.0.0.2", - PURL: "pkg:maven/org.graalvm.js/js@22.0.0.2", - Language: pkg.Java, - Type: pkg.JavaPkg, - Metadata: pkg.JavaArchive{ - PomProperties: &pkg.JavaPomProperties{ - GroupID: "org.graalvm.js", - ArtifactID: "js", - Scope: "test", - }, - }, - }, - { - 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, - Metadata: pkg.JavaArchive{ - PomProperties: &pkg.JavaPomProperties{ - GroupID: "org.graalvm.js", - ArtifactID: "js-scriptengine", - Scope: "test", - }, - }, + dir: "test-fixtures/pom/local/commons-text-1.10.0", + + expected: getCommonsTextExpectedPackages(), + }, + } + + for _, test := range tests { + t.Run(test.dir, func(t *testing.T) { + for i := range test.expected { + test.expected[i].Locations.Add(file.NewLocation("pom.xml")) + } + + cat := NewPomCataloger(ArchiveCatalogerConfig{ + ArchiveSearchConfig: cataloging.ArchiveSearchConfig{ + IncludeIndexedArchives: true, + IncludeUnindexedArchives: true, }, - { - Name: "commons-rng-simple", - Version: "1.4", - PURL: "pkg:maven/org.apache.commons/commons-rng-simple@1.4", - Language: pkg.Java, - Type: pkg.JavaPkg, - Metadata: pkg.JavaArchive{ - PomProperties: &pkg.JavaPomProperties{ - GroupID: "org.apache.commons", - ArtifactID: "commons-rng-simple", - Scope: "test", - }, - }, + UseMavenLocalRepository: false, + }) + pkgtest.TestCataloger(t, test.dir, cat, test.expected, nil) + }) + } +} + +func Test_parseCommonsTextPomXMLProjectWithLocalRepository(t *testing.T) { + // Using the local repository, the version of junit-jupiter will be resolved + expectedPackages := getCommonsTextExpectedPackages() + + for i := 0; i < len(expectedPackages); i++ { + if expectedPackages[i].Name == "junit-jupiter" { + expPkg := &expectedPackages[i] + expPkg.Version = "5.9.1" + expPkg.PURL = "pkg:maven/org.junit.jupiter/junit-jupiter@5.9.1" + expPkg.Metadata = pkg.JavaArchive{ + PomProperties: &pkg.JavaPomProperties{ + GroupID: "org.junit.jupiter", + ArtifactID: "junit-jupiter", + Scope: "test", }, - { - Name: "jmh-core", - Version: "1.35", - PURL: "pkg:maven/org.openjdk.jmh/jmh-core@1.35", - Language: pkg.Java, - Type: pkg.JavaPkg, - Metadata: pkg.JavaArchive{ - PomProperties: &pkg.JavaPomProperties{ - GroupID: "org.openjdk.jmh", - ArtifactID: "jmh-core", - Scope: "test", - }, - }, + } + } + } + + tests := []struct { + dir string + expected []pkg.Package + }{ + { + dir: "test-fixtures/pom/local/commons-text-1.10.0", + expected: expectedPackages, + }, + } + + for _, test := range tests { + t.Run(test.dir, func(t *testing.T) { + for i := range test.expected { + test.expected[i].Locations.Add(file.NewLocation("pom.xml")) + } + + cat := NewPomCataloger(ArchiveCatalogerConfig{ + ArchiveSearchConfig: cataloging.ArchiveSearchConfig{ + IncludeIndexedArchives: true, + IncludeUnindexedArchives: true, }, - { - Name: "jmh-generator-annprocess", - Version: "1.35", - PURL: "pkg:maven/org.openjdk.jmh/jmh-generator-annprocess@1.35", - Language: pkg.Java, - Type: pkg.JavaPkg, - Metadata: pkg.JavaArchive{ - PomProperties: &pkg.JavaPomProperties{ - GroupID: "org.openjdk.jmh", - ArtifactID: "jmh-generator-annprocess", - Scope: "test", - }, - }, + UseMavenLocalRepository: true, + MavenLocalRepositoryDir: "test-fixtures/pom/maven-repo", + }) + pkgtest.TestCataloger(t, test.dir, cat, test.expected, nil) + }) + } +} + +func Test_parseCommonsTextPomXMLProjectWithNetwork(t *testing.T) { + url := mockMavenRepo(t) + + // Using the local repository, the version of junit-jupiter will be resolved + expectedPackages := getCommonsTextExpectedPackages() + + for i := 0; i < len(expectedPackages); i++ { + if expectedPackages[i].Name == "junit-jupiter" { + expPkg := &expectedPackages[i] + expPkg.Version = "5.9.1" + expPkg.PURL = "pkg:maven/org.junit.jupiter/junit-jupiter@5.9.1" + expPkg.Metadata = pkg.JavaArchive{ + PomProperties: &pkg.JavaPomProperties{ + GroupID: "org.junit.jupiter", + ArtifactID: "junit-jupiter", + Scope: "test", }, - }, + } + } + } + + tests := []struct { + dir string + expected []pkg.Package + }{ + { + dir: "test-fixtures/pom/local/commons-text-1.10.0", + expected: expectedPackages, }, } for _, test := range tests { - t.Run(test.input, func(t *testing.T) { + t.Run(test.dir, func(t *testing.T) { for i := range test.expected { - test.expected[i].Locations.Add(file.NewLocation(test.input)) + test.expected[i].Locations.Add(file.NewLocation("pom.xml")) } - gap := newGenericArchiveParserAdapter(ArchiveCatalogerConfig{ + cat := NewPomCataloger(ArchiveCatalogerConfig{ ArchiveSearchConfig: cataloging.ArchiveSearchConfig{ IncludeIndexedArchives: true, IncludeUnindexedArchives: true, }, + UseNetwork: true, + MavenBaseURL: url, + UseMavenLocalRepository: false, }) - pkgtest.TestFileParser(t, test.input, gap.parserPomXML, test.expected, nil) + pkgtest.TestCataloger(t, test.dir, cat, test.expected, nil) }) } } @@ -302,63 +268,60 @@ func Test_parsePomXMLProject(t *testing.T) { jarLocation := file.NewLocation("path/to/archive.jar") tests := []struct { name string - expected parsedPomProject + project *pkg.JavaPomProject + licenses []pkg.License }{ { name: "go case", - expected: parsedPomProject{ - JavaPomProject: &pkg.JavaPomProject{ - Path: "test-fixtures/pom/commons-codec.pom.xml", - Parent: &pkg.JavaPomParent{ - GroupID: "org.apache.commons", - ArtifactID: "commons-parent", - Version: "42", - }, - GroupID: "commons-codec", - ArtifactID: "commons-codec", - Version: "1.11", - Name: "Apache Commons Codec", - Description: "The Apache Commons Codec package contains simple encoder and decoders for various formats such as Base64 and Hexadecimal. In addition to these widely used encoders and decoders, the codec package also maintains a collection of phonetic encoding utilities.", - URL: "http://commons.apache.org/proper/commons-codec/", + project: &pkg.JavaPomProject{ + Path: "test-fixtures/pom/commons-codec.pom.xml", + Parent: &pkg.JavaPomParent{ + GroupID: "org.apache.commons", + ArtifactID: "commons-parent", + Version: "42", }, + GroupID: "commons-codec", + ArtifactID: "commons-codec", + Version: "1.11", + Name: "Apache Commons Codec", + Description: "The Apache Commons Codec package contains simple encoder and decoders for various formats such as Base64 and Hexadecimal. In addition to these widely used encoders and decoders, the codec package also maintains a collection of phonetic encoding utilities.", + URL: "http://commons.apache.org/proper/commons-codec/", }, }, { name: "with license data", - expected: parsedPomProject{ - JavaPomProject: &pkg.JavaPomProject{ - Path: "test-fixtures/pom/neo4j-license-maven-plugin.pom.xml", - Parent: &pkg.JavaPomParent{ - GroupID: "org.sonatype.oss", - ArtifactID: "oss-parent", - Version: "7", - }, - GroupID: "org.neo4j.build.plugins", - ArtifactID: "license-maven-plugin", - Version: "4-SNAPSHOT", - Name: "${project.artifactId}", // TODO: this is not an ideal answer - Description: "Maven 2 plugin to check and update license headers in source files", - URL: "http://components.neo4j.org/${project.artifactId}/${project.version}", // TODO: this is not an ideal answer + project: &pkg.JavaPomProject{ + Path: "test-fixtures/pom/neo4j-license-maven-plugin.pom.xml", + Parent: &pkg.JavaPomParent{ + GroupID: "org.sonatype.oss", + ArtifactID: "oss-parent", + Version: "7", }, - Licenses: []pkg.License{ - { - Value: "The Apache Software License, Version 2.0", - SPDXExpression: "", // TODO: ideally we would parse this title to get Apache-2.0 (created issue #2210 https://github.com/anchore/syft/issues/2210) - Type: license.Declared, - URLs: []string{"http://www.apache.org/licenses/LICENSE-2.0.txt"}, - Locations: file.NewLocationSet(jarLocation), - }, - { - Value: "MIT", - SPDXExpression: "MIT", - Type: license.Declared, - Locations: file.NewLocationSet(jarLocation), - }, - { - Type: license.Declared, - URLs: []string{"https://opensource.org/license/unlicense/"}, - Locations: file.NewLocationSet(jarLocation), - }, + GroupID: "org.neo4j.build.plugins", + ArtifactID: "license-maven-plugin", + Version: "4-SNAPSHOT", + Name: "license-maven-plugin", + Description: "Maven 2 plugin to check and update license headers in source files", + URL: "http://components.neo4j.org/license-maven-plugin/4-SNAPSHOT", + }, + licenses: []pkg.License{ + { + Value: "The Apache Software License, Version 2.0", + SPDXExpression: "", // TODO: ideally we would parse this title to get Apache-2.0 (created issue #2210 https://github.com/anchore/syft/issues/2210) + Type: license.Declared, + URLs: []string{"http://www.apache.org/licenses/LICENSE-2.0.txt"}, + Locations: file.NewLocationSet(jarLocation), + }, + { + Value: "MIT", + SPDXExpression: "MIT", + Type: license.Declared, + Locations: file.NewLocationSet(jarLocation), + }, + { + Type: license.Declared, + URLs: []string{"https://opensource.org/license/unlicense/"}, + Locations: file.NewLocationSet(jarLocation), }, }, }, @@ -366,13 +329,20 @@ func Test_parsePomXMLProject(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - fixture, err := os.Open(test.expected.Path) + fixture, err := os.Open(test.project.Path) assert.NoError(t, err) + r := newMavenResolver(nil, ArchiveCatalogerConfig{}) + + pom, err := gopom.ParseFromReader(fixture) + require.NoError(t, err) - actual, err := parsePomXMLProject(fixture.Name(), fixture, jarLocation) + actual := newPomProject(context.Background(), r, fixture.Name(), pom) assert.NoError(t, err) + assert.Equal(t, test.project, actual) - assert.Equal(t, &test.expected, actual) + licenses := r.pomLicenses(context.Background(), pom) + assert.NoError(t, err) + assert.Equal(t, test.licenses, toPkgLicenses(&jarLocation, licenses)) }) } } @@ -386,7 +356,7 @@ func Test_pomParent(t *testing.T) { { name: "only group ID", input: &gopom.Parent{ - GroupID: stringPointer("org.something"), + GroupID: ptr("org.something"), }, expected: &pkg.JavaPomParent{ GroupID: "org.something", @@ -395,7 +365,7 @@ func Test_pomParent(t *testing.T) { { name: "only artifact ID", input: &gopom.Parent{ - ArtifactID: stringPointer("something"), + ArtifactID: ptr("something"), }, expected: &pkg.JavaPomParent{ ArtifactID: "something", @@ -404,7 +374,7 @@ func Test_pomParent(t *testing.T) { { name: "only Version", input: &gopom.Parent{ - Version: stringPointer("something"), + Version: ptr("something"), }, expected: &pkg.JavaPomParent{ Version: "something", @@ -423,7 +393,7 @@ func Test_pomParent(t *testing.T) { { name: "unused field", input: &gopom.Parent{ - RelativePath: stringPointer("something"), + RelativePath: ptr("something"), }, expected: nil, }, @@ -431,7 +401,8 @@ func Test_pomParent(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - assert.Equal(t, test.expected, pomParent(gopom.Project{}, test.input)) + r := newMavenResolver(nil, DefaultArchiveCatalogerConfig()) + assert.Equal(t, test.expected, pomParent(context.Background(), r, &gopom.Project{Parent: test.input})) }) } } @@ -454,184 +425,283 @@ func Test_cleanDescription(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - assert.Equal(t, test.expected, cleanDescription(stringPointer(test.input))) + assert.Equal(t, test.expected, cleanDescription(test.input)) }) } } -func Test_resolveProperty(t *testing.T) { +func Test_resolveLicenses(t *testing.T) { + mavenURL := mockMavenRepo(t) + localM2 := "test-fixtures/pom/maven-repo" + localDir := "test-fixtures/pom/local" + containingDir := "test-fixtures/pom/local/contains-child-1" + + expectedLicenses := []pkg.License{ + { + Value: "Eclipse Public License v2.0", + SPDXExpression: "", + Type: license.Declared, + URLs: []string{"https://www.eclipse.org/legal/epl-v20.html"}, + }, + } + tests := []struct { name string - property string - pom gopom.Project - expected string + scanDir string + cfg ArchiveCatalogerConfig + expected []pkg.License }{ { - name: "property", - property: "${version.number}", - pom: gopom.Project{ - Properties: &gopom.Properties{ - Entries: map[string]string{ - "version.number": "12.5.0", - }, - }, + name: "local no resolution", + scanDir: containingDir, + cfg: ArchiveCatalogerConfig{ + UseMavenLocalRepository: false, + UseNetwork: false, + MavenLocalRepositoryDir: "", + MavenBaseURL: "", }, - expected: "12.5.0", + expected: nil, }, { - name: "groupId", - property: "${project.groupId}", - pom: gopom.Project{ - GroupID: stringPointer("org.some.group"), + name: "local all poms", + scanDir: localDir, + cfg: ArchiveCatalogerConfig{ + UseMavenLocalRepository: false, + UseNetwork: false, }, - expected: "org.some.group", + expected: expectedLicenses, }, { - name: "parent groupId", - property: "${project.parent.groupId}", - pom: gopom.Project{ - Parent: &gopom.Parent{ - GroupID: stringPointer("org.some.parent"), - }, + name: "local m2 cache", + scanDir: containingDir, + cfg: ArchiveCatalogerConfig{ + UseMavenLocalRepository: true, + MavenLocalRepositoryDir: localM2, + UseNetwork: false, + MavenBaseURL: "", }, - expected: "org.some.parent", + expected: expectedLicenses, }, { - name: "nil pointer halts search", - property: "${project.parent.groupId}", - pom: gopom.Project{ - Parent: nil, + name: "local with network", + scanDir: containingDir, + cfg: ArchiveCatalogerConfig{ + UseMavenLocalRepository: false, + UseNetwork: true, + MavenBaseURL: mavenURL, }, - expected: "", + expected: expectedLicenses, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + cat := NewPomCataloger(test.cfg) + + ds, err := directorysource.NewFromPath(test.scanDir) + require.NoError(t, err) + + fr, err := ds.FileResolver(source.AllLayersScope) + require.NoError(t, err) + + ctx := context.TODO() + pkgs, _, err := cat.Catalog(ctx, fr) + require.NoError(t, err) + + var child1 pkg.Package + for _, p := range pkgs { + if p.Name == "child-one" { + child1 = p + break + } + } + require.Equal(t, "child-one", child1.Name) + + got := child1.Licenses.ToSlice() + for i := 0; i < len(got); i++ { + // ignore locations, just check license text + (&got[i]).Locations = file.LocationSet{} + } + require.ElementsMatch(t, test.expected, got) + }) + } +} + +func Test_getUtf8Reader(t *testing.T) { + tests := []struct { + name string + contents string + }{ + { + name: "unknown encoding", + // random binary contents + contents: "BkiJz02JyEWE0nXR6TH///9NicpJweEETIucJIgAAABJicxPjQwhTY1JCE05WQh0BU2J0eunTYshTIusJIAAAAAPHwBNOeV1BUUx2+tWTIlUJDhMiUwkSEyJRCQgSIl8JFBMiQ==", }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(tt.contents)) + + got, err := getUtf8Reader(decoder) + require.NoError(t, err) + gotBytes, err := io.ReadAll(got) + require.NoError(t, err) + // if we couldn't decode the section as UTF-8, we should get a replacement character + assert.Contains(t, string(gotBytes), "īŋŊ") + }) + } +} + +func getCommonsTextExpectedPackages() []pkg.Package { + return []pkg.Package{ { - name: "nil string pointer halts search", - property: "${project.parent.groupId}", - pom: gopom.Project{ - Parent: &gopom.Parent{ - GroupID: nil, + 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, + Metadata: pkg.JavaArchive{ + PomProperties: &pkg.JavaPomProperties{ + GroupID: "org.apache.commons", + ArtifactID: "commons-lang3", }, }, - expected: "", }, { - name: "double dereference", - property: "${springboot.version}", - pom: gopom.Project{ - Parent: &gopom.Parent{ - Version: stringPointer("1.2.3"), - }, - Properties: &gopom.Properties{ - Entries: map[string]string{ - "springboot.version": "${project.parent.version}", - }, + Name: "junit-jupiter", + Version: "", + PURL: "pkg:maven/org.junit.jupiter/junit-jupiter", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Metadata: pkg.JavaArchive{ + PomProperties: &pkg.JavaPomProperties{ + GroupID: "org.junit.jupiter", + ArtifactID: "junit-jupiter", + Scope: "test", }, }, - expected: "1.2.3", }, { - name: "map missing stops double dereference", - property: "${springboot.version}", - pom: gopom.Project{ - Parent: &gopom.Parent{ - Version: stringPointer("1.2.3"), + 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, + Metadata: pkg.JavaArchive{ + PomProperties: &pkg.JavaPomProperties{ + GroupID: "org.assertj", + ArtifactID: "assertj-core", + Scope: "test", }, }, - expected: "", }, { - name: "resolution halts even if it resolves to a variable", - property: "${springboot.version}", - pom: gopom.Project{ - Parent: &gopom.Parent{ - Version: stringPointer("${undefined.version}"), + 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, + Metadata: pkg.JavaArchive{ + PomProperties: &pkg.JavaPomProperties{ + GroupID: "commons-io", + ArtifactID: "commons-io", + Scope: "test", }, - Properties: &gopom.Properties{ - Entries: map[string]string{ - "springboot.version": "${project.parent.version}", - }, + }, + }, + { + 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, + Metadata: pkg.JavaArchive{ + PomProperties: &pkg.JavaPomProperties{ + GroupID: "org.mockito", + ArtifactID: "mockito-inline", + Scope: "test", }, }, - expected: "", }, { - name: "resolution halts even if cyclic", - property: "${springboot.version}", - pom: gopom.Project{ - Properties: &gopom.Properties{ - Entries: map[string]string{ - "springboot.version": "${springboot.version}", - }, + 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, + Metadata: pkg.JavaArchive{ + PomProperties: &pkg.JavaPomProperties{ + GroupID: "org.graalvm.js", + ArtifactID: "js", + Scope: "test", }, }, - expected: "", }, { - name: "resolution halts even if cyclic more steps", - property: "${cyclic.version}", - pom: gopom.Project{ - Properties: &gopom.Properties{ - Entries: map[string]string{ - "other.version": "${cyclic.version}", - "springboot.version": "${other.version}", - "cyclic.version": "${springboot.version}", - }, + 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, + Metadata: pkg.JavaArchive{ + PomProperties: &pkg.JavaPomProperties{ + GroupID: "org.graalvm.js", + ArtifactID: "js-scriptengine", + Scope: "test", }, }, - expected: "", }, { - name: "resolution halts even if cyclic involving parent", - property: "${cyclic.version}", - pom: gopom.Project{ - Parent: &gopom.Parent{ - Version: stringPointer("${cyclic.version}"), + 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, + Metadata: pkg.JavaArchive{ + PomProperties: &pkg.JavaPomProperties{ + GroupID: "org.apache.commons", + ArtifactID: "commons-rng-simple", + Scope: "test", }, - Properties: &gopom.Properties{ - Entries: map[string]string{ - "other.version": "${parent.version}", - "springboot.version": "${other.version}", - "cyclic.version": "${springboot.version}", - }, + }, + }, + { + Name: "jmh-core", + Version: "1.35", + PURL: "pkg:maven/org.openjdk.jmh/jmh-core@1.35", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Metadata: pkg.JavaArchive{ + PomProperties: &pkg.JavaPomProperties{ + GroupID: "org.openjdk.jmh", + ArtifactID: "jmh-core", + Scope: "test", }, }, - expected: "", }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - resolved := resolveProperty(test.pom, stringPointer(test.property), test.name) - assert.Equal(t, test.expected, resolved) - }) - } -} - -func stringPointer(s string) *string { - return &s -} - -func Test_getUtf8Reader(t *testing.T) { - tests := []struct { - name string - contents string - }{ { - name: "unknown encoding", - // random binary contents - contents: "BkiJz02JyEWE0nXR6TH///9NicpJweEETIucJIgAAABJicxPjQwhTY1JCE05WQh0BU2J0eunTYshTIusJIAAAAAPHwBNOeV1BUUx2+tWTIlUJDhMiUwkSEyJRCQgSIl8JFBMiQ==", + 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, + Metadata: pkg.JavaArchive{ + PomProperties: &pkg.JavaPomProperties{ + GroupID: "org.openjdk.jmh", + ArtifactID: "jmh-generator-annprocess", + Scope: "test", + }, + }, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(tt.contents)) - - got, err := getUtf8Reader(decoder) - require.NoError(t, err) - gotBytes, err := io.ReadAll(got) - require.NoError(t, err) - // if we couldn't decode the section as UTF-8, we should get a replacement character - assert.Contains(t, string(gotBytes), "īŋŊ") - }) - } } diff --git a/syft/pkg/cataloger/java/test-fixtures/local-repository-settings/.m2/settings.xml b/syft/pkg/cataloger/java/test-fixtures/local-repository-settings/.m2/settings.xml new file mode 100644 index 000000000..f8b9552a4 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/local-repository-settings/.m2/settings.xml @@ -0,0 +1,4 @@ + + /some/other/repo + \ No newline at end of file diff --git a/syft/pkg/cataloger/java/test-fixtures/pom/commons-text.pom.xml b/syft/pkg/cataloger/java/test-fixtures/pom/commons-text.pom.xml deleted file mode 100644 index 6f54a6ed6..000000000 --- a/syft/pkg/cataloger/java/test-fixtures/pom/commons-text.pom.xml +++ /dev/null @@ -1,575 +0,0 @@ - - - - 4.0.0 - - org.apache.commons - commons-parent - 54 - - commons-text - 1.10.0 - Apache Commons Text - Apache Commons Text is a library focused on algorithms working on strings. - https://commons.apache.org/proper/commons-text - - - ISO-8859-1 - UTF-8 - 1.8 - 1.8 - - text - org.apache.commons.text - - 1.10.0 - (Java 8+) - - TEXT - 12318221 - - text - https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-text - site-content - - 5.9.1 - 3.2.0 - 9.3 - - 4.7.2.0 - 4.7.2 - 3.19.0 - 6.49.0 - - 4.8.0 - 0.8.8 - - - 3.10.0 - 3.4.1 - - - 22.0.0.2 - 1.4 - - 0.16.0 - false - - 1.35 - 3.1.2 - - - 1.9 - RC1 - true - scm:svn:https://dist.apache.org/repos/dist/dev/commons/${commons.componentid} - Gary Gregory - 86fdc7e2a11262cb - - - - - org.apache.commons - commons-lang3 - 3.12.0 - - - - org.junit.jupiter - junit-jupiter - test - - - org.assertj - assertj-core - 3.23.1 - test - - - commons-io - commons-io - 2.11.0 - test - - - org.mockito - - mockito-inline - ${commons.mockito.version} - test - - - org.graalvm.js - js - ${graalvm.version} - test - - - org.graalvm.js - js-scriptengine - ${graalvm.version} - test - - - org.apache.commons - commons-rng-simple - ${commons.rng.version} - test - - - org.openjdk.jmh - jmh-core - ${jmh.version} - test - - - org.openjdk.jmh - jmh-generator-annprocess - ${jmh.version} - test - - - - - clean verify apache-rat:check japicmp:cmp checkstyle:check spotbugs:check javadoc:javadoc - - - - org.apache.rat - apache-rat-plugin - - - site-content/** - src/site/resources/download_lang.cgi - src/test/resources/org/apache/commons/text/stringEscapeUtilsTestData.txt - src/test/resources/org/apache/commons/text/lcs-perf-analysis-inputs.csv - src/site/resources/release-notes/RELEASE-NOTES-*.txt - - - - - maven-pmd-plugin - ${commons.pmd.version} - - ${maven.compiler.target} - - - - net.sourceforge.pmd - pmd-core - ${commons.pmd-impl.version} - - - net.sourceforge.pmd - pmd-java - ${commons.pmd-impl.version} - - - net.sourceforge.pmd - pmd-javascript - ${commons.pmd-impl.version} - - - net.sourceforge.pmd - pmd-jsp - ${commons.pmd-impl.version} - - - - - - - - maven-checkstyle-plugin - ${checkstyle.plugin.version} - - false - src/conf/checkstyle.xml - src/conf/checkstyle-header.txt - src/conf/checkstyle-suppressions.xml - src/conf/checkstyle-suppressions.xml - true - **/generated/**.java,**/jmh_generated/**.java - - - - com.puppycrawl.tools - checkstyle - ${checkstyle.version} - - - - - com.github.spotbugs - spotbugs-maven-plugin - ${commons.spotbugs.plugin.version} - - - com.github.spotbugs - spotbugs - ${commons.spotbugs.impl.version} - - - - src/conf/spotbugs-exclude-filter.xml - - - - maven-assembly-plugin - - - src/assembly/bin.xml - src/assembly/src.xml - - gnu - - - - org.apache.maven.plugins - maven-jar-plugin - - - - test-jar - - - - - - - ${commons.module.name} - - - - - - org.apache.maven.plugins - maven-scm-publish-plugin - - - javadocs - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - ${maven.compiler.source} - - - - - - - - - maven-checkstyle-plugin - ${checkstyle.plugin.version} - - false - src/conf/checkstyle.xml - src/conf/checkstyle-header.txt - src/conf/checkstyle-suppressions.xml - src/conf/checkstyle-suppressions.xml - true - **/generated/**.java,**/jmh_generated/**.java - - - - - checkstyle - - - - - - - com.github.spotbugs - spotbugs-maven-plugin - ${commons.spotbugs.plugin.version} - - src/conf/spotbugs-exclude-filter.xml - - - - com.github.siom79.japicmp - japicmp-maven-plugin - - - maven-pmd-plugin - 3.19.0 - - ${maven.compiler.target} - - - - - pmd - cpd - - - - - - org.codehaus.mojo - taglist-maven-plugin - 3.0.0 - - - - - Needs Work - - - TODO - exact - - - FIXME - exact - - - XXX - exact - - - - - Noteable Markers - - - NOTE - exact - - - NOPMD - exact - - - NOSONAR - exact - - - - - - - - - - - 2014 - - - - kinow - Bruno P. Kinoshita - kinow@apache.org - - - britter - Benedikt Ritter - britter@apache.org - - - chtompki - Rob Tompkins - chtompki@apache.org - - - ggregory - Gary Gregory - ggregory at apache.org - https://www.garygregory.com - The Apache Software Foundation - https://www.apache.org/ - - PMC Member - - America/New_York - - https://people.apache.org/~ggregory/img/garydgregory80.png - - - - djones - Duncan Jones - djones@apache.org - - - - - - Don Jeba - donjeba@yahoo.com - - - Sampanna Kahu - - - Jarek Strzelecki - - - Lee Adcock - - - Amey Jadiye - ameyjadiye@gmail.com - - - Arun Vinud S S - - - Ioannis Sermetziadis - - - Jostein Tveit - - - Luciano Medallia - - - Jan Martin Keil - - - Nandor Kollar - - - Nick Wong - - - Ali Ghanbari - https://ali-ghanbari.github.io/ - - - - - scm:git:https://gitbox.apache.org/repos/asf/commons-text - scm:git:https://gitbox.apache.org/repos/asf/commons-text - https://gitbox.apache.org/repos/asf?p=commons-text.git - - - - jira - https://issues.apache.org/jira/browse/TEXT - - - - - apache.website - Apache Commons Site - scm:svn:https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-text/ - - - - - - setup-checkout - - - site-content - - - - - - org.apache.maven.plugins - maven-antrun-plugin - - - prepare-checkout - - run - - pre-site - - - - - - - - - - - - - - - - - - - - - - - - java9+ - - [9,) - - - - true - - - - benchmark - - true - org.apache - - - - - org.codehaus.mojo - exec-maven-plugin - 3.1.0 - - - benchmark - test - - exec - - - test - java - - -classpath - - org.openjdk.jmh.Main - -rf - json - -rff - target/jmh-result.${benchmark}.json - ${benchmark} - - - - - - - - - - \ No newline at end of file diff --git a/syft/pkg/cataloger/java/test-fixtures/pom/local/child-1/pom.xml b/syft/pkg/cataloger/java/test-fixtures/pom/local/child-1/pom.xml new file mode 100644 index 000000000..63ed7d474 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/pom/local/child-1/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + + + + my.org + parent-one + 3.11.0 + ../parent-1/pom.xml + + + child-one + + ${project.one}.3.6 + jar + + + 3.12.0 + 4.2 + 4.12 + + + + + org.apache.commons + commons-lang3 + + + + diff --git a/syft/pkg/cataloger/java/test-fixtures/pom/local/commons-text-1.10.0/pom.xml b/syft/pkg/cataloger/java/test-fixtures/pom/local/commons-text-1.10.0/pom.xml new file mode 100644 index 000000000..e4ad83f15 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/pom/local/commons-text-1.10.0/pom.xml @@ -0,0 +1,263 @@ + + + + 4.0.0 + + org.apache.commons + commons-parent + 54 + + commons-text + 1.10.0 + Apache Commons Text + Apache Commons Text is a library focused on algorithms working on strings. + https://commons.apache.org/proper/commons-text + + + ISO-8859-1 + UTF-8 + 1.8 + 1.8 + + text + org.apache.commons.text + + 1.10.0 + (Java 8+) + + TEXT + 12318221 + + text + https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-text + site-content + + 5.9.1 + 3.2.0 + 9.3 + + 4.7.2.0 + 4.7.2 + 3.19.0 + 6.49.0 + + 4.8.0 + 0.8.8 + + + 3.10.0 + 3.4.1 + + + 22.0.0.2 + 1.4 + + 0.16.0 + false + + 1.35 + 3.1.2 + + + 1.9 + RC1 + true + scm:svn:https://dist.apache.org/repos/dist/dev/commons/${commons.componentid} + Gary Gregory + 86fdc7e2a11262cb + + + + + org.apache.commons + commons-lang3 + 3.12.0 + + + + org.junit.jupiter + junit-jupiter + test + + + org.assertj + assertj-core + 3.23.1 + test + + + commons-io + commons-io + 2.11.0 + test + + + org.mockito + + mockito-inline + ${commons.mockito.version} + test + + + org.graalvm.js + js + ${graalvm.version} + test + + + org.graalvm.js + js-scriptengine + ${graalvm.version} + test + + + org.apache.commons + commons-rng-simple + ${commons.rng.version} + test + + + org.openjdk.jmh + jmh-core + ${jmh.version} + test + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + test + + + + 2014 + + + scm:git:https://gitbox.apache.org/repos/asf/commons-text + scm:git:https://gitbox.apache.org/repos/asf/commons-text + https://gitbox.apache.org/repos/asf?p=commons-text.git + + + + jira + https://issues.apache.org/jira/browse/TEXT + + + + + apache.website + Apache Commons Site + scm:svn:https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-text/ + + + + + + setup-checkout + + + site-content + + + + + + org.apache.maven.plugins + maven-antrun-plugin + + + prepare-checkout + + run + + pre-site + + + + + + + + + + + + + + + + + + + + + + + + java9+ + + [9,) + + + + true + + + + benchmark + + true + org.apache + + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + benchmark + test + + exec + + + test + java + + -classpath + + org.openjdk.jmh.Main + -rf + json + -rff + target/jmh-result.${benchmark}.json + ${benchmark} + + + + + + + + + + \ No newline at end of file diff --git a/syft/pkg/cataloger/java/test-fixtures/pom/local/contains-child-1/pom.xml b/syft/pkg/cataloger/java/test-fixtures/pom/local/contains-child-1/pom.xml new file mode 100644 index 000000000..18dcd8c4b --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/pom/local/contains-child-1/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + contains-child-one + 5 + jar + + + + + my.org + child-one + 1.3.6 + + + + + + + my.org + child-one + + + + diff --git a/syft/pkg/cataloger/java/test-fixtures/pom/pom.xml b/syft/pkg/cataloger/java/test-fixtures/pom/local/example-java-app-maven/pom.xml similarity index 100% rename from syft/pkg/cataloger/java/test-fixtures/pom/pom.xml rename to syft/pkg/cataloger/java/test-fixtures/pom/local/example-java-app-maven/pom.xml diff --git a/syft/pkg/cataloger/java/test-fixtures/pom/local/parent-1/pom.xml b/syft/pkg/cataloger/java/test-fixtures/pom/local/parent-1/pom.xml new file mode 100644 index 000000000..4a6d1f323 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/pom/local/parent-1/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + + my.org + parent-two + 13.7.8 + ../parent-2/pom.xml + + + parent-one + 3.11.0 + pom + + + + 3.1${project.parent.version}.0 + 4.3 + + + + + + org.apache.commons + commons-lang3 + ${commons.lang3.version} + + + + + + + org.apache.commons + commons-text + ${commons.text.version} + + + org.apache.commons + commons-collections4 + ${commons.collections4.version} + + + junit + junit + ${commons.junit.version} + test + + + + diff --git a/syft/pkg/cataloger/java/test-fixtures/pom/local/parent-2/pom.xml b/syft/pkg/cataloger/java/test-fixtures/pom/local/parent-2/pom.xml new file mode 100644 index 000000000..5ca8cc4a2 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/pom/local/parent-2/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + my.org + parent-two + 13.7.8 + pom + + + 3.14.0 + 4.4 + 1.12.0 + 4.13.2 + 3 + 1 + + + + + Eclipse Public License v2.0 + https://www.eclipse.org/legal/epl-v20.html + + + + + + + org.apache.commons + commons-lang3 + ${commons.lang3.version} + + + org.apache.commons + commons-text + ${commons.text.version} + + + junit + junit + ${commons.junit.version} + test + + + + + + + org.apache.commons + commons-text + ${commons.text.version} + + + org.apache.commons + commons-collections4 + ${commons.collections4.version} + + + junit + junit + ${commons.junit.version} + test + + + + diff --git a/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/my/org/child-one/1.3.6/child-one-1.3.6.pom b/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/my/org/child-one/1.3.6/child-one-1.3.6.pom new file mode 100644 index 000000000..6a72f2fd5 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/my/org/child-one/1.3.6/child-one-1.3.6.pom @@ -0,0 +1,41 @@ + + + 4.0.0 + + + + + my.org + parent-one + 3.11.0 + + + child-one + + ${project.one}.3.6 + jar + + + 3.12.0 + 4.2 + 4.12 + + + + + org.apache.commons + commons-lang3 + + + + diff --git a/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/my/org/child-two/2.1.90/child-two-2.1.90.pom b/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/my/org/child-two/2.1.90/child-two-2.1.90.pom new file mode 100644 index 000000000..62a3592d1 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/my/org/child-two/2.1.90/child-two-2.1.90.pom @@ -0,0 +1,53 @@ + + + 4.0.0 + + + + + my.org + parent-one + 3.11.0 + + + ${project.parent.groupId} + child-two + 2.1.90 + jar + + + 4.2 + 4.12 + my.other.org + + + + + org.apache.commons + commons-lang3 + + + org.apache.commons + commons-math${project.parent.version} + 3.5 + + + org.apache.commons + commons-exec + 1.${commons-exec_subversion} + + + + diff --git a/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/my/org/parent-one/3.11.0/parent-one-3.11.0.pom b/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/my/org/parent-one/3.11.0/parent-one-3.11.0.pom new file mode 100644 index 000000000..4dd7d533f --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/my/org/parent-one/3.11.0/parent-one-3.11.0.pom @@ -0,0 +1,51 @@ + + + 4.0.0 + + my.org + parent-two + 13.7.8 + + + my.org + parent-one + 3.11.0 + pom + + + + 3.1${project.parent.version}.0 + 4.3 + + + + + + org.apache.commons + commons-lang3 + ${commons.lang3.version} + + + + + + + org.apache.commons + commons-text + ${commons.text.version} + + + org.apache.commons + commons-collections4 + ${commons.collections4.version} + + + junit + junit + ${commons.junit.version} + test + + + + diff --git a/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/my/org/parent-two/13.7.8/parent-two-13.7.8.pom b/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/my/org/parent-two/13.7.8/parent-two-13.7.8.pom new file mode 100644 index 000000000..3341e805c --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/my/org/parent-two/13.7.8/parent-two-13.7.8.pom @@ -0,0 +1,67 @@ + + + 4.0.0 + + my.org + parent-two + 13.7.8 + pom + + + + Eclipse Public License v2.0 + https://www.eclipse.org/legal/epl-v20.html + + + + + 3.14.0 + 4.4 + 1.12.0 + 4.13.2 + 3 + 1 + + + + + + org.apache.commons + commons-lang3 + ${commons.lang3.version} + + + org.apache.commons + commons-text + ${commons.text.version} + + + junit + junit + ${commons.junit.version} + test + + + + + + + org.apache.commons + commons-text + ${commons.text.version} + + + org.apache.commons + commons-collections4 + ${commons.collections4.version} + + + junit + junit + ${commons.junit.version} + test + + + + diff --git a/syft/pkg/cataloger/java/test-fixtures/maven-xml-responses/parent-7.11.2.pom b/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/net/shibboleth/parent/7.11.2/parent-7.11.2.pom similarity index 100% rename from syft/pkg/cataloger/java/test-fixtures/maven-xml-responses/parent-7.11.2.pom rename to syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/net/shibboleth/parent/7.11.2/parent-7.11.2.pom diff --git a/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/org/apache/commons/commons-parent/54/commons-parent-54.pom b/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/org/apache/commons/commons-parent/54/commons-parent-54.pom new file mode 100644 index 000000000..3fd66f094 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/org/apache/commons/commons-parent/54/commons-parent-54.pom @@ -0,0 +1,132 @@ + + + + 4.0.0 + + org.apache + apache + 27 + + org.apache.commons + commons-parent + 54 + pom + Apache Commons Parent + The Apache Commons Parent POM provides common settings for all Apache Commons components. + 2006 + https://commons.apache.org/commons-parent-pom.html + + + 3.3.9 + ${project.version} + true + Gary Gregory + 86fdc7e2a11262cb + + 1.3 + 1.3 + false + + + + + 1.22 + 1.0 + 3.4.2 + 3.3.0 + 1.12 + 2.12.1 + 3.2.0 + 9.3 + 2.7 + 3.10.1 + 4.3.0 + EpochMillis + 2.7.1 + 0.5.5 + 5.9.0 + + 3.12.1 + 3.2.1 + 4.7.2.0 + 3.5.2 + + + ${project.artifactId}-${commons.release.version} + + -bin + ${project.artifactId}-${commons.release.2.version} + + -bin + ${project.artifactId}-${commons.release.3.version} + + -bin + + -bin + + + 1.00 + 0.90 + 0.95 + 0.85 + 0.85 + 0.90 + false + + ${project.artifactId} + + ${project.artifactId} + + + org.apache.commons.${commons.packageId} + org.apache.commons.*;version=${project.version};-noimport:=true + * + + + true + + + ${project.build.directory}/osgi/MANIFEST.MF + + scp + + iso-8859-1 + ${commons.encoding} + ${commons.encoding} + ${commons.encoding} + yyyy-MM-dd HH:mm:ssZ + ${scmBranch}@r${buildNumber}; ${maven.build.timestamp} + + + + + + org.junit + junit-bom + ${commons.junit.version} + pom + import + + + + + + + site-basic + + true + true + true + true + true + true + true + true + + + + diff --git a/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/org/junit/junit-bom/5.9.0/junit-bom-5.9.0.pom b/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/org/junit/junit-bom/5.9.0/junit-bom-5.9.0.pom new file mode 100644 index 000000000..eb1b959bc --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/org/junit/junit-bom/5.9.0/junit-bom-5.9.0.pom @@ -0,0 +1,151 @@ + + + 4.0.0 + org.junit + junit-bom + 5.9.0 + pom + + + Eclipse Public License v2.0 + https://www.eclipse.org/legal/epl-v20.html + + + + + bechte + Stefan Bechtold + stefan.bechtold@me.com + + + jlink + Johannes Link + business@johanneslink.net + + + marcphilipp + Marc Philipp + mail@marcphilipp.de + + + mmerdes + Matthias Merdes + matthias.merdes@heidelpay.com + + + sbrannen + Sam Brannen + sam@sambrannen.com + + + sormuras + Christian Stein + sormuras@gmail.com + + + juliette-derancourt + Juliette de Rancourt + derancourt.juliette@gmail.com + + + + scm:git:git://github.com/junit-team/junit5.git + scm:git:git://github.com/junit-team/junit5.git + https://github.com/junit-team/junit5 + + + + + org.junit.jupiter + junit-jupiter + 5.9.0 + + + org.junit.jupiter + junit-jupiter-api + 5.9.0 + + + org.junit.jupiter + junit-jupiter-engine + 5.9.0 + + + org.junit.jupiter + junit-jupiter-migrationsupport + 5.9.0 + + + org.junit.jupiter + junit-jupiter-params + 5.9.0 + + + org.junit.platform + junit-platform-commons + 1.9.0 + + + org.junit.platform + junit-platform-console + 1.9.0 + + + org.junit.platform + junit-platform-engine + 1.9.0 + + + org.junit.platform + junit-platform-jfr + 1.9.0 + + + org.junit.platform + junit-platform-launcher + 1.9.0 + + + org.junit.platform + junit-platform-reporting + 1.9.0 + + + org.junit.platform + junit-platform-runner + 1.9.0 + + + org.junit.platform + junit-platform-suite + 1.9.0 + + + org.junit.platform + junit-platform-suite-api + 1.9.0 + + + org.junit.platform + junit-platform-suite-commons + 1.9.0 + + + org.junit.platform + junit-platform-suite-engine + 1.9.0 + + + org.junit.platform + junit-platform-testkit + 1.9.0 + + + org.junit.vintage + junit-vintage-engine + 5.9.0 + + + + diff --git a/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/org/junit/junit-bom/5.9.1/junit-bom-5.9.1.pom b/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/org/junit/junit-bom/5.9.1/junit-bom-5.9.1.pom new file mode 100644 index 000000000..c21518a39 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/org/junit/junit-bom/5.9.1/junit-bom-5.9.1.pom @@ -0,0 +1,152 @@ + + + 4.0.0 + org.junit + junit-bom + 5.9.1 + pom + JUnit 5 (Bill of Materials) + + + Eclipse Public License v2.0 + https://www.eclipse.org/legal/epl-v20.html + + + + + bechte + Stefan Bechtold + stefan.bechtold@me.com + + + jlink + Johannes Link + business@johanneslink.net + + + marcphilipp + Marc Philipp + mail@marcphilipp.de + + + mmerdes + Matthias Merdes + matthias.merdes@heidelpay.com + + + sbrannen + Sam Brannen + sam@sambrannen.com + + + sormuras + Christian Stein + sormuras@gmail.com + + + juliette-derancourt + Juliette de Rancourt + derancourt.juliette@gmail.com + + + + scm:git:git://github.com/junit-team/junit5.git + scm:git:git://github.com/junit-team/junit5.git + https://github.com/junit-team/junit5 + + + + + org.junit.jupiter + junit-jupiter + 5.9.1 + + + org.junit.jupiter + junit-jupiter-api + 5.9.1 + + + org.junit.jupiter + junit-jupiter-engine + 5.9.1 + + + org.junit.jupiter + junit-jupiter-migrationsupport + 5.9.1 + + + org.junit.jupiter + junit-jupiter-params + 5.9.1 + + + org.junit.platform + junit-platform-commons + 1.9.1 + + + org.junit.platform + junit-platform-console + 1.9.1 + + + org.junit.platform + junit-platform-engine + 1.9.1 + + + org.junit.platform + junit-platform-jfr + 1.9.1 + + + org.junit.platform + junit-platform-launcher + 1.9.1 + + + org.junit.platform + junit-platform-reporting + 1.9.1 + + + org.junit.platform + junit-platform-runner + 1.9.1 + + + org.junit.platform + junit-platform-suite + 1.9.1 + + + org.junit.platform + junit-platform-suite-api + 1.9.1 + + + org.junit.platform + junit-platform-suite-commons + 1.9.1 + + + org.junit.platform + junit-platform-suite-engine + 1.9.1 + + + org.junit.platform + junit-platform-testkit + 1.9.1 + + + org.junit.vintage + junit-vintage-engine + 5.9.1 + + + + diff --git a/syft/pkg/cataloger/java/test-fixtures/maven-xml-responses/opensaml-parent-3.4.6.pom b/syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/org/opensaml/opensaml-parent/3.4.6/opensaml-parent-3.4.6.pom similarity index 100% rename from syft/pkg/cataloger/java/test-fixtures/maven-xml-responses/opensaml-parent-3.4.6.pom rename to syft/pkg/cataloger/java/test-fixtures/pom/maven-repo/org/opensaml/opensaml-parent/3.4.6/opensaml-parent-3.4.6.pom diff --git a/syft/pkg/cataloger/swipl/package.go b/syft/pkg/cataloger/swipl/package.go index 252dda56b..6421ede70 100644 --- a/syft/pkg/cataloger/swipl/package.go +++ b/syft/pkg/cataloger/swipl/package.go @@ -1,8 +1,6 @@ package swipl import ( - // "strings" - "github.com/anchore/packageurl-go" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" diff --git a/syft/pkg/license.go b/syft/pkg/license.go index fb79028ce..ae311a13c 100644 --- a/syft/pkg/license.go +++ b/syft/pkg/license.go @@ -70,7 +70,7 @@ func NewLicenseFromType(value string, t license.Type) License { var err error spdxExpression, err = license.ParseExpression(value) if err != nil { - log.Trace("unable to parse license expression: %w", err) + log.WithFields("error", err, "expression", value).Trace("unable to parse license expression") } } From 703330abd0c72b79702601dacf342c5f47d2340e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 13:07:21 -0400 Subject: [PATCH 126/284] chore(deps): bump github.com/gkampitakis/go-snaps from 0.5.6 to 0.5.7 (#3097) Bumps [github.com/gkampitakis/go-snaps](https://github.com/gkampitakis/go-snaps) from 0.5.6 to 0.5.7. - [Release notes](https://github.com/gkampitakis/go-snaps/releases) - [Commits](https://github.com/gkampitakis/go-snaps/compare/v0.5.6...v0.5.7) --- updated-dependencies: - dependency-name: github.com/gkampitakis/go-snaps dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 87692a0f3..0c2e94755 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/elliotchance/phpserialize v1.4.0 github.com/facebookincubator/nvdtools v0.1.5 github.com/github/go-spdx/v2 v2.3.1 - github.com/gkampitakis/go-snaps v0.5.6 + github.com/gkampitakis/go-snaps v0.5.7 github.com/go-git/go-billy/v5 v5.5.0 github.com/go-git/go-git/v5 v5.12.0 github.com/go-test/deep v1.1.1 diff --git a/go.sum b/go.sum index bd5319c94..5a56059cb 100644 --- a/go.sum +++ b/go.sum @@ -293,8 +293,8 @@ github.com/gkampitakis/ciinfo v0.3.0 h1:gWZlOC2+RYYttL0hBqcoQhM7h1qNkVqvRCV1fOvp github.com/gkampitakis/ciinfo v0.3.0/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk= -github.com/gkampitakis/go-snaps v0.5.6 h1:kAal5JbqTycI+6xeS3K0nPqvNDAxqKX5W3dRXKxIJpA= -github.com/gkampitakis/go-snaps v0.5.6/go.mod h1:ZABkO14uCuVxBHAXAfKG+bqNz+aa1bGPAg8jkI0Nk8Y= +github.com/gkampitakis/go-snaps v0.5.7 h1:uVGjHR4t4pPHU944udMx7VKHpwepZXmvDMF+yDmI0rg= +github.com/gkampitakis/go-snaps v0.5.7/go.mod h1:ZABkO14uCuVxBHAXAfKG+bqNz+aa1bGPAg8jkI0Nk8Y= github.com/glebarez/go-sqlite v1.20.3 h1:89BkqGOXR9oRmG58ZrzgoY/Fhy5x0M+/WV48U5zVrZ4= github.com/glebarez/go-sqlite v1.20.3/go.mod h1:u3N6D/wftiAzIOJtZl6BmedqxmmkDfH3q+ihjqxC9u0= github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= From 0f9df805c195c4e32db4d3f141210737ae1c300b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 13:07:33 -0400 Subject: [PATCH 127/284] chore(deps): bump golang.org/x/mod from 0.19.0 to 0.20.0 (#3096) Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.19.0 to 0.20.0. - [Commits](https://github.com/golang/mod/compare/v0.19.0...v0.20.0) --- updated-dependencies: - dependency-name: golang.org/x/mod dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0c2e94755..f99fd1c28 100644 --- a/go.mod +++ b/go.mod @@ -78,7 +78,7 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1 go.uber.org/goleak v1.3.0 - golang.org/x/mod v0.19.0 + golang.org/x/mod v0.20.0 golang.org/x/net v0.27.0 gopkg.in/yaml.v3 v3.0.1 modernc.org/sqlite v1.31.1 diff --git a/go.sum b/go.sum index 5a56059cb..b4ee9adca 100644 --- a/go.sum +++ b/go.sum @@ -920,8 +920,8 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= From 214a0498e03ac1e855a0a96ebddbf198ee6ec634 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 13:07:48 -0400 Subject: [PATCH 128/284] chore(deps): update CPE dictionary index (#3094) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: wagoodman <590471+wagoodman@users.noreply.github.com> --- .../dictionary/data/cpe-index.json | 137 +++++++++++++++++- 1 file changed, 131 insertions(+), 6 deletions(-) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index b7226416a..54ec320a8 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -4070,6 +4070,9 @@ "netmask": [ "cpe:2.3:a:netmask_project:netmask:*:*:*:*:*:node.js:*:*" ], + "network": [ + "cpe:2.3:a:forkhq:network:*:*:*:*:*:node.js:*:*" + ], "network-manager": [ "cpe:2.3:a:network-manager_project:network-manager:*:*:*:*:*:node.js:*:*" ], @@ -7531,6 +7534,9 @@ "ameliabooking": [ "cpe:2.3:a:tms-outsource:amelia:*:*:*:*:*:wordpress:*:*" ], + "amen": [ + "cpe:2.3:a:amen_project:amen:*:*:*:*:*:*:wordpress:*" + ], "amministrazione-aperta": [ "cpe:2.3:a:amministrazione_aperta_project:amministrazione_aperta:*:*:*:*:*:wordpress:*:*" ], @@ -7579,6 +7585,9 @@ "animated-counters": [ "cpe:2.3:a:eralion:animated_counters:*:*:*:*:*:wordpress:*:*" ], + "anonymous-restricted-content": [ + "cpe:2.3:a:tarassych:anonymous_restricted_content:*:*:*:*:*:wordpress:*:*" + ], "another-wordpress-classifieds-plugin": [ "cpe:2.3:a:awpcp:another_wordpress_classifieds_plugin:*:*:*:*:*:wordpress:*:*" ], @@ -7922,7 +7931,8 @@ "cpe:2.3:a:batch_cat_project:batch_cat:*:*:*:*:*:wordpress:*:*" ], "bb-bootstrap-cards": [ - "cpe:2.3:a:brainstormforce:cards_for_beaver_builder:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:brainstormforce:cards_for_beaver_builder:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:ultimateaddons:cards_for_beaver_builder:*:*:*:*:*:wordpress:*:*" ], "bbp-move-topics": [ "cpe:2.3:a:bbpress_move_topics_project:bbpress_move_topics:*:*:*:*:*:wordpress:*:*" @@ -7980,6 +7990,9 @@ "bestbooks": [ "cpe:2.3:a:presspage:bestbooks:*:*:*:*:*:wordpress:*:*" ], + "better-anchor-links": [ + "cpe:2.3:a:ludek:better_anchor_links:*:*:*:*:*:wordpress:*:*" + ], "better-font-awesome": [ "cpe:2.3:a:better_font_awesome_project:better_font_awesome:*:*:*:*:*:wordpress:*:*" ], @@ -8256,6 +8269,9 @@ "buddypress-media": [ "cpe:2.3:a:rtcamp:rtmedia:*:*:*:*:*:wordpress:*:*" ], + "buddypress-members-only": [ + "cpe:2.3:a:membersonly:buddypress_members_only:*:*:*:*:*:wordpress:*:*" + ], "bug-library": [ "cpe:2.3:a:bug_library_project:bug_library:*:*:*:*:*:wordpress:*:*" ], @@ -8371,6 +8387,9 @@ "calculator-builder": [ "cpe:2.3:a:wow-company:calculator-builder:*:*:*:*:*:wordpress:*:*" ], + "calculatorpro-calculators": [ + "cpe:2.3:a:jgadbois:calculatorpro_calculators:*:*:*:*:*:wordpress:*:*" + ], "caldera-forms": [ "cpe:2.3:a:calderaforms:caldera_forms:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:calderalabs:caldera_forms:*:*:*:*:*:wordpress:*:*" @@ -8379,11 +8398,15 @@ "cpe:2.3:a:kieranoshea:calendar:*:*:*:*:*:wordpress:*:*" ], "calendar-booking": [ - "cpe:2.3:a:startbooking:scheduling_plugin:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:startbooking:scheduling_plugin:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:startbooking:scheduling_plugin_-_online_booking:*:*:*:*:*:wordpress:*:*" ], "calendar-plugin": [ "cpe:2.3:a:calendar_plugin_project:calendar_plugin:*:*:*:*:*:wordpress:*:*" ], + "calendarista-basic-edition": [ + "cpe:2.3:a:typps:calendarista:*:*:*:*:basic:wordpress:*:*" + ], "call-now-button": [ "cpe:2.3:a:callnowbutton:call_now_button:*:*:*:*:*:wordpress:*:*" ], @@ -8944,6 +8967,9 @@ "contact-forms-builder": [ "cpe:2.3:a:wpdevart:contact_form_builder:*:*:*:*:*:wordpress:*:*" ], + "contact-list": [ + "cpe:2.3:a:contactlistpro:contact_list:*:*:*:*:*:wordpress:*:*" + ], "contact-us-page-contact-people": [ "cpe:2.3:a:a3rev:contact_us_page_-_contact_people:*:*:*:*:*:wordpress:*:*" ], @@ -9108,7 +9134,8 @@ "cpe:2.3:a:hasthemes:coupon_zen:*:*:*:*:*:wordpress:*:*" ], "cowidgets-elementor-addons": [ - "cpe:2.3:a:codeless:cowidgets_-_elementor:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:codeless:cowidgets_-_elementor:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:codeless:cowidgets_elementor_addons:*:*:*:*:*:wordpress:*:*" ], "cp-appointment-calendar": [ "cpe:2.3:a:codepeople:cp_appointment_calendar:*:*:*:*:*:wordpress:*:*" @@ -9489,6 +9516,9 @@ "delucks-seo": [ "cpe:2.3:a:delucks:delucks_seo:*:*:*:*:*:wordpress:*:*" ], + "demo-awesome": [ + "cpe:2.3:a:theme4press:demo_awesome:*:*:*:*:*:wordpress:*:*" + ], "democracy-poll": [ "cpe:2.3:a:wp-kama:democracy_poll:*:*:*:*:*:wordpress:*:*" ], @@ -9878,6 +9908,10 @@ "easyappointments": [ "cpe:2.3:a:easyappointments:easy\\!appointments:*:*:*:*:*:wordpress:*:*" ], + "easyazon": [ + "cpe:2.3:a:flowdee:easyazon:*:*:*:*:*:*:*:*", + "cpe:2.3:a:getaawp:easyazon:*:*:*:*:*:wordpress:*:*" + ], "easyjobs": [ "cpe:2.3:a:easy.jobs:easy.jobs:*:*:*:*:*:wordpress:*:*" ], @@ -9950,6 +9984,9 @@ "elegant-custom-fonts": [ "cpe:2.3:a:breakdance:elegant_custom_fonts:*:*:*:*:*:wordpress:*:*" ], + "elegant-themes-icons": [ + "cpe:2.3:a:wpai:elegant_themes_icons:*:*:*:*:*:wordpress:*:*" + ], "element-ready-lite": [ "cpe:2.3:a:quomodosoft:elementsready:*:*:*:*:*:wordpress:*:*" ], @@ -10178,6 +10215,7 @@ "cpe:2.3:a:e-dynamics:events_made_easy:*:*:*:*:*:wordpress:*:*" ], "events-manager": [ + "cpe:2.3:a:pixelite:events_manager:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:wp-events-plugin:events_manager:*:*:*:*:*:wordpress:*:*" ], "ever-compare": [ @@ -10224,7 +10262,8 @@ "cpe:2.3:a:ithemes:ithemes_exchange:*:*:*:*:*:wordpress:*:*" ], "exclusive-addons-for-elementor": [ - "cpe:2.3:a:devscred:exclusive_addons_for_elementor:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:devscred:exclusive_addons_for_elementor:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:exclusiveaddons:exclusive_addons_for_elementor:*:*:*:*:*:wordpress:*:*" ], "exit-intent-popups-by-optimonk": [ "cpe:2.3:a:optimonk:optimonk\\:popups\\,_personalization_\\\u0026_a\\/b_testing:*:*:*:*:*:wordpress:*:*" @@ -10271,6 +10310,9 @@ "extensions-for-cf7": [ "cpe:2.3:a:hasthemes:extensions_for_cf7:*:*:*:*:*:wordpress:*:*" ], + "extensions-for-elementor": [ + "cpe:2.3:a:idioweb:extensions_for_elementor:*:*:*:*:*:wordpress:*:*" + ], "extensive-vc-addon": [ "cpe:2.3:a:wprealize:extensive_vc_addons_for_wpbakery_page_builder:*:*:*:*:*:wordpress:*:*" ], @@ -11379,6 +11421,9 @@ "iframe": [ "cpe:2.3:a:iframe_project:iframe:*:*:*:*:*:wordpress:*:*" ], + "iframe-forms": [ + "cpe:2.3:a:jrbecart:iframe_forms:*:*:*:*:*:wordpress:*:*" + ], "iframe-shortcode": [ "cpe:2.3:a:jacksonwhelan:iframe_shortcode:*:*:*:*:*:wordpress:*:*" ], @@ -11471,7 +11516,8 @@ "cpe:2.3:a:imagestowebp_project:images_to_webp:*:*:*:*:*:wordpress:*:*" ], "imageseo": [ - "cpe:2.3:a:imageseo:optimize_images_alt_text_\\(alt_tag\\)_\\\u0026_names_for_seo_using_ai:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:imageseo:optimize_images_alt_text_\\(alt_tag\\)_\\\u0026_names_for_seo_using_ai:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpchill:optimize_images_alt_text_\\(alt_tag\\)_\\\u0026_names_for_seo_using_ai:*:*:*:*:*:wordpress:*:*" ], "imdb-info-box": [ "cpe:2.3:a:99webtools:imdb_info_box:*:*:*:*:*:wordpress:*:*" @@ -11592,7 +11638,8 @@ "cpe:2.3:a:getnet_argentina_para_woocommerce_project:getnet_argentina_para_woocommerce:*:*:*:*:*:wordpress:*:*" ], "integrate-google-drive": [ - "cpe:2.3:a:softlabbd:integrate_google_drive:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:softlabbd:integrate_google_drive:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:softlabdb:integrate_google_drive:*:*:*:*:*:wordpress:*:*" ], "integration-for-billingo-gravity-forms": [ "cpe:2.3:a:integration_for_billingo_\\\u0026_gravity_forms_project:integration_for_billingo_\\\u0026_gravity_forms:*:*:*:*:*:wordpress:*:*" @@ -11603,6 +11650,9 @@ "integration-for-szamlazzhu-woocommerce": [ "cpe:2.3:a:visztpeter:integration_for_szamlazz.hu_\\\u0026_woocommerce:*:*:*:*:*:wordpress:*:*" ], + "intelly-related-posts": [ + "cpe:2.3:a:data443:inline_related_posts:*:*:*:*:*:wordpress:*:*" + ], "interactive-3d-flipbook-powered-physics-engine": [ "cpe:2.3:a:3dflipbook:3d_flipbook:*:*:*:*:*:wordpress:*:*" ], @@ -12013,6 +12063,9 @@ "license-manager-for-woocommerce": [ "cpe:2.3:a:wpexperts:license_manager_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], + "lifeline-donation": [ + "cpe:2.3:a:webinane:lifeline_donation:*:*:*:*:*:wordpress:*:*" + ], "lifterlms": [ "cpe:2.3:a:lifterlms:lifterlms:*:*:*:*:*:wordpress:*:*" ], @@ -13300,6 +13353,9 @@ "pdf-viewer-block": [ "cpe:2.3:a:gutenberg_pdf_viewer_block_project:gutenberg_pdf_viewer_block:*:*:*:*:*:wordpress:*:*" ], + "pdf-viewer-for-elementor": [ + "cpe:2.3:a:redlettuce:pdf_viewer_for_elementor:*:*:*:*:*:wordpress:*:*" + ], "pdf24-posts-to-pdf": [ "cpe:2.3:a:pdf24_articles_to_pdf_project:pdf24_articles_to_pdf:*:*:*:*:*:wordpress:*:*" ], @@ -13678,6 +13734,9 @@ "powerpress": [ "cpe:2.3:a:blubrry:powerpress:*:*:*:*:*:wordpress:*:*" ], + "pray-for-me": [ + "cpe:2.3:a:projectcaruso:pray_for_me:*:*:*:*:*:wordpress:*:*" + ], "pre-orders-for-woocommerce": [ "cpe:2.3:a:brightplugins:pre-orders_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], @@ -13704,6 +13763,9 @@ "pressforward": [ "cpe:2.3:a:pressforward:pressforward:*:*:*:*:*:wordpress:*:*" ], + "prettyphoto": [ + "cpe:2.3:a:master-addons:prettyphoto:*:*:*:*:*:wordpress:*:*" + ], "preview-link-generator": [ "cpe:2.3:a:hasthemes:preview_link_generator:*:*:*:*:*:wordpress:*:*" ], @@ -13817,6 +13879,9 @@ "promobar": [ "cpe:2.3:a:bestwebsoft:promobar:*:*:*:*:*:wordpress:*:*" ], + "promolayer-popup-builder": [ + "cpe:2.3:a:promolayer:popup_builder:*:*:*:*:*:wordpress:*:*" + ], "promotion-slider": [ "cpe:2.3:a:promotion_slider_project:promotion_slider:*:*:*:*:*:wordpress:*:*" ], @@ -14295,6 +14360,9 @@ "roomcloud": [ "cpe:2.3:a:roomcloud:roomcloud:*:*:*:*:*:wordpress:*:*" ], + "rotatingtweets": [ + "cpe:2.3:a:martintod:rotating_tweets:*:*:*:*:*:wordpress:*:*" + ], "rough-chart": [ "cpe:2.3:a:rough_chart_project:rough_chart:*:*:*:*:*:wordpress:*:*" ], @@ -14666,6 +14734,9 @@ "show-posts": [ "cpe:2.3:a:weavertheme:weaver_show_posts:*:*:*:*:*:wordpress:*:*" ], + "show-website-content-in-wordpress-page-or-post": [ + "cpe:2.3:a:matteoenna:website_content_in_page_or_post:*:*:*:*:*:wordpress:*:*" + ], "si-contact-form": [ "cpe:2.3:a:fast_secure_contact_form_project:fast_secure_contact_form:*:*:*:*:*:wordpress:*:*" ], @@ -14694,6 +14765,9 @@ "similar-posts": [ "cpe:2.3:a:shareaholic:similar_posts:*:*:*:*:*:wordpress:*:*" ], + "similarity": [ + "cpe:2.3:a:davidjmiller:similarity:*:*:*:*:*:wordpress:*:*" + ], "simple-301-redirects-addon-bulk-uploader": [ "cpe:2.3:a:webcraftic:simple_301_redirects-addon-bulk_uploader:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:webcraftic:simple_301_redirects:*:*:*:*:*:wordpress:*:*" @@ -14776,6 +14850,9 @@ "simple-image-manipulator": [ "cpe:2.3:a:simple-image-manipulator_project:simple-image-manipulator:*:*:*:*:*:wordpress:*:*" ], + "simple-image-popup-shortcode": [ + "cpe:2.3:a:purvabathe:simple_image_popup_shortcode:*:*:*:*:*:wordpress:*:*" + ], "simple-ip-ban": [ "cpe:2.3:a:ip_ban_project:ip_ban:*:*:*:*:*:wordpress:*:*" ], @@ -14801,6 +14878,9 @@ "simple-matted-thumbnails": [ "cpe:2.3:a:devondev:simple_matted_thumbnails:*:*:*:*:*:wordpress:*:*" ], + "simple-media-directory": [ + "cpe:2.3:a:quantumcloud:simple_video_directory:*:*:*:*:*:wordpress:*:*" + ], "simple-membership": [ "cpe:2.3:a:simple-membership-plugin:simple_membership:*:*:*:*:*:wordpress:*:*" ], @@ -14899,6 +14979,9 @@ "simple-youtube-responsive": [ "cpe:2.3:a:simple_youtube_responsive_project:simple_youtube_responsive:*:*:*:*:*:wordpress:*:*" ], + "simplemap": [ + "cpe:2.3:a:simplemap-plugin:simplemap_store_locator:*:*:*:*:*:wordpress:*:*" + ], "simplemodal-contact-form-smcf": [ "cpe:2.3:a:simplemodal_contact_form_project:simplemodal_contact_form:*:*:*:*:*:wordpress:*:*" ], @@ -14978,6 +15061,9 @@ "sketchfab-oembed": [ "cpe:2.3:a:generatewp:sketchfab_embed:*:*:*:*:*:wordpress:*:*" ], + "skype-online-status": [ + "cpe:2.3:a:ravanh:skype_legacy_buttons:*:*:*:*:*:wordpress:*:*" + ], "sliced-invoices": [ "cpe:2.3:a:slicedinvoices:sliced_invoices:*:*:*:*:*:wordpress:*:*" ], @@ -15068,6 +15154,9 @@ "smart-slider-3": [ "cpe:2.3:a:nextendweb:smart_slider_3:*:*:*:*:*:wordpress:*:*" ], + "smart-wishlist-for-more-convert": [ + "cpe:2.3:a:moreconvert:woocommerce_wishlist:*:*:*:*:*:wordpress:*:*" + ], "smart-youtube": [ "cpe:2.3:a:smart_youtube_pro_project:smart_youtube_pro:*:*:*:*:*:wordpress:*:*" ], @@ -15143,6 +15232,9 @@ "social-photo-gallery": [ "cpe:2.3:a:infoway:social_photo_gallery:*:*:*:*:*:wordpress:*:*" ], + "social-pixel": [ + "cpe:2.3:a:labschool:social_pixel:*:*:*:*:*:*:wordpress:*" + ], "social-proof-testimonials-slider": [ "cpe:2.3:a:brandid:social_proof_\\(testimonial\\)_slider:*:*:*:*:*:wordpress:*:*" ], @@ -15291,12 +15383,18 @@ "stars-rating": [ "cpe:2.3:a:stars_rating_project:stars_rating:*:*:*:*:*:wordpress:*:*" ], + "startklar-elmentor-forms-extwidgets": [ + "cpe:2.3:a:web-shop-host:startklar_elmentor_addons:*:*:*:*:*:wordpress:*:*" + ], "stats-counter": [ "cpe:2.3:a:analytics_stats_counter_statistics_project:analytics_stats_counter_statistics:*:*:*:*:*:wordpress:*:*" ], "stax-addons-for-elementor": [ "cpe:2.3:a:staxwp:stax:*:*:*:*:*:wordpress:*:*" ], + "stellissimo-text-box": [ + "cpe:2.3:a:overclokk:stellissimo_text_box:*:*:*:*:*:wordpress:*:*" + ], "stetic": [ "cpe:2.3:a:stetic:stetic:*:*:*:*:*:wordpress:*:*" ], @@ -15454,6 +15552,9 @@ "svg-vector-icon-plugin": [ "cpe:2.3:a:wp_svg_icons_project:wp_svg_icons:*:*:*:*:*:wordpress:*:*" ], + "svgmagic": [ + "cpe:2.3:a:andibauer:svgmagic:*:*:*:*:*:wordpress:*:*" + ], "swatchly": [ "cpe:2.3:a:hasthemes:swatchly:*:*:*:*:*:wordpress:*:*" ], @@ -16211,6 +16312,9 @@ "video-thumbnails": [ "cpe:2.3:a:video_thumbnails_project:video_thumbnails:*:*:*:*:*:wordpress:*:*" ], + "video-widget": [ + "cpe:2.3:a:nikodev:video_widget:*:*:*:*:*:wordpress:*:*" + ], "videojs-html5-player": [ "cpe:2.3:a:wphowto:videojs_html5_player:*:*:*:*:*:wordpress:*:*" ], @@ -16394,6 +16498,9 @@ "weather-effect": [ "cpe:2.3:a:awplife:weather_effect:*:*:*:*:*:wordpress:*:*" ], + "weather-in-any-city-widget": [ + "cpe:2.3:a:eltiempoen:weather_widget_pro:*:*:*:*:*:wordpress:*:*" + ], "weaverx-theme-support": [ "cpe:2.3:a:weavertheme:weaver_xtreme_theme_support:*:*:*:*:*:wordpress:*:*" ], @@ -16492,6 +16599,9 @@ "whatshelp-chat-button": [ "cpe:2.3:a:getbutton:chat_button:*:*:*:*:*:wordpress:*:*" ], + "wheel-of-life": [ + "cpe:2.3:a:kraftplugins:wheel_of_life:*:*:*:*:*:wordpress:*:*" + ], "which-template-file": [ "cpe:2.3:a:gillesdumas:which_template_file:*:*:*:*:*:wordpress:*:*" ], @@ -16573,6 +16683,9 @@ "woo-altcoin-payment-gateway": [ "cpe:2.3:a:coinmarketstats:bitcoin_\\/_altcoin_payment_gateway_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], + "woo-auto-coupons": [ + "cpe:2.3:a:richardlerma:auto_coupons_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], "woo-badge-designer-lite": [ "cpe:2.3:a:accesspressthemes:badge_designer_lite_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], @@ -17544,6 +17657,9 @@ "wp-logo-showcase": [ "cpe:2.3:a:radiustheme:logo_slider_and_showcase:*:*:*:*:*:wordpress:*:*" ], + "wp-logs-book": [ + "cpe:2.3:a:onetarek:wp_logs_book:*:*:*:*:*:wordpress:*:*" + ], "wp-mail": [ "cpe:2.3:a:wp_mail_project:wp_mail:*:*:*:*:*:wordpress:*:*" ], @@ -17747,6 +17863,9 @@ "wp-publications": [ "cpe:2.3:a:wp-publications_project:wp-publications:*:*:*:*:*:wordpress:*:*" ], + "wp-quicklatex": [ + "cpe:2.3:a:holoborodko:wp_quicklatex:*:*:*:*:*:wordpress:*:*" + ], "wp-radio": [ "cpe:2.3:a:wpmilitary:wp_radio:*:*:*:*:*:wordpress:*:*" ], @@ -17809,6 +17928,9 @@ "wp-scrippets": [ "cpe:2.3:a:wp_scrippets_project:wp_scrippets:*:*:*:*:*:wordpress:*:*" ], + "wp-secure-maintainance": [ + "cpe:2.3:a:wpexperts:wp_secure_maintenance:*:*:*:*:*:wordpress:*:*" + ], "wp-security-hardening": [ "cpe:2.3:a:getastra:wp_hardening:*:*:*:*:*:wordpress:*:*" ], @@ -18735,6 +18857,9 @@ "newsmag": [ "cpe:2.3:a:machothemes:newsmag:*:*:*:*:*:wordpress:*:*" ], + "newspaper": [ + "cpe:2.3:a:tagdiv:newspaper:*:*:*:*:*:wordpress:*:*" + ], "newspaper-x": [ "cpe:2.3:a:colorlib:newspaper_x:*:*:*:*:*:wordpress:*:*" ], From dcd87d1fef4083285f23831ef384469f0a5f625b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 13:17:36 -0400 Subject: [PATCH 129/284] chore(deps): bump actions/upload-artifact from 4.3.4 to 4.3.5 (#3095) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.4 to 4.3.5. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/0b2256b8c012f0828dc542b3febcab082c67f72b...89ef406dd8d7e03cfd12d9e0a4a378f454709029) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/benchmark-testing.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/benchmark-testing.yaml b/.github/workflows/benchmark-testing.yaml index 7cdf9b4b8..c47908195 100644 --- a/.github/workflows/benchmark-testing.yaml +++ b/.github/workflows/benchmark-testing.yaml @@ -39,7 +39,7 @@ jobs: OUTPUT="${OUTPUT//$'\r'/'%0D'}" # URL encode all '\r' characters echo "result=$OUTPUT" >> $GITHUB_OUTPUT - - uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 + - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5 with: name: benchmark-test-results path: test/results/**/* From 040b683da8489e9bb6317775ef74f888ab13d8b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 14:25:28 -0400 Subject: [PATCH 130/284] chore(deps): bump golang.org/x/net from 0.27.0 to 0.28.0 (#3104) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.27.0 to 0.28.0. - [Commits](https://github.com/golang/net/compare/v0.27.0...v0.28.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index f99fd1c28..87e95130b 100644 --- a/go.mod +++ b/go.mod @@ -79,7 +79,7 @@ require ( github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1 go.uber.org/goleak v1.3.0 golang.org/x/mod v0.20.0 - golang.org/x/net v0.27.0 + golang.org/x/net v0.28.0 gopkg.in/yaml.v3 v3.0.1 modernc.org/sqlite v1.31.1 ) @@ -230,11 +230,11 @@ require ( go.opentelemetry.io/otel/trace v1.19.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect - golang.org/x/crypto v0.25.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/term v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.23.0 // indirect + golang.org/x/term v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect diff --git a/go.sum b/go.sum index b4ee9adca..246f0d270 100644 --- a/go.sum +++ b/go.sum @@ -878,8 +878,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -968,8 +968,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1000,8 +1000,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1081,15 +1081,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1102,8 +1102,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 47d192d79b3e8e12a81d200fe3143795243e7f6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 14:25:36 -0400 Subject: [PATCH 131/284] chore(deps): bump github.com/google/go-containerregistry (#3103) Bumps [github.com/google/go-containerregistry](https://github.com/google/go-containerregistry) from 0.20.1 to 0.20.2. - [Release notes](https://github.com/google/go-containerregistry/releases) - [Changelog](https://github.com/google/go-containerregistry/blob/main/.goreleaser.yml) - [Commits](https://github.com/google/go-containerregistry/compare/v0.20.1...v0.20.2) --- updated-dependencies: - dependency-name: github.com/google/go-containerregistry dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 87e95130b..9616db041 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/go-git/go-git/v5 v5.12.0 github.com/go-test/deep v1.1.1 github.com/google/go-cmp v0.6.0 - github.com/google/go-containerregistry v0.20.1 + github.com/google/go-containerregistry v0.20.2 github.com/google/licensecheck v0.3.1 github.com/google/uuid v1.6.0 github.com/gookit/color v1.5.4 @@ -125,7 +125,7 @@ require ( github.com/containerd/typeurl/v2 v2.1.1 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/docker/cli v27.0.3+incompatible // indirect + github.com/docker/cli v27.1.1+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-connections v0.4.0 // indirect diff --git a/go.sum b/go.sum index 246f0d270..45ffa2b0d 100644 --- a/go.sum +++ b/go.sum @@ -227,8 +227,8 @@ github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da/go.mod h1:B3tI9iGHi4i github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/cli v27.0.3+incompatible h1:usGs0/BoBW8MWxGeEtqPMkzOY56jZ6kYlSN5BLDioCQ= -github.com/docker/cli v27.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2oNn0GkeZE= +github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= @@ -384,8 +384,8 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.20.1 h1:eTgx9QNYugV4DN5mz4U8hiAGTi1ybXn0TPi4Smd8du0= -github.com/google/go-containerregistry v0.20.1/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI= +github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo= +github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/licensecheck v0.3.1 h1:QoxgoDkaeC4nFrtGN1jV7IPmDCHFNIVh54e5hSt6sPs= github.com/google/licensecheck v0.3.1/go.mod h1:ORkR35t/JjW+emNKtfJDII0zlciG9JgbT7SmsohlHmY= From 903159264954148fdefa125c45b0a0709555dcf3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 14:25:44 -0400 Subject: [PATCH 132/284] chore(deps): bump actions/upload-artifact from 4.3.5 to 4.3.6 (#3102) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.5 to 4.3.6. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/89ef406dd8d7e03cfd12d9e0a4a378f454709029...834a144ee995460fba8ed112a2fc961b36a5ec5a) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/benchmark-testing.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/benchmark-testing.yaml b/.github/workflows/benchmark-testing.yaml index c47908195..8284d8264 100644 --- a/.github/workflows/benchmark-testing.yaml +++ b/.github/workflows/benchmark-testing.yaml @@ -39,7 +39,7 @@ jobs: OUTPUT="${OUTPUT//$'\r'/'%0D'}" # URL encode all '\r' characters echo "result=$OUTPUT" >> $GITHUB_OUTPUT - - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5 + - uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 with: name: benchmark-test-results path: test/results/**/* From 2339743c8cb6c455d07449e399efeb67c5729d25 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 14:25:52 -0400 Subject: [PATCH 133/284] chore(deps): bump github/codeql-action from 3.25.15 to 3.26.0 (#3101) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.15 to 3.26.0. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/afb54ba388a7dca6ecae48f608c4ff05ff4cc77a...eb055d739abdc2e8de2e5f4ba1a8b246daa779aa) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d15a2c997..46fc84963 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a #v3.25.15 + uses: github/codeql-action/init@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa #v3.26.0 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a #v3.25.15 + uses: github/codeql-action/autobuild@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa #v3.26.0 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a #v3.25.15 + uses: github/codeql-action/analyze@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa #v3.26.0 From 1fb47d908eb0ac353a7395c3269291f02b13135e Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 14:26:05 -0400 Subject: [PATCH 134/284] chore(deps): update tools to latest versions (#3099) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index ac2f4cc10..42ea5c760 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -42,7 +42,7 @@ tools: # used for signing the checksums file at release - name: cosign version: - want: v2.3.0 + want: v2.4.0 method: github-release with: repo: sigstore/cosign From 6267d69930aec2b66524f83a6a2a04525846c425 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Aug 2024 15:49:37 -0400 Subject: [PATCH 135/284] chore(deps): bump sigstore/cosign-installer from 3.5.0 to 3.6.0 (#3107) Bumps [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) from 3.5.0 to 3.6.0. - [Release notes](https://github.com/sigstore/cosign-installer/releases) - [Commits](https://github.com/sigstore/cosign-installer/compare/v3.5.0...v3.6.0) --- updated-dependencies: - dependency-name: sigstore/cosign-installer dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/validations.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validations.yaml b/.github/workflows/validations.yaml index f54771d9b..669d8b8c5 100644 --- a/.github/workflows/validations.yaml +++ b/.github/workflows/validations.yaml @@ -188,7 +188,7 @@ jobs: runs-on: macos-latest steps: - name: Install Cosign - uses: sigstore/cosign-installer@v3.5.0 + uses: sigstore/cosign-installer@v3.6.0 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 From 64a9ecbf7a94336710f2fa886ebd66fcc819b8df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Aug 2024 15:49:45 -0400 Subject: [PATCH 136/284] chore(deps): bump modernc.org/sqlite from 1.31.1 to 1.32.0 (#3106) Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.31.1 to 1.32.0. - [Commits](https://gitlab.com/cznic/sqlite/compare/v1.31.1...v1.32.0) --- updated-dependencies: - dependency-name: modernc.org/sqlite dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9616db041..56b075e10 100644 --- a/go.mod +++ b/go.mod @@ -81,7 +81,7 @@ require ( golang.org/x/mod v0.20.0 golang.org/x/net v0.28.0 gopkg.in/yaml.v3 v3.0.1 - modernc.org/sqlite v1.31.1 + modernc.org/sqlite v1.32.0 ) require google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect diff --git a/go.sum b/go.sum index 45ffa2b0d..15800d2ab 100644 --- a/go.sum +++ b/go.sum @@ -1379,8 +1379,8 @@ modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= -modernc.org/sqlite v1.31.1 h1:XVU0VyzxrYHlBhIs1DiEgSl0ZtdnPtbLVy8hSkzxGrs= -modernc.org/sqlite v1.31.1/go.mod h1:UqoylwmTb9F+IqXERT8bW9zzOWN8qwAIcLdzeBZs4hA= +modernc.org/sqlite v1.32.0 h1:6BM4uGza7bWypsw4fdLRsLxut6bHe4c58VeqjRgST8s= +modernc.org/sqlite v1.32.0/go.mod h1:UqoylwmTb9F+IqXERT8bW9zzOWN8qwAIcLdzeBZs4hA= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= From 19cc664cf8e7020dd692a62efcbba98ab670bde9 Mon Sep 17 00:00:00 2001 From: Weston Steimel Date: Fri, 9 Aug 2024 10:14:10 +0000 Subject: [PATCH 137/284] test: increase java purl generation test coverage (#3110) ensures correct package url generation for more java packages now that syft has more deterministic results per https://github.com/anchore/syft/pull/3085 Signed-off-by: Weston Steimel --- .../test/integration/java_purl_test.go | 198 +++++++----------- 1 file changed, 72 insertions(+), 126 deletions(-) diff --git a/cmd/syft/internal/test/integration/java_purl_test.go b/cmd/syft/internal/test/integration/java_purl_test.go index a7adbc396..d63675222 100644 --- a/cmd/syft/internal/test/integration/java_purl_test.go +++ b/cmd/syft/internal/test/integration/java_purl_test.go @@ -51,138 +51,84 @@ var noAssertion = map[string]string{ "/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar": "pkg:maven/sdk/sdk@3.0", // syft generates incorrect purls - "/packages/akka-actor_2.13-2.6.6.jar": "pkg:maven/com.typesafe.akka/akka-actor_2.13@2.6.6", - "/packages/akka-management-cluster-bootstrap_2.13-1.2.0.jar": "pkg:maven/com.lightbend.akka.management/akka-management-cluster-bootstrap_2.13@1.2.0", - "/packages/hudson.war:WEB-INF/lib/asm-2.2.3.jar": "pkg:maven/asm/asm@2.2.3", - "/packages/hudson.war:WEB-INF/lib/asm-commons-2.2.3.jar": "pkg:maven/asm/asm-commons@2.2.3", - "/packages/hudson.war:WEB-INF/lib/asm-tree-2.2.3.jar": "pkg:maven/asm/asm-tree@2.2.3", - "/packages/hudson.war:WEB-INF/slave.jar": "pkg:maven/org.jvnet.hudson.main/remoting@1.390", - "/packages/hudson.war:WEB-INF/lib/xpp3_min-1.1.4c.jar": "pkg:maven/xpp3_min/xpp3_min@1.1.4c", - "/packages/hudson.war:WEB-INF/lib/xpp3-1.1.4c.jar": "pkg:maven/xpp3/xpp3@1.1.4c", - "/packages/hudson.war:WEB-INF/hudson-cli.jar": "pkg:maven/org.jvnet.hudson.main/hudson-cli@1.390", - "/packages/hudson.war:WEB-INF/lib/dom4j-1.6.1-hudson-3.jar": "pkg:maven/org.jvnet.hudson.dom4j/dom4j@1.6.1-hudson-3", - "/packages/xpp3_min-1.1.4c.jar": "pkg:maven/xpp3/xpp3_min@1.1.4c", - - // syft generates an unstable purl - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-auth": "pkg:maven/org.apache.dubbo/dubbo-auth@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-cluster": "pkg:maven/org.apache.dubbo/dubbo-cluster@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-common": "pkg:maven/org.apache.dubbo/dubbo-common@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-compatible": "pkg:maven/org.apache.dubbo/dubbo-compatible@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-config-api": "pkg:maven/org.apache.dubbo/dubbo-config-api@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-config-spring": "pkg:maven/org.apache.dubbo/dubbo-config-spring@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-configcenter-apollo": "pkg:maven/org.apache.dubbo/dubbo-configcenter-apollo@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-configcenter-nacos": "pkg:maven/org.apache.dubbo/dubbo-configcenter-nacos@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-configcenter-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-configcenter-zookeeper@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-container-api": "pkg:maven/org.apache.dubbo/dubbo-container-api@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-container-spring": "pkg:maven/org.apache.dubbo/dubbo-container-spring@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-filter-cache": "pkg:maven/org.apache.dubbo/dubbo-filter-cache@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-filter-validation": "pkg:maven/org.apache.dubbo/dubbo-filter-validation@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-kubernetes": "pkg:maven/org.apache.dubbo/dubbo-kubernetes@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-api": "pkg:maven/org.apache.dubbo/dubbo-metadata-api@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-definition-protobuf": "pkg:maven/org.apache.dubbo/dubbo-metadata-definition-protobuf@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-report-nacos": "pkg:maven/org.apache.dubbo/dubbo-metadata-report-nacos@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-report-redis": "pkg:maven/org.apache.dubbo/dubbo-metadata-report-redis@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-report-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-metadata-report-zookeeper@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metrics-api": "pkg:maven/org.apache.dubbo/dubbo-metrics-api@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metrics-prometheus": "pkg:maven/org.apache.dubbo/dubbo-metrics-prometheus@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-monitor-api": "pkg:maven/org.apache.dubbo/dubbo-monitor-api@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-monitor-default": "pkg:maven/org.apache.dubbo/dubbo-monitor-default@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-qos": "pkg:maven/org.apache.dubbo/dubbo-qos@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-reactive": "pkg:maven/org.apache.dubbo/dubbo-reactive@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-api": "pkg:maven/org.apache.dubbo/dubbo-registry-api@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-multicast": "pkg:maven/org.apache.dubbo/dubbo-registry-multicast@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-multiple": "pkg:maven/org.apache.dubbo/dubbo-registry-multiple@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-nacos": "pkg:maven/org.apache.dubbo/dubbo-registry-nacos@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-registry-zookeeper@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-api": "pkg:maven/org.apache.dubbo/dubbo-remoting-api@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-http": "pkg:maven/org.apache.dubbo/dubbo-remoting-http@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-netty": "pkg:maven/org.apache.dubbo/dubbo-remoting-netty@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-netty4": "pkg:maven/org.apache.dubbo/dubbo-remoting-netty4@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-remoting-zookeeper@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-zookeeper-curator5": "pkg:maven/org.apache.dubbo/dubbo-remoting-zookeeper-curator5@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-api": "pkg:maven/org.apache.dubbo/dubbo-rpc-api@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-dubbo": "pkg:maven/org.apache.dubbo/dubbo-rpc-dubbo@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-grpc": "pkg:maven/org.apache.dubbo/dubbo-rpc-grpc@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-injvm": "pkg:maven/org.apache.dubbo/dubbo-rpc-injvm@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-rest": "pkg:maven/org.apache.dubbo/dubbo-rpc-rest@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-triple": "pkg:maven/org.apache.dubbo/dubbo-rpc-triple@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-api": "pkg:maven/org.apache.dubbo/dubbo-serialization-api@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-fastjson2": "pkg:maven/org.apache.dubbo/dubbo-serialization-fastjson2@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-hessian2": "pkg:maven/org.apache.dubbo/dubbo-serialization-hessian2@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-jdk": "pkg:maven/org.apache.dubbo/dubbo-serialization-jdk@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-xds": "pkg:maven/org.apache.dubbo/dubbo-xds@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo": "pkg:maven/org.apache.dubbo/dubbo@3.1.4", - "/packages/dubbo-3.1.4.jar": "pkg:maven/org.apache.dubbo/dubbo@3.1.4", + "/packages/hudson.war:WEB-INF/lib/asm-2.2.3.jar": "pkg:maven/asm/asm@2.2.3", + "/packages/hudson.war:WEB-INF/lib/asm-commons-2.2.3.jar": "pkg:maven/asm/asm-commons@2.2.3", + "/packages/hudson.war:WEB-INF/lib/asm-tree-2.2.3.jar": "pkg:maven/asm/asm-tree@2.2.3", + "/packages/hudson.war:WEB-INF/slave.jar": "pkg:maven/org.jvnet.hudson.main/remoting@1.390", + "/packages/hudson.war:WEB-INF/lib/xpp3_min-1.1.4c.jar": "pkg:maven/xpp3_min/xpp3_min@1.1.4c", + "/packages/hudson.war:WEB-INF/lib/xpp3-1.1.4c.jar": "pkg:maven/xpp3/xpp3@1.1.4c", + "/packages/hudson.war:WEB-INF/hudson-cli.jar": "pkg:maven/org.jvnet.hudson.main/hudson-cli@1.390", + "/packages/hudson.war:WEB-INF/lib/dom4j-1.6.1-hudson-3.jar": "pkg:maven/org.jvnet.hudson.dom4j/dom4j@1.6.1-hudson-3", + "/packages/xpp3_min-1.1.4c.jar": "pkg:maven/xpp3/xpp3_min@1.1.4c", } // Constructed by: // syft anchore/test_images:java-1abc58f -o json | jq -r '.artifacts.[] | [.metadata.virtualPath, .purl, ""] | @csv' | grep 'pkg:maven' | sort | uniq >> /tmp/java_artifacts_mapping.txt // The map was then hand-edited for correctness by comparing to Maven Central. var expectedPURLs = map[string]string{ - "/packages/activemq-client-5.18.2.jar": "pkg:maven/org.apache.activemq/activemq-client@5.18.2", - "/packages/activemq-protobuf-1.1.jar": "pkg:maven/org.apache.activemq.protobuf/activemq-protobuf@1.1", - // "/packages/akka-actor_2.13-2.6.6.jar": "pkg:maven/com.typesafe.akka/akka-actor_2.13@2.6.6", - // "/packages/akka-management-cluster-bootstrap_2.13-1.2.0.jar": "pkg:maven/com.lightbend.akka.management/akka-management-cluster-bootstrap_2.13@1.2.0", - "/packages/ant-1.10.3.jar": "pkg:maven/org.apache.ant/ant@1.10.3", - "/packages/apache-chainsaw-2.1.0.jar": "pkg:maven/log4j/apache-chainsaw@2.1.0", - "/packages/apache-log4j-extras-1.1.jar": "pkg:maven/log4j/apache-log4j-extras@1.1", - "/packages/apoc-4.4.0.11.jar": "pkg:maven/org.neo4j.procedure/apoc@4.4.0.11", - "/packages/bc-fips-1.0.2.3.jar": "pkg:maven/org.bouncycastle/bc-fips@1.0.2.3", - "/packages/camel-core-3.1.0.jar": "pkg:maven/org.apache.camel/camel-core@3.1.0", - "/packages/cassandra-all-4.1.1.jar": "pkg:maven/org.apache.cassandra/cassandra-all@4.1.1", - "/packages/commons-logging-1.1.1.jar": "pkg:maven/commons-logging/commons-logging@1.1.1", - "/packages/commons-vfs-1.0.jar": "pkg:maven/commons-vfs/commons-vfs@1.0", - "/packages/cxf-rt-transports-http-2.7.3.jar": "pkg:maven/org.apache.cxf/cxf-rt-transports-http@2.7.3", - "/packages/dubbo-3.1.4.jar:com.alibaba:hessian-lite": "pkg:maven/com.alibaba/hessian-lite@3.2.13", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-auth": "pkg:maven/org.apache.dubbo/dubbo-auth@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-cluster": "pkg:maven/org.apache.dubbo/dubbo-cluster@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-common": "pkg:maven/org.apache.dubbo/dubbo-common@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-compatible": "pkg:maven/org.apache.dubbo/dubbo-compatible@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-config-api": "pkg:maven/org.apache.dubbo/dubbo-config-api@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-config-spring": "pkg:maven/org.apache.dubbo/dubbo-config-spring@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-configcenter-apollo": "pkg:maven/org.apache.dubbo/dubbo-configcenter-apollo@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-configcenter-nacos": "pkg:maven/org.apache.dubbo/dubbo-configcenter-nacos@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-configcenter-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-configcenter-zookeeper@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-container-api": "pkg:maven/org.apache.dubbo/dubbo-container-api@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-container-spring": "pkg:maven/org.apache.dubbo/dubbo-container-spring@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-filter-cache": "pkg:maven/org.apache.dubbo/dubbo-filter-cache@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-filter-validation": "pkg:maven/org.apache.dubbo/dubbo-filter-validation@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-kubernetes": "pkg:maven/org.apache.dubbo/dubbo-kubernetes@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-api": "pkg:maven/org.apache.dubbo/dubbo-metadata-api@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-definition-protobuf": "pkg:maven/org.apache.dubbo/dubbo-metadata-definition-protobuf@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-report-nacos": "pkg:maven/org.apache.dubbo/dubbo-metadata-report-nacos@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-report-redis": "pkg:maven/org.apache.dubbo/dubbo-metadata-report-redis@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-report-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-metadata-report-zookeeper@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metrics-api": "pkg:maven/org.apache.dubbo/dubbo-metrics-api@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metrics-prometheus": "pkg:maven/org.apache.dubbo/dubbo-metrics-prometheus@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-monitor-api": "pkg:maven/org.apache.dubbo/dubbo-monitor-api@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-monitor-default": "pkg:maven/org.apache.dubbo/dubbo-monitor-default@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-qos": "pkg:maven/org.apache.dubbo/dubbo-qos@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-reactive": "pkg:maven/org.apache.dubbo/dubbo-reactive@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-api": "pkg:maven/org.apache.dubbo/dubbo-registry-api@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-multicast": "pkg:maven/org.apache.dubbo/dubbo-registry-multicast@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-multiple": "pkg:maven/org.apache.dubbo/dubbo-registry-multiple@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-nacos": "pkg:maven/org.apache.dubbo/dubbo-registry-nacos@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-registry-zookeeper@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-api": "pkg:maven/org.apache.dubbo/dubbo-remoting-api@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-http": "pkg:maven/org.apache.dubbo/dubbo-remoting-http@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-netty": "pkg:maven/org.apache.dubbo/dubbo-remoting-netty@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-netty4": "pkg:maven/org.apache.dubbo/dubbo-remoting-netty4@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-remoting-zookeeper@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-zookeeper-curator5": "pkg:maven/org.apache.dubbo/dubbo-remoting-zookeeper-curator5@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-api": "pkg:maven/org.apache.dubbo/dubbo-rpc-api@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-dubbo": "pkg:maven/org.apache.dubbo/dubbo-rpc-dubbo@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-grpc": "pkg:maven/org.apache.dubbo/dubbo-rpc-grpc@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-injvm": "pkg:maven/org.apache.dubbo/dubbo-rpc-injvm@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-rest": "pkg:maven/org.apache.dubbo/dubbo-rpc-rest@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-triple": "pkg:maven/org.apache.dubbo/dubbo-rpc-triple@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-api": "pkg:maven/org.apache.dubbo/dubbo-serialization-api@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-fastjson2": "pkg:maven/org.apache.dubbo/dubbo-serialization-fastjson2@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-hessian2": "pkg:maven/org.apache.dubbo/dubbo-serialization-hessian2@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-jdk": "pkg:maven/org.apache.dubbo/dubbo-serialization-jdk@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-xds": "pkg:maven/org.apache.dubbo/dubbo-xds@3.1.4", - // "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo": "pkg:maven/org.apache.dubbo/dubbo@3.1.4", - // "/packages/dubbo-3.1.4.jar": "pkg:maven/org.apache.dubbo/dubbo@3.1.4", + "/packages/activemq-client-5.18.2.jar": "pkg:maven/org.apache.activemq/activemq-client@5.18.2", + "/packages/activemq-protobuf-1.1.jar": "pkg:maven/org.apache.activemq.protobuf/activemq-protobuf@1.1", + "/packages/akka-actor_2.13-2.6.6.jar": "pkg:maven/com.typesafe.akka/akka-actor_2.13@2.6.6", + "/packages/akka-management-cluster-bootstrap_2.13-1.2.0.jar": "pkg:maven/com.lightbend.akka.management/akka-management-cluster-bootstrap_2.13@1.2.0", + "/packages/ant-1.10.3.jar": "pkg:maven/org.apache.ant/ant@1.10.3", + "/packages/apache-chainsaw-2.1.0.jar": "pkg:maven/log4j/apache-chainsaw@2.1.0", + "/packages/apache-log4j-extras-1.1.jar": "pkg:maven/log4j/apache-log4j-extras@1.1", + "/packages/apoc-4.4.0.11.jar": "pkg:maven/org.neo4j.procedure/apoc@4.4.0.11", + "/packages/bc-fips-1.0.2.3.jar": "pkg:maven/org.bouncycastle/bc-fips@1.0.2.3", + "/packages/camel-core-3.1.0.jar": "pkg:maven/org.apache.camel/camel-core@3.1.0", + "/packages/cassandra-all-4.1.1.jar": "pkg:maven/org.apache.cassandra/cassandra-all@4.1.1", + "/packages/commons-logging-1.1.1.jar": "pkg:maven/commons-logging/commons-logging@1.1.1", + "/packages/commons-vfs-1.0.jar": "pkg:maven/commons-vfs/commons-vfs@1.0", + "/packages/cxf-rt-transports-http-2.7.3.jar": "pkg:maven/org.apache.cxf/cxf-rt-transports-http@2.7.3", + "/packages/dubbo-3.1.4.jar:com.alibaba:hessian-lite": "pkg:maven/com.alibaba/hessian-lite@3.2.13", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-auth": "pkg:maven/org.apache.dubbo/dubbo-auth@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-cluster": "pkg:maven/org.apache.dubbo/dubbo-cluster@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-common": "pkg:maven/org.apache.dubbo/dubbo-common@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-compatible": "pkg:maven/org.apache.dubbo/dubbo-compatible@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-config-api": "pkg:maven/org.apache.dubbo/dubbo-config-api@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-config-spring": "pkg:maven/org.apache.dubbo/dubbo-config-spring@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-configcenter-apollo": "pkg:maven/org.apache.dubbo/dubbo-configcenter-apollo@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-configcenter-nacos": "pkg:maven/org.apache.dubbo/dubbo-configcenter-nacos@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-configcenter-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-configcenter-zookeeper@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-container-api": "pkg:maven/org.apache.dubbo/dubbo-container-api@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-container-spring": "pkg:maven/org.apache.dubbo/dubbo-container-spring@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-filter-cache": "pkg:maven/org.apache.dubbo/dubbo-filter-cache@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-filter-validation": "pkg:maven/org.apache.dubbo/dubbo-filter-validation@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-kubernetes": "pkg:maven/org.apache.dubbo/dubbo-kubernetes@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-api": "pkg:maven/org.apache.dubbo/dubbo-metadata-api@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-definition-protobuf": "pkg:maven/org.apache.dubbo/dubbo-metadata-definition-protobuf@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-report-nacos": "pkg:maven/org.apache.dubbo/dubbo-metadata-report-nacos@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-report-redis": "pkg:maven/org.apache.dubbo/dubbo-metadata-report-redis@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-report-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-metadata-report-zookeeper@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metrics-api": "pkg:maven/org.apache.dubbo/dubbo-metrics-api@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metrics-prometheus": "pkg:maven/org.apache.dubbo/dubbo-metrics-prometheus@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-monitor-api": "pkg:maven/org.apache.dubbo/dubbo-monitor-api@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-monitor-default": "pkg:maven/org.apache.dubbo/dubbo-monitor-default@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-qos": "pkg:maven/org.apache.dubbo/dubbo-qos@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-reactive": "pkg:maven/org.apache.dubbo/dubbo-reactive@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-api": "pkg:maven/org.apache.dubbo/dubbo-registry-api@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-multicast": "pkg:maven/org.apache.dubbo/dubbo-registry-multicast@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-multiple": "pkg:maven/org.apache.dubbo/dubbo-registry-multiple@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-nacos": "pkg:maven/org.apache.dubbo/dubbo-registry-nacos@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-registry-zookeeper@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-api": "pkg:maven/org.apache.dubbo/dubbo-remoting-api@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-http": "pkg:maven/org.apache.dubbo/dubbo-remoting-http@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-netty": "pkg:maven/org.apache.dubbo/dubbo-remoting-netty@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-netty4": "pkg:maven/org.apache.dubbo/dubbo-remoting-netty4@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-remoting-zookeeper@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-zookeeper-curator5": "pkg:maven/org.apache.dubbo/dubbo-remoting-zookeeper-curator5@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-api": "pkg:maven/org.apache.dubbo/dubbo-rpc-api@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-dubbo": "pkg:maven/org.apache.dubbo/dubbo-rpc-dubbo@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-grpc": "pkg:maven/org.apache.dubbo/dubbo-rpc-grpc@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-injvm": "pkg:maven/org.apache.dubbo/dubbo-rpc-injvm@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-rest": "pkg:maven/org.apache.dubbo/dubbo-rpc-rest@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-triple": "pkg:maven/org.apache.dubbo/dubbo-rpc-triple@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-api": "pkg:maven/org.apache.dubbo/dubbo-serialization-api@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-fastjson2": "pkg:maven/org.apache.dubbo/dubbo-serialization-fastjson2@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-hessian2": "pkg:maven/org.apache.dubbo/dubbo-serialization-hessian2@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-jdk": "pkg:maven/org.apache.dubbo/dubbo-serialization-jdk@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-xds": "pkg:maven/org.apache.dubbo/dubbo-xds@3.1.4", + "/packages/dubbo-3.1.4.jar": "pkg:maven/org.apache.dubbo/dubbo@3.1.4", "/packages/elasticsearch-8.10.2.jar": "pkg:maven/org.elasticsearch/elasticsearch@8.10.2", "/packages/elasticsearch-rest-client-sniffer-7.17.11.jar": "pkg:maven/org.elasticsearch.client/elasticsearch-rest-client-sniffer@7.17.11", "/packages/example-java-app-gradle-0.1.0.ear": "pkg:maven/example-java-app-gradle/example-java-app-gradle@0.1.0", From 49d4e32241fc3025fd87515ad4ce37196871d2f2 Mon Sep 17 00:00:00 2001 From: Alan Pope Date: Mon, 12 Aug 2024 11:49:10 +0100 Subject: [PATCH 138/284] update-slack-to-discourse (#3111) Signed-off-by: Alan Pope --- .github/ISSUE_TEMPLATE/config.yml | 6 +++--- DEVELOPING.md | 2 +- README.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index edd71d504..3009b9c0c 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,6 +1,6 @@ contact_links: - - name: Join the Slack community đŸ’Ŧ - # link to our community Slack registration page - url: https://anchore.com/slack + - name: Join our Discourse community đŸ’Ŧ + # link to our community Discourse site + url: https://anchore.com/discourse about: 'Come chat with us! Ask for help, join our software development efforts, or just give us feedback!' diff --git a/DEVELOPING.md b/DEVELOPING.md index 2308c51b1..3d1e5ff18 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -212,7 +212,7 @@ Finally, here is an example of where the package construction is done within the - [The APK package constructor itself](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/apkdb/package.go#L12-L27) Interested in building a new cataloger? Checkout the [list of issues with the `new-cataloger` label](https://github.com/anchore/syft/issues?q=is%3Aopen+is%3Aissue+label%3Anew-cataloger+no%3Aassignee)! -If you have questions about implementing a cataloger feel free to file an issue or reach out to us [on slack](https://anchore.com/slack)! +If you have questions about implementing a cataloger feel free to file an issue or reach out to us [on discourse](https://anchore.com/discourse)! #### Searching for files diff --git a/README.md b/README.md index 4a714210c..cf4d361c5 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@  GitHub release   GitHub go.mod Go version   License: Apache-2.0  -  Slack  +  Join our Discourse 

![syft-demo](https://user-images.githubusercontent.com/590471/90277200-2a253000-de33-11ea-893f-32c219eea11a.gif) From cf85450e08da80f940c21f977e9e061844648904 Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Mon, 12 Aug 2024 12:07:47 -0400 Subject: [PATCH 139/284] chore: fix failing python relationship test (#3117) Signed-off-by: Keith Zantow --- syft/pkg/cataloger/python/cataloger_test.go | 2 +- .../python/test-fixtures/image-multi-site-package/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/syft/pkg/cataloger/python/cataloger_test.go b/syft/pkg/cataloger/python/cataloger_test.go index f3fc06017..8e827322e 100644 --- a/syft/pkg/cataloger/python/cataloger_test.go +++ b/syft/pkg/cataloger/python/cataloger_test.go @@ -643,7 +643,7 @@ func Test_PackageCataloger_SitePackageRelationships(t *testing.T) { // Note: we'll only see new relationships, so any relationship where there is at least one new player (in FROM or TO) "blessed @ 1.20.0 (/usr/local/lib/python3.9/dist-packages) [dependency-of] inquirer @ 3.0.0 (/app/project1/venv/lib/python3.9/site-packages)", // note: depends on global site package! "python-editor @ 1.0.4 (/usr/local/lib/python3.9/dist-packages) [dependency-of] inquirer @ 3.0.0 (/app/project1/venv/lib/python3.9/site-packages)", // note: depends on global site package! - "readchar @ 4.1.0 (/app/project1/venv/lib/python3.9/site-packages) [dependency-of] inquirer @ 3.0.0 (/app/project1/venv/lib/python3.9/site-packages)", + "readchar @ 4.2.0 (/app/project1/venv/lib/python3.9/site-packages) [dependency-of] inquirer @ 3.0.0 (/app/project1/venv/lib/python3.9/site-packages)", "soupsieve @ 2.3 (/app/project1/venv/lib/python3.9/site-packages) [dependency-of] beautifulsoup4 @ 4.10.0 (/app/project1/venv/lib/python3.9/site-packages)", // project 2 virtual env diff --git a/syft/pkg/cataloger/python/test-fixtures/image-multi-site-package/Dockerfile b/syft/pkg/cataloger/python/test-fixtures/image-multi-site-package/Dockerfile index dcc27e38c..3895cebbd 100644 --- a/syft/pkg/cataloger/python/test-fixtures/image-multi-site-package/Dockerfile +++ b/syft/pkg/cataloger/python/test-fixtures/image-multi-site-package/Dockerfile @@ -17,7 +17,7 @@ RUN python3.9 -m pip install requests==2.25.0 certifi==2020.12.5 chardet==3.0.4 RUN python3.8 -m pip install click==8.0.2 beautifulsoup4==4.9.2 soupsieve==2.2.0 requests==2.25.0 RUN python3.8 -m pip install runs==1.2.2 xmod==1.8.1 # partial dependencies for inquirer in project2 (which is a red herring) RUN python3.8 -m pip install requests==2.25.0 certifi==2020.12.5 chardet==3.0.4 idna==2.10 urllib3==1.26.18 # total dependencies for requests -RUN python3.8 -m pip install readchar==4.1.0 +RUN python3.8 -m pip install readchar==4.2.0 # create directories for the two projects RUN mkdir -p /app/project1 /app/project2 From c19cf626abf2319a3cf0e2687cd4ee761425c962 Mon Sep 17 00:00:00 2001 From: luozexuan Date: Tue, 13 Aug 2024 00:08:04 +0800 Subject: [PATCH 140/284] chore: fix some comments (#3114) Signed-off-by: luozexuan --- DEVELOPING.md | 2 +- cmd/syft/internal/options/format.go | 2 +- internal/cache/README.md | 2 +- test/cli/cyclonedx_valid_test.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DEVELOPING.md b/DEVELOPING.md index 3d1e5ff18..5dd88e274 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -83,7 +83,7 @@ Syft's core library is implemented in the `syft` package and subpackages, where - the `syft` package contains a single function that can take a `source.Source` object and catalog it, producing an `sbom.SBOM` object - the `syft/format` package contains the ability to encode and decode SBOMs to and from different SBOM formats (such as SPDX and CycloneDX) -The `cmd` pacakge at the highest level execution flow wires up [`spf13/cobra`](https://github.com/spf13/cobra) commands for execution in the main application: +The `cmd` package at the highest level execution flow wires up [`spf13/cobra`](https://github.com/spf13/cobra) commands for execution in the main application: ```mermaid sequenceDiagram participant main as cmd/syft/main diff --git a/cmd/syft/internal/options/format.go b/cmd/syft/internal/options/format.go index 4ff1e9934..4540b5fee 100644 --- a/cmd/syft/internal/options/format.go +++ b/cmd/syft/internal/options/format.go @@ -50,7 +50,7 @@ if false, uses the syft-json output for templating (which follows the syft JSON Note: long term support for this option is not guaranteed (it may change or break at any time)`) - prettyDescription := `include space indention and newlines + prettyDescription := `include space indentation and newlines note: inherits default value from 'format.pretty' or 'false' if parent is unset` descriptions.Add(&o.SyftJSON.Pretty, prettyDescription) descriptions.Add(&o.SPDXJSON.Pretty, prettyDescription) diff --git a/internal/cache/README.md b/internal/cache/README.md index 174e03b9e..b24a6f934 100644 --- a/internal/cache/README.md +++ b/internal/cache/README.md @@ -1,6 +1,6 @@ # Caching -All caches are created from a global `manager`. By defaut this is a `bypassedCache`, which performs no caching. +All caches are created from a global `manager`. By default this is a `bypassedCache`, which performs no caching. One benefit of this is that tests don't need to worry about caching causing issues unless they explicitly need to test the cache and can opt-in using the `cache.TestCache(t)` helper. diff --git a/test/cli/cyclonedx_valid_test.go b/test/cli/cyclonedx_valid_test.go index 1feca08d9..49755f0bc 100644 --- a/test/cli/cyclonedx_valid_test.go +++ b/test/cli/cyclonedx_valid_test.go @@ -12,7 +12,7 @@ import ( "github.com/anchore/syft/syft/format/cyclonedxjson" ) -// We have schema validation mechanims in schema/cyclonedx/ +// We have schema validation mechanisms in schema/cyclonedx/ // This test allows us to double check that validation against the cyclonedx-cli tool func TestValidCycloneDX(t *testing.T) { imageFixture := func(t *testing.T) string { From 91cf066db6ff4fc9be4a7e15ff086a811ca449fa Mon Sep 17 00:00:00 2001 From: GGMU <49076226+tomersein@users.noreply.github.com> Date: Mon, 12 Aug 2024 19:10:03 +0300 Subject: [PATCH 141/284] support .kar files (#3113) * add kar Signed-off-by: tomersein --- syft/pkg/cataloger/java/archive_filename.go | 2 +- syft/pkg/cataloger/java/archive_filename_test.go | 7 +++++++ syft/pkg/cataloger/java/archive_parser.go | 1 + syft/pkg/cataloger/java/cataloger_test.go | 1 + .../test-fixtures/glob-paths/java-archives/example.kar | 1 + 5 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 syft/pkg/cataloger/java/test-fixtures/glob-paths/java-archives/example.kar diff --git a/syft/pkg/cataloger/java/archive_filename.go b/syft/pkg/cataloger/java/archive_filename.go index 084371499..cc377e438 100644 --- a/syft/pkg/cataloger/java/archive_filename.go +++ b/syft/pkg/cataloger/java/archive_filename.go @@ -108,7 +108,7 @@ func (a archiveFilename) extension() string { func (a archiveFilename) pkgType() pkg.Type { switch strings.ToLower(a.extension()) { - case "jar", "war", "ear", "lpkg", "par", "sar", "nar": + case "jar", "war", "ear", "lpkg", "par", "sar", "nar", "kar": return pkg.JavaPkg case "jpi", "hpi": return pkg.JenkinsPluginPkg diff --git a/syft/pkg/cataloger/java/archive_filename_test.go b/syft/pkg/cataloger/java/archive_filename_test.go index 5752e7d1a..985604912 100644 --- a/syft/pkg/cataloger/java/archive_filename_test.go +++ b/syft/pkg/cataloger/java/archive_filename_test.go @@ -86,6 +86,13 @@ func TestExtractInfoFromJavaArchiveFilename(t *testing.T) { name: "pkg-extra-field-maven", ty: pkg.JavaPkg, }, + { + filename: "pkg-extra-field-maven-4.3.2-rc1.kar", + version: "4.3.2-rc1", + extension: "kar", + name: "pkg-extra-field-maven", + ty: pkg.JavaPkg, + }, { filename: "/some/path/pkg-extra-field-maven-4.3.2-rc1.jpi", version: "4.3.2-rc1", diff --git a/syft/pkg/cataloger/java/archive_parser.go b/syft/pkg/cataloger/java/archive_parser.go index 663563c61..1de3ab80a 100644 --- a/syft/pkg/cataloger/java/archive_parser.go +++ b/syft/pkg/cataloger/java/archive_parser.go @@ -31,6 +31,7 @@ var archiveFormatGlobs = []string{ "**/*.nar", "**/*.jpi", "**/*.hpi", + "**/*.kar", "**/*.lpkg", // Zip-compressed package used to deploy applications // (aka plugins) to Liferay Portal server. Those files contains .JAR(s) and a .PROPERTIES file, the latter // has information about the application and installation requirements. diff --git a/syft/pkg/cataloger/java/cataloger_test.go b/syft/pkg/cataloger/java/cataloger_test.go index da524fc5b..84ba1ea91 100644 --- a/syft/pkg/cataloger/java/cataloger_test.go +++ b/syft/pkg/cataloger/java/cataloger_test.go @@ -23,6 +23,7 @@ func Test_ArchiveCataloger_Globs(t *testing.T) { "java-archives/example.par", "java-archives/example.sar", "java-archives/example.nar", + "java-archives/example.kar", "java-archives/example.jpi", "java-archives/example.hpi", "java-archives/example.lpkg", diff --git a/syft/pkg/cataloger/java/test-fixtures/glob-paths/java-archives/example.kar b/syft/pkg/cataloger/java/test-fixtures/glob-paths/java-archives/example.kar new file mode 100644 index 000000000..0b3d595db --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/glob-paths/java-archives/example.kar @@ -0,0 +1 @@ +example archive \ No newline at end of file From d2b33f1acb34fd75782032e519f804efd90aecae Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 16:57:47 +0000 Subject: [PATCH 142/284] chore(deps): update CPE dictionary index (#3116) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: wagoodman <590471+wagoodman@users.noreply.github.com> Co-authored-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> --- .../dictionary/data/cpe-index.json | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index 54ec320a8..586be8f3e 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -1464,6 +1464,9 @@ "quality-gates": [ "cpe:2.3:a:jenkins:quality_gates:*:*:*:*:*:jenkins:*:*" ], + "qualys-pc": [ + "cpe:2.3:a:qualys:policy_compliance:*:*:*:*:*:jenkins:*:*" + ], "quayio-trigger": [ "cpe:2.3:a:jenkins:quay.io_trigger:*:*:*:*:*:jenkins:*:*" ], @@ -7219,6 +7222,7 @@ "cpe:2.3:a:webtechstreet:elementor_addon_elements:*:*:*:*:*:wordpress:*:*" ], "addons-for-beaver-builder": [ + "cpe:2.3:a:livemesh:beaver_builder_addons:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:livemesh:livemesh_addons_for_beaver_builder:*:*:*:*:*:wordpress:*:*" ], "addons-for-elementor": [ @@ -8598,7 +8602,8 @@ "cpe:2.3:a:quantumcloud:ai_chatbot:*:*:*:*:*:wordpress:*:*" ], "chatbot-chatgpt": [ - "cpe:2.3:a:kognetics:kognetiks_chatbot:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:kognetics:kognetiks_chatbot:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:kognetiks:chatbot:*:*:*:*:*:wordpress:*:*" ], "chaty": [ "cpe:2.3:a:premio:chaty:*:*:*:*:*:wordpress:*:*", @@ -8690,6 +8695,9 @@ "clockwork-two-factor-authentication": [ "cpe:2.3:a:mediaburst:two-factor_authentication:*:*:*:*:*:wordpress:*:*" ], + "clone-menu": [ + "cpe:2.3:a:afzalmultani:wp_clone_menu:*:*:*:*:*:wordpress:*:*" + ], "cloudnet-sync": [ "cpe:2.3:a:cloudnet360:cloudnet360:*:*:*:*:*:wordpress:*:*" ], @@ -10099,6 +10107,9 @@ "enquiry-quotation-for-woocommerce": [ "cpe:2.3:a:piwebsolution:product_enquiry_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], + "enteraddons": [ + "cpe:2.3:a:themelooks:enter_addons:*:*:*:*:*:wordpress:*:*" + ], "envato-elements": [ "cpe:2.3:a:envato:envato_elements:*:*:*:*:*:wordpress:*:*" ], @@ -10854,6 +10865,9 @@ "generatepress-premium": [ "cpe:2.3:a:generatepress:generatepress:*:*:*:*:premium:wordpress:*:*" ], + "genesis-blocks": [ + "cpe:2.3:a:wpengine:genesis_blocks:*:*:*:*:*:wordpress:*:*" + ], "genesis-columns-advanced": [ "cpe:2.3:a:genesis_columns_advanced_project:genesis_columns_advanced:*:*:*:*:*:wordpress:*:*" ], @@ -11601,6 +11615,7 @@ "cpe:2.3:a:insert_pages_project:insert_pages:*:*:*:*:*:wordpress:*:*" ], "insert-php": [ + "cpe:2.3:a:cm-wp:woody_ad_snippets:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:cm-wp:woody_code_snippets:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:webcraftic:woody_ad_snippets:*:*:*:*:*:wordpress:*:*" ], @@ -13244,6 +13259,9 @@ "page-list": [ "cpe:2.3:a:page-list_project:page-list:*:*:*:*:*:wordpress:*:*" ], + "page-or-post-clone": [ + "cpe:2.3:a:carlosfazenda:page_and_post_clone:*:*:*:*:*:wordpress:*:*" + ], "page-scroll-to-id": [ "cpe:2.3:a:page_scroll_to_id_project:page_scroll_to_id:*:*:*:*:*:wordpress:*:*" ], @@ -13317,6 +13335,9 @@ "paypal-donations": [ "cpe:2.3:a:tipsandtricks-hq:donations_via_paypal:*:*:*:*:*:wordpress:*:*" ], + "paypal-pay-buy-donation-and-cart-buttons-shortcode": [ + "cpe:2.3:a:mohsinrasool:paypal_pay_now\\,_buy_now\\,_donation_and_cart_buttons_shortcode:*:*:*:*:*:wordpress:*:*" + ], "paypal-payment-button-by-vcita": [ "cpe:2.3:a:vcita:online_payments_-_get_paid_with_paypal\\,_square_\\\u0026_stripe:*:*:*:*:*:wordpress:*:*" ], @@ -13719,6 +13740,9 @@ "postmatic": [ "cpe:2.3:a:gopostmatic:replyable:*:*:*:*:*:wordpress:*:*" ], + "posts-and-users-stats": [ + "cpe:2.3:a:patrick-robrecht:posts_and_user_stats:*:*:*:*:*:wordpress:*:*" + ], "posts-in-page": [ "cpe:2.3:a:ivycat:posts_in_page:*:*:*:*:*:wordpress:*:*" ], @@ -13921,6 +13945,9 @@ "pwa-for-wp": [ "cpe:2.3:a:magazine3:pwa_for_wp_\\\u0026_amp:*:*:*:*:*:wordpress:*:*" ], + "pz-frontend-manager": [ + "cpe:2.3:a:projectzealous:pz_frontend_manager:*:*:*:*:*:wordpress:*:*" + ], "pz-linkcard": [ "cpe:2.3:a:popozure:pz-linkcard:*:*:*:*:*:wordpress:*:*" ], @@ -14803,6 +14830,9 @@ "simple-cod-fee-for-woocommerce": [ "cpe:2.3:a:83pixel:simple_cod_fees_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], + "simple-csv-xls-exporter": [ + "cpe:2.3:a:shambix:simple_csv\\/xls_exporter:*:*:*:*:*:wordpress:*:*" + ], "simple-custom-author-profiles": [ "cpe:2.3:a:usbmemorydirect:simple_custom_author_profiles:*:*:*:*:*:wordpress:*:*" ], @@ -15525,6 +15555,9 @@ "superb-social-share-and-follow-buttons": [ "cpe:2.3:a:superbthemes:superb_social_media_share_buttons_and_follow_buttons_for_wordpress:*:*:*:*:*:wordpress:*:*" ], + "supersaas-appointment-scheduling": [ + "cpe:2.3:a:supersaas:supersaas:*:*:*:*:*:wordpress:*:*" + ], "supportcandy": [ "cpe:2.3:a:supportcandy:supportcandy:*:*:*:*:*:wordpress:*:*" ], @@ -15984,6 +16017,9 @@ "typofr": [ "cpe:2.3:a:typofr_project:typofr:*:*:*:*:*:wordpress:*:*" ], + "ubermenu": [ + "cpe:2.3:a:sevenspark:ubermenu:*:*:*:*:*:wordpress:*:*" + ], "ucontext": [ "cpe:2.3:a:summitmediaconcepts:ucontext_for_clickbank:*:*:*:*:*:wordpress:*:*" ], @@ -17637,6 +17673,9 @@ "wp-links-page": [ "cpe:2.3:a:wplinkspage:wp_links_page:*:*:*:*:*:wordpress:*:*" ], + "wp-lister-for-amazon": [ + "cpe:2.3:a:wplab:wp-lister_lite_for_amazon:*:*:*:*:*:wordpress:*:*" + ], "wp-lister-for-ebay": [ "cpe:2.3:a:wplab:wp-lister_lite_for_ebay:*:*:*:*:*:wordpress:*:*" ], @@ -17746,6 +17785,9 @@ "wp-open-graph": [ "cpe:2.3:a:custom4web:wp_open_graph:*:*:*:*:*:wordpress:*:*" ], + "wp-open-street-map": [ + "cpe:2.3:a:info-d-74:open_street_map:*:*:*:*:*:wordpress:*:*" + ], "wp-opt-in": [ "cpe:2.3:a:wp_opt-in_project:wp_opt-in:*:*:*:*:*:wordpress:*:*" ], @@ -18325,6 +18367,9 @@ "wpematico": [ "cpe:2.3:a:etruel:wpematico_rss_feed_fetcher:*:*:*:*:*:wordpress:*:*" ], + "wpextended": [ + "cpe:2.3:a:wpextended:wp_extended:*:*:*:*:*:wordpress:*:*" + ], "wpforms": [ "cpe:2.3:a:wpforms:wpforms:*:*:*:*:pro:wordpress:*:*" ], From df1e5b57fe94b67312762262d4361b1b9b762813 Mon Sep 17 00:00:00 2001 From: Weston Steimel Date: Mon, 12 Aug 2024 17:01:44 +0000 Subject: [PATCH 143/284] fix: improve groupid extraction for Jenkins plugins (#2815) * fix: improve groupid extraction for Jenkins plugins Consider the `Group-Id` java manifest property as this is typically set for Jenkins plugins if there is no pom file Signed-off-by: Weston Steimel * test: update java purl integration test image Signed-off-by: Weston Steimel --------- Signed-off-by: Weston Steimel --- .../test/integration/java_purl_test.go | 965 ++++++++++++------ .../image-test-java-purls/Dockerfile | 4 +- .../cataloger/internal/cpegenerate/java.go | 1 + syft/pkg/cataloger/java/archive_parser.go | 5 + .../pkg/cataloger/java/archive_parser_test.go | 56 +- .../java/test-fixtures/jar-metadata/Makefile | 5 + .../gradle/2.11/META-INF/MANIFEST.MF | 13 + 7 files changed, 748 insertions(+), 301 deletions(-) create mode 100644 syft/pkg/cataloger/java/test-fixtures/jar-metadata/jenkins-plugins/gradle/2.11/META-INF/MANIFEST.MF diff --git a/cmd/syft/internal/test/integration/java_purl_test.go b/cmd/syft/internal/test/integration/java_purl_test.go index d63675222..5dab545d6 100644 --- a/cmd/syft/internal/test/integration/java_purl_test.go +++ b/cmd/syft/internal/test/integration/java_purl_test.go @@ -41,105 +41,396 @@ func TestJavaPURLs(t *testing.T) { // generating the incorrect PURL var noAssertion = map[string]string{ // These are not known to exist on any public maven repo, so no real PURL should be asserted - "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/jopenssl.jar": "pkg:maven/jopenssl/jopenssl", - "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/json/ext/generator.jar": "pkg:maven/generator/generator", - "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/json/ext/parser.jar": "pkg:maven/parser/parser", - "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/psych.jar": "pkg:maven/psych/psych", - "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/racc/cparse-jruby.jar": "pkg:maven/cparse-jruby/cparse-jruby", - "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/readline.jar": "pkg:maven/readline/readline", - "/packages/org.eclipse.ant.core-3.7.0.jar:lib/antsupportlib.jar": "pkg:maven/antsupportlib/antsupportlib", - "/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar": "pkg:maven/sdk/sdk@3.0", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/trilead-ssh2-build-217-jenkins-27.jar": "pkg:maven/trilead-ssh2-build/trilead-ssh2-build@217-jenkins-27", + // possibly org.gradle as groupid for these, but unclear + "/packages/gradle-7.1.1/lib/gradle-api-metadata-7.1.1.jar": "pkg:maven/gradle-api-metadata/gradle-api-metadata@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-base-annotations-7.1.1.jar": "pkg:maven/gradle-base-annotations/gradle-base-annotations@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-base-services-7.1.1.jar": "pkg:maven/gradle-base-services/gradle-base-services@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-base-services-groovy-7.1.1.jar": "pkg:maven/gradle-base-services-groovy/gradle-base-services-groovy@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-bootstrap-7.1.1.jar": "pkg:maven/gradle-bootstrap/gradle-bootstrap@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-build-cache-7.1.1.jar": "pkg:maven/gradle-build-cache/gradle-build-cache@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-build-cache-base-7.1.1.jar": "pkg:maven/gradle-build-cache-base/gradle-build-cache-base@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-build-cache-packaging-7.1.1.jar": "pkg:maven/gradle-build-cache-packaging/gradle-build-cache-packaging@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-build-events-7.1.1.jar": "pkg:maven/gradle-build-events/gradle-build-events@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-build-operations-7.1.1.jar": "pkg:maven/gradle-build-operations/gradle-build-operations@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-build-option-7.1.1.jar": "pkg:maven/gradle-build-option/gradle-build-option@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-cli-7.1.1.jar": "pkg:maven/gradle-cli/gradle-cli@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-core-7.1.1.jar": "pkg:maven/gradle-core/gradle-core@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-core-api-7.1.1.jar": "pkg:maven/gradle-core-api/gradle-core-api@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-data-structures-7.1.1.jar": "pkg:maven/gradle-data-structures/gradle-data-structures@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-execution-7.1.1.jar": "pkg:maven/gradle-execution/gradle-execution@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-file-collections-7.1.1.jar": "pkg:maven/gradle-file-collections/gradle-file-collections@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-file-temp-7.1.1.jar": "pkg:maven/gradle-file-temp/gradle-file-temp@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-file-watching-7.1.1.jar": "pkg:maven/gradle-file-watching/gradle-file-watching@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-files-7.1.1.jar": "pkg:maven/gradle-files/gradle-files@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-hashing-7.1.1.jar": "pkg:maven/gradle-hashing/gradle-hashing@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-installation-beacon-7.1.1.jar": "pkg:maven/gradle-installation-beacon/gradle-installation-beacon@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-jvm-services-7.1.1.jar": "pkg:maven/gradle-jvm-services/gradle-jvm-services@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-kotlin-dsl-7.1.1.jar": "pkg:maven/gradle-kotlin-dsl/gradle-kotlin-dsl@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-kotlin-dsl-tooling-models-7.1.1.jar": "pkg:maven/gradle-kotlin-dsl-tooling-models/gradle-kotlin-dsl-tooling-models@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-launcher-7.1.1.jar": "pkg:maven/org.gradle.launcher.GradleMain/gradle-launcher@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-logging-7.1.1.jar": "pkg:maven/gradle-logging/gradle-logging@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-messaging-7.1.1.jar": "pkg:maven/gradle-messaging/gradle-messaging@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-model-core-7.1.1.jar": "pkg:maven/gradle-model-core/gradle-model-core@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-model-groovy-7.1.1.jar": "pkg:maven/gradle-model-groovy/gradle-model-groovy@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-native-7.1.1.jar": "pkg:maven/gradle-native/gradle-native@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-normalization-java-7.1.1.jar": "pkg:maven/gradle-normalization-java/gradle-normalization-java@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-persistent-cache-7.1.1.jar": "pkg:maven/gradle-persistent-cache/gradle-persistent-cache@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-problems-7.1.1.jar": "pkg:maven/gradle-problems/gradle-problems@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-process-services-7.1.1.jar": "pkg:maven/gradle-process-services/gradle-process-services@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-resources-7.1.1.jar": "pkg:maven/gradle-resources/gradle-resources@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-runtime-api-info-7.1.1.jar": "pkg:maven/gradle-runtime-api-info/gradle-runtime-api-info@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-snapshots-7.1.1.jar": "pkg:maven/gradle-snapshots/gradle-snapshots@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-tooling-api-7.1.1.jar": "pkg:maven/gradle-tooling-api/gradle-tooling-api@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-worker-processes-7.1.1.jar": "pkg:maven/gradle-worker-processes/gradle-worker-processes@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-wrapper-7.1.1.jar": "pkg:maven/gradle-wrapper/gradle-wrapper@7.1.1", + "/packages/gradle-7.1.1/lib/gradle-wrapper-7.1.1.jar:gradle-wrapper.jar": "pkg:maven/gradle-wrapper/gradle-wrapper", + "/packages/gradle-7.1.1/lib/plugins/gradle-antlr-7.1.1.jar": "pkg:maven/gradle-antlr/gradle-antlr@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-build-cache-http-7.1.1.jar": "pkg:maven/gradle-build-cache-http/gradle-build-cache-http@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-build-init-7.1.1.jar": "pkg:maven/gradle-build-init/gradle-build-init@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-build-profile-7.1.1.jar": "pkg:maven/gradle-build-profile/gradle-build-profile@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-code-quality-7.1.1.jar": "pkg:maven/gradle-code-quality/gradle-code-quality@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-composite-builds-7.1.1.jar": "pkg:maven/gradle-composite-builds/gradle-composite-builds@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-configuration-cache-7.1.1.jar": "pkg:maven/gradle-configuration-cache/gradle-configuration-cache@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-dependency-management-7.1.1.jar": "pkg:maven/gradle-dependency-management/gradle-dependency-management@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-diagnostics-7.1.1.jar": "pkg:maven/gradle-diagnostics/gradle-diagnostics@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-ear-7.1.1.jar": "pkg:maven/gradle-ear/gradle-ear@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-enterprise-7.1.1.jar": "pkg:maven/gradle-enterprise/gradle-enterprise@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-ide-7.1.1.jar": "pkg:maven/gradle-ide/gradle-ide@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-ide-native-7.1.1.jar": "pkg:maven/gradle-ide-native/gradle-ide-native@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-ivy-7.1.1.jar": "pkg:maven/gradle-ivy/gradle-ivy@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-jacoco-7.1.1.jar": "pkg:maven/gradle-jacoco/gradle-jacoco@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-java-compiler-plugin-7.1.1.jar": "pkg:maven/gradle-java-compiler-plugin/gradle-java-compiler-plugin@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-kotlin-dsl-provider-plugins-7.1.1.jar": "pkg:maven/gradle-kotlin-dsl-provider-plugins/gradle-kotlin-dsl-provider-plugins@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-kotlin-dsl-tooling-builders-7.1.1.jar": "pkg:maven/gradle-kotlin-dsl-tooling-builders/gradle-kotlin-dsl-tooling-builders@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-language-groovy-7.1.1.jar": "pkg:maven/gradle-language-groovy/gradle-language-groovy@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-language-java-7.1.1.jar": "pkg:maven/gradle-language-java/gradle-language-java@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-language-jvm-7.1.1.jar": "pkg:maven/gradle-language-jvm/gradle-language-jvm@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-language-native-7.1.1.jar": "pkg:maven/gradle-language-native/gradle-language-native@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-maven-7.1.1.jar": "pkg:maven/gradle-maven/gradle-maven@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-platform-base-7.1.1.jar": "pkg:maven/gradle-platform-base/gradle-platform-base@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-platform-jvm-7.1.1.jar": "pkg:maven/gradle-platform-jvm/gradle-platform-jvm@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-platform-native-7.1.1.jar": "pkg:maven/gradle-platform-native/gradle-platform-native@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-plugin-development-7.1.1.jar": "pkg:maven/gradle-plugin-development/gradle-plugin-development@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-plugin-use-7.1.1.jar": "pkg:maven/gradle-plugin-use/gradle-plugin-use@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-plugins-7.1.1.jar": "pkg:maven/gradle-plugins/gradle-plugins@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-publish-7.1.1.jar": "pkg:maven/gradle-publish/gradle-publish@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-reporting-7.1.1.jar": "pkg:maven/gradle-reporting/gradle-reporting@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-resources-gcs-7.1.1.jar": "pkg:maven/gradle-resources-gcs/gradle-resources-gcs@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-resources-http-7.1.1.jar": "pkg:maven/gradle-resources-http/gradle-resources-http@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-resources-s3-7.1.1.jar": "pkg:maven/gradle-resources-s3/gradle-resources-s3@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-resources-sftp-7.1.1.jar": "pkg:maven/gradle-resources-sftp/gradle-resources-sftp@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-scala-7.1.1.jar": "pkg:maven/gradle-scala/gradle-scala@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-security-7.1.1.jar": "pkg:maven/gradle-security/gradle-security@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-signing-7.1.1.jar": "pkg:maven/gradle-signing/gradle-signing@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-test-kit-7.1.1.jar": "pkg:maven/gradle-test-kit/gradle-test-kit@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-testing-base-7.1.1.jar": "pkg:maven/gradle-testing-base/gradle-testing-base@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-testing-junit-platform-7.1.1.jar": "pkg:maven/gradle-testing-junit-platform/gradle-testing-junit-platform@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-testing-jvm-7.1.1.jar": "pkg:maven/gradle-testing-jvm/gradle-testing-jvm@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-testing-native-7.1.1.jar": "pkg:maven/gradle-testing-native/gradle-testing-native@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-tooling-api-builders-7.1.1.jar": "pkg:maven/gradle-tooling-api-builders/gradle-tooling-api-builders@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-tooling-native-7.1.1.jar": "pkg:maven/gradle-tooling-native/gradle-tooling-native@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-version-control-7.1.1.jar": "pkg:maven/gradle-version-control/gradle-version-control@7.1.1", + "/packages/gradle-7.1.1/lib/plugins/gradle-workers-7.1.1.jar": "pkg:maven/gradle-workers/gradle-workers@7.1.1", + "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/jopenssl.jar": "pkg:maven/jopenssl/jopenssl", + "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/jopenssl.jar:rubygems:jruby-openssl": "pkg:maven/rubygems/jruby-openssl@0.9.21", + "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/json/ext/parser.jar": "pkg:maven/parser/parser", + "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/json/ext/generator.jar": "pkg:maven/generator/generator", + "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/psych.jar": "pkg:maven/psych/psych", + "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/racc/cparse-jruby.jar": "pkg:maven/cparse-jruby/cparse-jruby", + "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/readline.jar": "pkg:maven/readline/readline", + "/packages/org.eclipse.ant.core-3.7.0.jar:lib/antsupportlib.jar": "pkg:maven/antsupportlib/antsupportlib", + "/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar": "pkg:maven/sdk/sdk@3.0", // syft generates incorrect purls - "/packages/hudson.war:WEB-INF/lib/asm-2.2.3.jar": "pkg:maven/asm/asm@2.2.3", - "/packages/hudson.war:WEB-INF/lib/asm-commons-2.2.3.jar": "pkg:maven/asm/asm-commons@2.2.3", - "/packages/hudson.war:WEB-INF/lib/asm-tree-2.2.3.jar": "pkg:maven/asm/asm-tree@2.2.3", - "/packages/hudson.war:WEB-INF/slave.jar": "pkg:maven/org.jvnet.hudson.main/remoting@1.390", - "/packages/hudson.war:WEB-INF/lib/xpp3_min-1.1.4c.jar": "pkg:maven/xpp3_min/xpp3_min@1.1.4c", - "/packages/hudson.war:WEB-INF/lib/xpp3-1.1.4c.jar": "pkg:maven/xpp3/xpp3@1.1.4c", - "/packages/hudson.war:WEB-INF/hudson-cli.jar": "pkg:maven/org.jvnet.hudson.main/hudson-cli@1.390", - "/packages/hudson.war:WEB-INF/lib/dom4j-1.6.1-hudson-3.jar": "pkg:maven/org.jvnet.hudson.dom4j/dom4j@1.6.1-hudson-3", - "/packages/xpp3_min-1.1.4c.jar": "pkg:maven/xpp3/xpp3_min@1.1.4c", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/jbcrypt-1.0.0.jar": "pkg:maven/org.connectbot/jbcrypt@1.0.0", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/tink-1.5.0.jar": "pkg:maven/com.google.crypto.tink/tink@1.5.0", + "/packages/gradle-7.1.1/lib/fastutil-8.5.2-min.jar": "pkg:maven/it.unimi.dsi/fastutil@8.5.2-min", + "/packages/gradle-7.1.1/lib/file-events-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/file-events@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/file-events-linux-aarch64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/file-events-linux-aarch64@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/file-events-linux-amd64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/file-events-linux-amd64@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/file-events-osx-aarch64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/file-events-osx-aarch64@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/file-events-osx-amd64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/file-events-osx-amd64@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/file-events-windows-amd64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/file-events-windows-amd64@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/file-events-windows-amd64-min-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/file-events-windows-amd64-min@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/file-events-windows-i386-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/file-events-windows-i386@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/file-events-windows-i386-min-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/file-events-windows-i386-min@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/hamcrest-core-1.3.jar": "pkg:maven/org.hamcrest/hamcrest-core@1.3", + "/packages/gradle-7.1.1/lib/kotlin-compiler-embeddable-1.4.31-patched-for-gradle-7.1.1.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-compiler-embeddable@1.4.31-patched-for-gradle-7.1.1", + "/packages/gradle-7.1.1/lib/kotlin-daemon-embeddable-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-daemon-embeddable@1.4.31", + "/packages/gradle-7.1.1/lib/kotlin-reflect-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-reflect@1.4.31", + "/packages/gradle-7.1.1/lib/kotlin-sam-with-receiver-compiler-plugin-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-sam-with-receiver-compiler-plugin@1.4.31", + "/packages/gradle-7.1.1/lib/kotlin-script-runtime-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-script-runtime@1.4.31", + "/packages/gradle-7.1.1/lib/kotlin-scripting-common-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-scripting-common@1.4.31", + "/packages/gradle-7.1.1/lib/kotlin-scripting-compiler-embeddable-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-scripting-compiler-embeddable@1.4.31", + "/packages/gradle-7.1.1/lib/kotlin-scripting-compiler-impl-embeddable-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-scripting-compiler-impl-embeddable@1.4.31", + "/packages/gradle-7.1.1/lib/kotlin-scripting-jvm-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-scripting-jvm@1.4.31", + "/packages/gradle-7.1.1/lib/kotlin-scripting-jvm-host-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-scripting-jvm-host@1.4.31", + "/packages/gradle-7.1.1/lib/kotlin-stdlib-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-stdlib@1.4.31", + "/packages/gradle-7.1.1/lib/kotlin-stdlib-common-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-stdlib-common@1.4.31", + "/packages/gradle-7.1.1/lib/kotlin-stdlib-jdk7-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-stdlib-jdk7@1.4.31", + "/packages/gradle-7.1.1/lib/kotlin-stdlib-jdk8-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-stdlib-jdk8@1.4.31", + "/packages/gradle-7.1.1/lib/kotlinx-metadata-jvm-0.2.0.jar": "pkg:maven/org.jetbrains.kotlinx/kotlinx-metadata-jvm@0.2.0", + "/packages/gradle-7.1.1/lib/native-platform-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/native-platform-freebsd-amd64-libcpp-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-freebsd-amd64-libcpp@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/native-platform-linux-aarch64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-linux-aarch64@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/native-platform-linux-aarch64-ncurses5-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-linux-aarch64-ncurses5@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/native-platform-linux-aarch64-ncurses6-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-linux-aarch64-ncurses6@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/native-platform-linux-amd64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-linux-amd64@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/native-platform-linux-amd64-ncurses5-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-linux-amd64-ncurses5@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/native-platform-linux-amd64-ncurses6-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-linux-amd64-ncurses6@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/native-platform-osx-aarch64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-osx-aarch64@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/native-platform-osx-amd64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-osx-amd64@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/native-platform-windows-amd64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-windows-amd64@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/native-platform-windows-amd64-min-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-windows-amd64-min@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/native-platform-windows-i386-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-windows-i386@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/native-platform-windows-i386-min-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-windows-i386-min@0.22-milestone-16", + "/packages/gradle-7.1.1/lib/plugins/apiguardian-api-1.1.0.jar": "pkg:maven/org.apiguardian/apiguardian-api@1.1.0", + "/packages/gradle-7.1.1/lib/plugins/bsh-2.0b6.jar": "pkg:maven/org.apache-extras.beanshell/bsh@2.0b6", + "/packages/gradle-7.1.1/lib/plugins/google-api-client-1.25.0.jar": "pkg:maven/com.google.api-client/google-api-client@1.25.0", + "/packages/gradle-7.1.1/lib/plugins/google-api-services-storage-v1-rev171-1.25.0.jar": "pkg:maven/com.google.apis/google-api-services-storage@v1-rev171-1.25.0", + "/packages/gradle-7.1.1/lib/plugins/jcommander-1.78.jar": "pkg:maven/com.beust/jcommander@1.78", + "/packages/gradle-7.1.1/lib/plugins/junit-platform-commons-1.7.2.jar": "pkg:maven/org.junit.platform/junit-platform-commons@1.7.2", + "/packages/gradle-7.1.1/lib/plugins/junit-platform-engine-1.7.2.jar": "pkg:maven/org.junit.platform/junit-platform-engine@1.7.2", + "/packages/gradle-7.1.1/lib/plugins/junit-platform-launcher-1.7.2.jar": "pkg:maven/org.junit.platform/junit-platform-launcher@1.7.2", + "/packages/gradle-7.1.1/lib/plugins/nekohtml-1.9.22.jar": "pkg:maven/net.sourceforge.nekohtml/nekohtml@1.9.22", + "/packages/gradle-7.1.1/lib/tomlj-1.0.0.jar": "pkg:maven/org.tomlj/tomlj@1.0.0", + "/packages/gradle-7.1.1/lib/trove4j-1.0.20181211.jar": "pkg:maven/net.sf.trove4j /trove4j@1.0.20181211", + "/packages/gradle-7.1.1/lib/xml-apis-1.4.01.jar": "pkg:maven/xml-apis/xml-apis@1.4.01", + "/packages/gradle-7.1.1/lib/asm-analysis-9.1.jar": "pkg:maven/org.ow2.asm/asm-analysis@9.1", + "/packages/gradle-7.1.1/lib/asm-commons-9.1.jar": "pkg:maven/org.ow2.asm/asm-commons@9.1", + "/packages/gradle-7.1.1/lib/asm-tree-9.1.jar": "pkg:maven/org.ow2.asm/asm-tree@9.1", + "/packages/gradle-7.1.1/lib/plugins/ivy-2.3.0.jar": "pkg:maven/org.apache.ivy/ivy@2.3.0", + "/packages/hudson.war:WEB-INF/lib/asm-2.2.3.jar": "pkg:maven/asm/asm@2.2.3", + "/packages/hudson.war:WEB-INF/lib/asm-commons-2.2.3.jar": "pkg:maven/asm/asm-commons@2.2.3", + "/packages/hudson.war:WEB-INF/lib/asm-tree-2.2.3.jar": "pkg:maven/asm/asm-tree@2.2.3", + "/packages/hudson.war:WEB-INF/slave.jar": "pkg:maven/org.jvnet.hudson.main/remoting@1.390", + "/packages/hudson.war:WEB-INF/lib/xpp3_min-1.1.4c.jar": "pkg:maven/xpp3_min/xpp3_min@1.1.4c", + "/packages/hudson.war:WEB-INF/lib/xpp3-1.1.4c.jar": "pkg:maven/xpp3/xpp3@1.1.4c", + "/packages/hudson.war:WEB-INF/hudson-cli.jar": "pkg:maven/org.jvnet.hudson.main/hudson-cli@1.390", + "/packages/hudson.war:WEB-INF/lib/dom4j-1.6.1-hudson-3.jar": "pkg:maven/org.jvnet.hudson.dom4j/dom4j@1.6.1-hudson-3", + "/packages/newrelic-agent-8.8.0.jar": "pkg:maven/com.newrelic.bootstrap.BootstrapAgent/newrelic-agent@8.8.0", + "/packages/newrelic-agent-8.8.0.jar:agent-bridge-datastore.jar": "pkg:maven/agent-bridge-datastore/agent-bridge-datastore@8.8.0", + "/packages/newrelic-agent-8.8.0.jar:agent-bridge.jar": "pkg:maven/agent-bridge/agent-bridge@8.8.0", + "/packages/newrelic-agent-8.8.0.jar:newrelic-api.jar": "pkg:maven/newrelic-api/newrelic-api@8.8.0", + "/packages/newrelic-agent-8.8.0.jar:newrelic-security-agent.jar": "pkg:maven/newrelic-security-agent/newrelic-security-agent@1.0.7-public-preview", + "/packages/newrelic-agent-8.8.0.jar:newrelic-security-api.jar": "pkg:maven/newrelic-security-api/newrelic-security-api@1.0.7-public-preview", + "/packages/newrelic-agent-8.8.0.jar:newrelic-weaver-api.jar": "pkg:maven/newrelic-weaver-api/newrelic-weaver-api@8.8.0", + "/packages/newrelic-agent-8.8.0.jar:newrelic-weaver-scala-api.jar": "pkg:maven/newrelic-weaver-scala-api/newrelic-weaver-scala-api@8.8.0", + "/packages/maven-plugin.hpi:WEB-INF/lib/jsr250-api-1.0.jar": "pkg:maven/javax.annotation/jsr250-api@1.0", + "/packages/TwilioNotifier.hpi:WEB-INF/lib/commons-httpclient-3.1.jar": "pkg:maven/commons-httpclient/commons-httpclient@3.1", + "/packages/xpp3_min-1.1.4c.jar": "pkg:maven/xpp3/xpp3_min@1.1.4c", + + // Unclear: groupid might be org.glassfish.jaxb or com.sun.xml.bind + "/packages/gradle-7.1.1/lib/plugins/jaxb-core-3.0.0.jar": "pkg:maven/org.glassfish.jaxb/jaxb-core@3.0.0", } // Constructed by: // syft anchore/test_images:java-1abc58f -o json | jq -r '.artifacts.[] | [.metadata.virtualPath, .purl, ""] | @csv' | grep 'pkg:maven' | sort | uniq >> /tmp/java_artifacts_mapping.txt // The map was then hand-edited for correctness by comparing to Maven Central. var expectedPURLs = map[string]string{ - "/packages/activemq-client-5.18.2.jar": "pkg:maven/org.apache.activemq/activemq-client@5.18.2", - "/packages/activemq-protobuf-1.1.jar": "pkg:maven/org.apache.activemq.protobuf/activemq-protobuf@1.1", - "/packages/akka-actor_2.13-2.6.6.jar": "pkg:maven/com.typesafe.akka/akka-actor_2.13@2.6.6", - "/packages/akka-management-cluster-bootstrap_2.13-1.2.0.jar": "pkg:maven/com.lightbend.akka.management/akka-management-cluster-bootstrap_2.13@1.2.0", - "/packages/ant-1.10.3.jar": "pkg:maven/org.apache.ant/ant@1.10.3", - "/packages/apache-chainsaw-2.1.0.jar": "pkg:maven/log4j/apache-chainsaw@2.1.0", - "/packages/apache-log4j-extras-1.1.jar": "pkg:maven/log4j/apache-log4j-extras@1.1", - "/packages/apoc-4.4.0.11.jar": "pkg:maven/org.neo4j.procedure/apoc@4.4.0.11", - "/packages/bc-fips-1.0.2.3.jar": "pkg:maven/org.bouncycastle/bc-fips@1.0.2.3", - "/packages/camel-core-3.1.0.jar": "pkg:maven/org.apache.camel/camel-core@3.1.0", - "/packages/cassandra-all-4.1.1.jar": "pkg:maven/org.apache.cassandra/cassandra-all@4.1.1", - "/packages/commons-logging-1.1.1.jar": "pkg:maven/commons-logging/commons-logging@1.1.1", - "/packages/commons-vfs-1.0.jar": "pkg:maven/commons-vfs/commons-vfs@1.0", - "/packages/cxf-rt-transports-http-2.7.3.jar": "pkg:maven/org.apache.cxf/cxf-rt-transports-http@2.7.3", - "/packages/dubbo-3.1.4.jar:com.alibaba:hessian-lite": "pkg:maven/com.alibaba/hessian-lite@3.2.13", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-auth": "pkg:maven/org.apache.dubbo/dubbo-auth@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-cluster": "pkg:maven/org.apache.dubbo/dubbo-cluster@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-common": "pkg:maven/org.apache.dubbo/dubbo-common@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-compatible": "pkg:maven/org.apache.dubbo/dubbo-compatible@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-config-api": "pkg:maven/org.apache.dubbo/dubbo-config-api@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-config-spring": "pkg:maven/org.apache.dubbo/dubbo-config-spring@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-configcenter-apollo": "pkg:maven/org.apache.dubbo/dubbo-configcenter-apollo@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-configcenter-nacos": "pkg:maven/org.apache.dubbo/dubbo-configcenter-nacos@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-configcenter-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-configcenter-zookeeper@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-container-api": "pkg:maven/org.apache.dubbo/dubbo-container-api@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-container-spring": "pkg:maven/org.apache.dubbo/dubbo-container-spring@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-filter-cache": "pkg:maven/org.apache.dubbo/dubbo-filter-cache@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-filter-validation": "pkg:maven/org.apache.dubbo/dubbo-filter-validation@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-kubernetes": "pkg:maven/org.apache.dubbo/dubbo-kubernetes@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-api": "pkg:maven/org.apache.dubbo/dubbo-metadata-api@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-definition-protobuf": "pkg:maven/org.apache.dubbo/dubbo-metadata-definition-protobuf@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-report-nacos": "pkg:maven/org.apache.dubbo/dubbo-metadata-report-nacos@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-report-redis": "pkg:maven/org.apache.dubbo/dubbo-metadata-report-redis@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-report-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-metadata-report-zookeeper@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metrics-api": "pkg:maven/org.apache.dubbo/dubbo-metrics-api@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metrics-prometheus": "pkg:maven/org.apache.dubbo/dubbo-metrics-prometheus@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-monitor-api": "pkg:maven/org.apache.dubbo/dubbo-monitor-api@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-monitor-default": "pkg:maven/org.apache.dubbo/dubbo-monitor-default@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-qos": "pkg:maven/org.apache.dubbo/dubbo-qos@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-reactive": "pkg:maven/org.apache.dubbo/dubbo-reactive@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-api": "pkg:maven/org.apache.dubbo/dubbo-registry-api@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-multicast": "pkg:maven/org.apache.dubbo/dubbo-registry-multicast@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-multiple": "pkg:maven/org.apache.dubbo/dubbo-registry-multiple@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-nacos": "pkg:maven/org.apache.dubbo/dubbo-registry-nacos@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-registry-zookeeper@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-api": "pkg:maven/org.apache.dubbo/dubbo-remoting-api@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-http": "pkg:maven/org.apache.dubbo/dubbo-remoting-http@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-netty": "pkg:maven/org.apache.dubbo/dubbo-remoting-netty@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-netty4": "pkg:maven/org.apache.dubbo/dubbo-remoting-netty4@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-remoting-zookeeper@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-zookeeper-curator5": "pkg:maven/org.apache.dubbo/dubbo-remoting-zookeeper-curator5@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-api": "pkg:maven/org.apache.dubbo/dubbo-rpc-api@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-dubbo": "pkg:maven/org.apache.dubbo/dubbo-rpc-dubbo@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-grpc": "pkg:maven/org.apache.dubbo/dubbo-rpc-grpc@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-injvm": "pkg:maven/org.apache.dubbo/dubbo-rpc-injvm@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-rest": "pkg:maven/org.apache.dubbo/dubbo-rpc-rest@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-triple": "pkg:maven/org.apache.dubbo/dubbo-rpc-triple@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-api": "pkg:maven/org.apache.dubbo/dubbo-serialization-api@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-fastjson2": "pkg:maven/org.apache.dubbo/dubbo-serialization-fastjson2@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-hessian2": "pkg:maven/org.apache.dubbo/dubbo-serialization-hessian2@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-jdk": "pkg:maven/org.apache.dubbo/dubbo-serialization-jdk@3.1.4", - "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-xds": "pkg:maven/org.apache.dubbo/dubbo-xds@3.1.4", - "/packages/dubbo-3.1.4.jar": "pkg:maven/org.apache.dubbo/dubbo@3.1.4", - "/packages/elasticsearch-8.10.2.jar": "pkg:maven/org.elasticsearch/elasticsearch@8.10.2", - "/packages/elasticsearch-rest-client-sniffer-7.17.11.jar": "pkg:maven/org.elasticsearch.client/elasticsearch-rest-client-sniffer@7.17.11", - "/packages/example-java-app-gradle-0.1.0.ear": "pkg:maven/example-java-app-gradle/example-java-app-gradle@0.1.0", - "/packages/geode-core-1.14.3.jar": "pkg:maven/org.apache.geode/geode-core@1.14.3", - "/packages/github-api-1.118.jar": "pkg:maven/org.kohsuke/github-api@1.118", - "/packages/google-oauth-client-1.25.0.jar": "pkg:maven/com.google.oauth-client/google-oauth-client@1.25.0", + "/packages/activemq-client-5.18.2.jar": "pkg:maven/org.apache.activemq/activemq-client@5.18.2", + "/packages/activemq-protobuf-1.1.jar": "pkg:maven/org.apache.activemq.protobuf/activemq-protobuf@1.1", + "/packages/akka-actor_2.13-2.6.6.jar": "pkg:maven/com.typesafe.akka/akka-actor_2.13@2.6.6", + "/packages/akka-management-cluster-bootstrap_2.13-1.2.0.jar": "pkg:maven/com.lightbend.akka.management/akka-management-cluster-bootstrap_2.13@1.2.0", + "/packages/ant-1.10.3.jar": "pkg:maven/org.apache.ant/ant@1.10.3", + "/packages/apache-chainsaw-2.1.0.jar": "pkg:maven/log4j/apache-chainsaw@2.1.0", + "/packages/apache-log4j-extras-1.1.jar": "pkg:maven/log4j/apache-log4j-extras@1.1", + "/packages/apoc-4.4.0.11.jar": "pkg:maven/org.neo4j.procedure/apoc@4.4.0.11", + "/packages/atlassian-bitbucket-server-integration.hpi": "pkg:maven/io.jenkins.plugins/atlassian-bitbucket-server-integration@2.1.2", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/atlassian-bitbucket-server-integration.jar": "pkg:maven/io.jenkins.plugins/atlassian-bitbucket-server-integration@2.1.2", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/commons-codec-1.13.jar": "pkg:maven/commons-codec/commons-codec@1.13", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/commons-lang3-3.9.jar": "pkg:maven/org.apache.commons/commons-lang3@3.9", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/eddsa-0.3.0.jar": "pkg:maven/net.i2p.crypto/eddsa@0.3.0", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/httpcore-4.4.9.jar": "pkg:maven/org.apache.httpcomponents/httpcore@4.4.9", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/jackson-annotations-2.11.2.jar": "pkg:maven/com.fasterxml.jackson.core/jackson-annotations@2.11.2", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/jackson-core-2.11.2.jar": "pkg:maven/com.fasterxml.jackson.core/jackson-core@2.11.2", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/jackson-databind-2.9.10.7.jar": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.9.10.7", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/jcommon-1.0.24.jar": "pkg:maven/org.jfree/jcommon@1.0.24", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/json-20180813.jar": "pkg:maven/org.json/json@20180813", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/oauth-20100527.jar": "pkg:maven/net.oauth.core/oauth@20100527", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/oauth-provider-20100527.jar": "pkg:maven/net.oauth.core/oauth-provider@20100527", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/okhttp-3.14.1.jar": "pkg:maven/com.squareup.okhttp3/okhttp@3.14.1", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/okio-1.17.2.jar": "pkg:maven/com.squareup.okio/okio@1.17.2", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/protobuf-java-3.11.1.jar": "pkg:maven/com.google.protobuf/protobuf-java@3.11.1", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/trilead-putty-extension-1.2.jar": "pkg:maven/org.kohsuke/trilead-putty-extension@1.2", + "/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/trilead-ssh2-build-217-jenkins-27.jar:org.jenkins-ci:trilead-ssh2": "pkg:maven/org.jenkins-ci/trilead-ssh2@build-217-jenkins-27", + "/packages/aws-sam.hpi": "pkg:maven/io.jenkins.plugins/aws-sam@1.2.2", + "/packages/aws-sam.hpi:WEB-INF/lib/aws-sam.jar": "pkg:maven/io.jenkins.plugins/aws-sam@1.2.2", + "/packages/aws-sam.hpi:WEB-INF/lib/json-20180130.jar": "pkg:maven/org.json/json@20180130", + "/packages/aws-sam.hpi:WEB-INF/lib/snakeyaml-1.21.jar": "pkg:maven/org.yaml/snakeyaml@1.21", + "/packages/bc-fips-1.0.2.3.jar": "pkg:maven/org.bouncycastle/bc-fips@1.0.2.3", + "/packages/camel-core-3.1.0.jar": "pkg:maven/org.apache.camel/camel-core@3.1.0", + "/packages/cassandra-all-4.1.1.jar": "pkg:maven/org.apache.cassandra/cassandra-all@4.1.1", + "/packages/commons-logging-1.1.1.jar": "pkg:maven/commons-logging/commons-logging@1.1.1", + "/packages/commons-vfs-1.0.jar": "pkg:maven/commons-vfs/commons-vfs@1.0", + "/packages/cxf-rt-transports-http-2.7.3.jar": "pkg:maven/org.apache.cxf/cxf-rt-transports-http@2.7.3", + "/packages/dubbo-3.1.4.jar": "pkg:maven/org.apache.dubbo/dubbo@3.1.4", + "/packages/dubbo-3.1.4.jar:com.alibaba:hessian-lite": "pkg:maven/com.alibaba/hessian-lite@3.2.13", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-auth": "pkg:maven/org.apache.dubbo/dubbo-auth@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-cluster": "pkg:maven/org.apache.dubbo/dubbo-cluster@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-common": "pkg:maven/org.apache.dubbo/dubbo-common@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-compatible": "pkg:maven/org.apache.dubbo/dubbo-compatible@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-config-api": "pkg:maven/org.apache.dubbo/dubbo-config-api@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-config-spring": "pkg:maven/org.apache.dubbo/dubbo-config-spring@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-configcenter-apollo": "pkg:maven/org.apache.dubbo/dubbo-configcenter-apollo@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-configcenter-nacos": "pkg:maven/org.apache.dubbo/dubbo-configcenter-nacos@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-configcenter-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-configcenter-zookeeper@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-container-api": "pkg:maven/org.apache.dubbo/dubbo-container-api@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-container-spring": "pkg:maven/org.apache.dubbo/dubbo-container-spring@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-filter-cache": "pkg:maven/org.apache.dubbo/dubbo-filter-cache@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-filter-validation": "pkg:maven/org.apache.dubbo/dubbo-filter-validation@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-kubernetes": "pkg:maven/org.apache.dubbo/dubbo-kubernetes@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-api": "pkg:maven/org.apache.dubbo/dubbo-metadata-api@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-definition-protobuf": "pkg:maven/org.apache.dubbo/dubbo-metadata-definition-protobuf@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-report-nacos": "pkg:maven/org.apache.dubbo/dubbo-metadata-report-nacos@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-report-redis": "pkg:maven/org.apache.dubbo/dubbo-metadata-report-redis@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-report-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-metadata-report-zookeeper@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metrics-api": "pkg:maven/org.apache.dubbo/dubbo-metrics-api@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metrics-prometheus": "pkg:maven/org.apache.dubbo/dubbo-metrics-prometheus@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-monitor-api": "pkg:maven/org.apache.dubbo/dubbo-monitor-api@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-monitor-default": "pkg:maven/org.apache.dubbo/dubbo-monitor-default@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-qos": "pkg:maven/org.apache.dubbo/dubbo-qos@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-reactive": "pkg:maven/org.apache.dubbo/dubbo-reactive@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-api": "pkg:maven/org.apache.dubbo/dubbo-registry-api@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-multicast": "pkg:maven/org.apache.dubbo/dubbo-registry-multicast@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-multiple": "pkg:maven/org.apache.dubbo/dubbo-registry-multiple@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-nacos": "pkg:maven/org.apache.dubbo/dubbo-registry-nacos@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-registry-zookeeper@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-api": "pkg:maven/org.apache.dubbo/dubbo-remoting-api@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-http": "pkg:maven/org.apache.dubbo/dubbo-remoting-http@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-netty": "pkg:maven/org.apache.dubbo/dubbo-remoting-netty@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-netty4": "pkg:maven/org.apache.dubbo/dubbo-remoting-netty4@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-remoting-zookeeper@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-zookeeper-curator5": "pkg:maven/org.apache.dubbo/dubbo-remoting-zookeeper-curator5@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-api": "pkg:maven/org.apache.dubbo/dubbo-rpc-api@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-dubbo": "pkg:maven/org.apache.dubbo/dubbo-rpc-dubbo@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-grpc": "pkg:maven/org.apache.dubbo/dubbo-rpc-grpc@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-injvm": "pkg:maven/org.apache.dubbo/dubbo-rpc-injvm@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-rest": "pkg:maven/org.apache.dubbo/dubbo-rpc-rest@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-triple": "pkg:maven/org.apache.dubbo/dubbo-rpc-triple@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-api": "pkg:maven/org.apache.dubbo/dubbo-serialization-api@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-fastjson2": "pkg:maven/org.apache.dubbo/dubbo-serialization-fastjson2@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-hessian2": "pkg:maven/org.apache.dubbo/dubbo-serialization-hessian2@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-jdk": "pkg:maven/org.apache.dubbo/dubbo-serialization-jdk@3.1.4", + "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-xds": "pkg:maven/org.apache.dubbo/dubbo-xds@3.1.4", + "/packages/elasticsearch-8.10.2.jar": "pkg:maven/org.elasticsearch/elasticsearch@8.10.2", + "/packages/elasticsearch-rest-client-sniffer-7.17.11.jar": "pkg:maven/org.elasticsearch.client/elasticsearch-rest-client-sniffer@7.17.11", + "/packages/example-java-app-gradle-0.1.0.ear": "pkg:maven/example-java-app-gradle/example-java-app-gradle@0.1.0", + "/packages/generic-webhook-trigger.hpi": "pkg:maven/org.jenkins-ci.plugins/generic-webhook-trigger@1.71", + "/packages/generic-webhook-trigger.hpi:WEB-INF/lib/accessors-smart-1.2.jar": "pkg:maven/net.minidev/accessors-smart@1.2", + "/packages/generic-webhook-trigger.hpi:WEB-INF/lib/asm-5.0.4.jar": "pkg:maven/org.objectweb.asm/asm@5.0.4", + "/packages/generic-webhook-trigger.hpi:WEB-INF/lib/commons-ip-math-1.32.jar": "pkg:maven/com.github.jgonian/commons-ip-math@1.32", + "/packages/generic-webhook-trigger.hpi:WEB-INF/lib/generic-webhook-trigger.jar": "pkg:maven/org.jenkins-ci.plugins/generic-webhook-trigger@1.71", + "/packages/generic-webhook-trigger.hpi:WEB-INF/lib/gson-2.8.2.jar": "pkg:maven/com.google.code.gson/gson@2.8.2", + "/packages/generic-webhook-trigger.hpi:WEB-INF/lib/json-path-2.3.0.jar": "pkg:maven/com.jayway.jsonpath.json-path/json-path@2.3.0", + "/packages/generic-webhook-trigger.hpi:WEB-INF/lib/json-smart-2.3.jar": "pkg:maven/net.minidev/json-smart@2.3", + "/packages/geode-core-1.14.3.jar": "pkg:maven/org.apache.geode/geode-core@1.14.3", + "/packages/github-api-1.118.jar": "pkg:maven/org.kohsuke/github-api@1.118", + "/packages/google-oauth-client-1.25.0.jar": "pkg:maven/com.google.oauth-client/google-oauth-client@1.25.0", + "/packages/gradle-7.1.1/lib/annotations-20.1.0.jar": "pkg:maven/org.jetbrains.annotations/annotations@20.1.0", + "/packages/gradle-7.1.1/lib/ant-1.10.9.jar": "pkg:maven/org.apache.ant/ant@1.10.9", + "/packages/gradle-7.1.1/lib/ant-antlr-1.10.9.jar": "pkg:maven/org.apache.ant/ant-antlr@1.10.9", + "/packages/gradle-7.1.1/lib/ant-junit-1.10.9.jar": "pkg:maven/org.apache.ant/ant-junit@1.10.9", + "/packages/gradle-7.1.1/lib/ant-launcher-1.10.9.jar": "pkg:maven/org.apache.ant/ant-launcher@1.10.9", + "/packages/gradle-7.1.1/lib/antlr4-runtime-4.7.2.jar": "pkg:maven/org.antlr/antlr4-runtime@4.7.2", + "/packages/gradle-7.1.1/lib/asm-9.1.jar": "pkg:maven/org.objectweb.asm/asm@9.1", + "/packages/gradle-7.1.1/lib/commons-compress-1.20.jar": "pkg:maven/org.apache.commons/commons-compress@1.20", + "/packages/gradle-7.1.1/lib/commons-io-2.6.jar": "pkg:maven/commons-io/commons-io@2.6", + "/packages/gradle-7.1.1/lib/commons-lang-2.6.jar": "pkg:maven/commons-lang/commons-lang@2.6", + "/packages/gradle-7.1.1/lib/failureaccess-1.0.1.jar": "pkg:maven/com.google.guava/failureaccess@1.0.1", + "/packages/gradle-7.1.1/lib/groovy-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy@3.0.7", + "/packages/gradle-7.1.1/lib/groovy-ant-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-ant@3.0.7", + "/packages/gradle-7.1.1/lib/groovy-astbuilder-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-astbuilder@3.0.7", + "/packages/gradle-7.1.1/lib/groovy-console-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-console@3.0.7", + "/packages/gradle-7.1.1/lib/groovy-datetime-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-datetime@3.0.7", + "/packages/gradle-7.1.1/lib/groovy-dateutil-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-dateutil@3.0.7", + "/packages/gradle-7.1.1/lib/groovy-docgenerator-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-docgenerator@3.0.7", + "/packages/gradle-7.1.1/lib/groovy-groovydoc-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-groovydoc@3.0.7", + "/packages/gradle-7.1.1/lib/groovy-json-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-json@3.0.7", + "/packages/gradle-7.1.1/lib/groovy-nio-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-nio@3.0.7", + "/packages/gradle-7.1.1/lib/groovy-sql-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-sql@3.0.7", + "/packages/gradle-7.1.1/lib/groovy-swing-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-swing@3.0.7", + "/packages/gradle-7.1.1/lib/groovy-templates-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-templates@3.0.7", + "/packages/gradle-7.1.1/lib/groovy-test-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-test@3.0.7", + "/packages/gradle-7.1.1/lib/groovy-xml-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-xml@3.0.7", + "/packages/gradle-7.1.1/lib/guava-27.1-android.jar": "pkg:maven/com.google.guava/guava@27.1-android", + "/packages/gradle-7.1.1/lib/jansi-1.18.jar": "pkg:maven/org.fusesource.jansi/jansi@1.18", + "/packages/gradle-7.1.1/lib/jansi-1.18.jar:org.fusesource.hawtjni:hawtjni-runtime": "pkg:maven/org.fusesource.hawtjni/hawtjni-runtime@1.17", + "/packages/gradle-7.1.1/lib/jansi-1.18.jar:org.fusesource.jansi:jansi-freebsd32": "pkg:maven/org.fusesource.jansi/jansi-freebsd32@1.8", + "/packages/gradle-7.1.1/lib/jansi-1.18.jar:org.fusesource.jansi:jansi-freebsd64": "pkg:maven/org.fusesource.jansi/jansi-freebsd64@1.8", + "/packages/gradle-7.1.1/lib/jansi-1.18.jar:org.fusesource.jansi:jansi-linux32": "pkg:maven/org.fusesource.jansi/jansi-linux32@1.8", + "/packages/gradle-7.1.1/lib/jansi-1.18.jar:org.fusesource.jansi:jansi-linux64": "pkg:maven/org.fusesource.jansi/jansi-linux64@1.8", + "/packages/gradle-7.1.1/lib/jansi-1.18.jar:org.fusesource.jansi:jansi-native": "pkg:maven/org.fusesource.jansi/jansi-native@1.8", + "/packages/gradle-7.1.1/lib/jansi-1.18.jar:org.fusesource.jansi:jansi-osx": "pkg:maven/org.fusesource.jansi/jansi-osx@1.8", + "/packages/gradle-7.1.1/lib/jansi-1.18.jar:org.fusesource.jansi:jansi-windows32": "pkg:maven/org.fusesource.jansi/jansi-windows32@1.8", + "/packages/gradle-7.1.1/lib/jansi-1.18.jar:org.fusesource.jansi:jansi-windows64": "pkg:maven/org.fusesource.jansi/jansi-windows64@1.8", + "/packages/gradle-7.1.1/lib/javaparser-core-3.17.0.jar": "pkg:maven/com.github.javaparser/javaparser-core@3.17.0", + "/packages/gradle-7.1.1/lib/jcl-over-slf4j-1.7.30.jar": "pkg:maven/org.slf4j/jcl-over-slf4j@1.7.30", + "/packages/gradle-7.1.1/lib/jsr305-3.0.2.jar": "pkg:maven/com.google.code.findbugs/jsr305@3.0.2", + "/packages/gradle-7.1.1/lib/jul-to-slf4j-1.7.30.jar": "pkg:maven/org.slf4j/jul-to-slf4j@1.7.30", + "/packages/gradle-7.1.1/lib/junit-4.13.2.jar": "pkg:maven/junit/junit@4.13.2", + "/packages/gradle-7.1.1/lib/kryo-2.24.0.jar": "pkg:maven/com.esotericsoftware.kryo/kryo@2.24.0", + "/packages/gradle-7.1.1/lib/kryo-2.24.0.jar:com.esotericsoftware.reflectasm:reflectasm": "pkg:maven/com.esotericsoftware.reflectasm/reflectasm@1.09", + "/packages/gradle-7.1.1/lib/log4j-over-slf4j-1.7.30.jar": "pkg:maven/org.slf4j/log4j-over-slf4j@1.7.30", + "/packages/gradle-7.1.1/lib/minlog-1.2.jar": "pkg:maven/com.esotericsoftware.minlog/minlog@1.2", + "/packages/gradle-7.1.1/lib/objenesis-2.6.jar": "pkg:maven/org.objenesis/objenesis@2.6", + "/packages/gradle-7.1.1/lib/plugins/aws-java-sdk-core-1.11.948.jar": "pkg:maven/com.amazonaws/aws-java-sdk-core@1.11.948", + "/packages/gradle-7.1.1/lib/plugins/aws-java-sdk-kms-1.11.948.jar": "pkg:maven/com.amazonaws/aws-java-sdk-kms@1.11.948", + "/packages/gradle-7.1.1/lib/plugins/aws-java-sdk-s3-1.11.948.jar": "pkg:maven/com.amazonaws/aws-java-sdk-s3@1.11.948", + "/packages/gradle-7.1.1/lib/plugins/aws-java-sdk-sts-1.11.948.jar": "pkg:maven/com.amazonaws/aws-java-sdk-sts@1.11.948", + "/packages/gradle-7.1.1/lib/plugins/bcpg-jdk15on-1.68.jar": "pkg:maven/org.bouncycastle/bcpg-jdk15on@1.68", + "/packages/gradle-7.1.1/lib/plugins/bcpkix-jdk15on-1.68.jar": "pkg:maven/org.bouncycastle/bcpkix-jdk15on@1.68", + "/packages/gradle-7.1.1/lib/plugins/bcprov-jdk15on-1.68.jar": "pkg:maven/org.bouncycastle/bcprov-jdk15on@1.68", + "/packages/gradle-7.1.1/lib/plugins/commons-codec-1.15.jar": "pkg:maven/commons-codec/commons-codec@1.15", + "/packages/gradle-7.1.1/lib/plugins/dd-plist-1.21.jar": "pkg:maven/com.googlecode.plist/dd-plist@1.21", + "/packages/gradle-7.1.1/lib/plugins/google-api-services-storage-v1-rev171-1.25.0.jar:com.google.apis:google-api-services-storage": "pkg:maven/com.google.apis/google-api-services-storage@v1-rev171-1.25.0", + "/packages/gradle-7.1.1/lib/plugins/google-http-client-1.25.0.jar": "pkg:maven/com.google.http-client/google-http-client@1.25.0", + "/packages/gradle-7.1.1/lib/plugins/google-http-client-jackson2-1.25.0.jar": "pkg:maven/com.google.http-client/google-http-client-jackson2@1.25.0", + "/packages/gradle-7.1.1/lib/plugins/google-oauth-client-1.25.0.jar": "pkg:maven/com.google.oauth-client/google-oauth-client@1.25.0", + "/packages/gradle-7.1.1/lib/plugins/gson-2.8.6.jar": "pkg:maven/com.google.code.gson/gson@2.8.6", + "/packages/gradle-7.1.1/lib/plugins/httpclient-4.5.13.jar": "pkg:maven/org.apache.httpcomponents/httpclient@4.5.13", + "/packages/gradle-7.1.1/lib/plugins/httpcore-4.4.14.jar": "pkg:maven/org.apache.httpcomponents/httpcore@4.4.14", + "/packages/gradle-7.1.1/lib/plugins/ion-java-1.0.2.jar": "pkg:maven/software.amazon.ion/ion-java@1.0.2", + "/packages/gradle-7.1.1/lib/plugins/jackson-annotations-2.12.1.jar": "pkg:maven/com.fasterxml.jackson.core/jackson-annotations@2.12.1", + "/packages/gradle-7.1.1/lib/plugins/jackson-core-2.12.1.jar": "pkg:maven/com.fasterxml.jackson.core/jackson-core@2.12.1", + "/packages/gradle-7.1.1/lib/plugins/jackson-databind-2.12.1.jar": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.12.1", + "/packages/gradle-7.1.1/lib/plugins/jakarta.activation-2.0.0.jar": "pkg:maven/com.sun.activation/jakarta.activation@2.0.0", + "/packages/gradle-7.1.1/lib/plugins/jakarta.xml.bind-api-3.0.0.jar": "pkg:maven/jakarta.xml.bind/jakarta.xml.bind-api@3.0.0", + "/packages/gradle-7.1.1/lib/plugins/jatl-0.2.3.jar": "pkg:maven/com.googlecode.jatl/jatl@0.2.3", + "/packages/gradle-7.1.1/lib/plugins/jaxb-core-3.0.0.jar:com.sun.istack:istack-commons-runtime": "pkg:maven/com.sun.istack/istack-commons-runtime@4.0.0", + "/packages/gradle-7.1.1/lib/plugins/jaxb-core-3.0.0.jar:org.glassfish.jaxb:txw2": "pkg:maven/org.glassfish.jaxb/txw2@3.0.0", + "/packages/gradle-7.1.1/lib/plugins/jaxb-impl-3.0.0.jar": "pkg:maven/com.sun.xml.bind/jaxb-impl@3.0.0", + "/packages/gradle-7.1.1/lib/plugins/jaxb-impl-3.0.0.jar:org.glassfish.jaxb:jaxb-runtime": "pkg:maven/org.glassfish.jaxb/jaxb-runtime@3.0.0", + "/packages/gradle-7.1.1/lib/plugins/jcifs-1.3.17.jar": "pkg:maven/jcifs/jcifs@1.3.17", + "/packages/gradle-7.1.1/lib/plugins/jmespath-java-1.11.948.jar": "pkg:maven/com.amazonaws/jmespath-java@1.11.948", + "/packages/gradle-7.1.1/lib/plugins/joda-time-2.10.4.jar": "pkg:maven/joda-time/joda-time@2.10.4", + "/packages/gradle-7.1.1/lib/plugins/jsch-0.1.55.jar": "pkg:maven/com.jcraft/jsch@0.1.55", + "/packages/gradle-7.1.1/lib/plugins/jzlib-1.1.3.jar": "pkg:maven/com.jcraft/jzlib@1.1.3", + "/packages/gradle-7.1.1/lib/plugins/maven-builder-support-3.6.3.jar": "pkg:maven/org.apache.maven/maven-builder-support@3.6.3", + "/packages/gradle-7.1.1/lib/plugins/maven-model-3.6.3.jar": "pkg:maven/org.apache.maven/maven-model@3.6.3", + "/packages/gradle-7.1.1/lib/plugins/maven-repository-metadata-3.6.3.jar": "pkg:maven/org.apache.maven/maven-repository-metadata@3.6.3", + "/packages/gradle-7.1.1/lib/plugins/maven-settings-3.6.3.jar": "pkg:maven/org.apache.maven/maven-settings@3.6.3", + "/packages/gradle-7.1.1/lib/plugins/maven-settings-builder-3.6.3.jar": "pkg:maven/org.apache.maven/maven-settings-builder@3.6.3", + "/packages/gradle-7.1.1/lib/plugins/opentest4j-1.2.0.jar": "pkg:maven/org.opentest4j/opentest4j@1.2.0", + "/packages/gradle-7.1.1/lib/plugins/org.eclipse.jgit-5.7.0.202003110725-r.jar": "pkg:maven/org.eclipse.jgit/org.eclipse.jgit@5.7.0.202003110725-r", + "/packages/gradle-7.1.1/lib/plugins/plexus-cipher-1.7.jar": "pkg:maven/org.sonatype.plexus/plexus-cipher@1.7", + "/packages/gradle-7.1.1/lib/plugins/plexus-interpolation-1.26.jar": "pkg:maven/org.codehaus.plexus/plexus-interpolation@1.26", + "/packages/gradle-7.1.1/lib/plugins/plexus-sec-dispatcher-1.4.jar": "pkg:maven/org.sonatype.plexus/plexus-sec-dispatcher@1.4", + "/packages/gradle-7.1.1/lib/plugins/plexus-utils-3.3.0.jar": "pkg:maven/org.codehaus.plexus/plexus-utils@3.3.0", + "/packages/gradle-7.1.1/lib/plugins/snakeyaml-1.28.jar": "pkg:maven/org.yaml/snakeyaml@1.28", + "/packages/gradle-7.1.1/lib/plugins/testng-6.3.1.jar": "pkg:maven/org.testng/testng@6.3.1", + "/packages/gradle-7.1.1/lib/plugins/xercesImpl-2.12.0.jar": "pkg:maven/org.apache.xerces.impl.Version/xercesImpl@2.12.0", + "/packages/gradle-7.1.1/lib/qdox-1.12.1.jar": "pkg:maven/com.thoughtworks.qdox/qdox@1.12.1", + "/packages/gradle-7.1.1/lib/slf4j-api-1.7.30.jar": "pkg:maven/org.slf4j/slf4j-api@1.7.30", + "/packages/gradle.hpi": "pkg:maven/org.jenkins-ci.plugins/gradle@1.36", + "/packages/gradle.hpi:WEB-INF/lib/gradle-plugin-1.36.jar": "pkg:maven/org.jenkins-ci.plugins/gradle-plugin@1.36", + "/packages/graphql-java-20.0.jar": "pkg:maven/com.graphql-java/graphql-java@20.0", "/packages/graphql-java-20.0.jar:com.google.guava:guava": "pkg:maven/com.google.guava/guava@31.0.1-jre", "/packages/graphql-java-20.0.jar:org.antlr:antlr4-runtime": "pkg:maven/org.antlr/antlr4-runtime@4.9.3", - "/packages/graphql-java-20.0.jar": "pkg:maven/com.graphql-java/graphql-java@20.0", "/packages/guava-29.0-jre.jar": "pkg:maven/com.google.guava/guava@29.0-jre", "/packages/hadoop-common-3.3.2.jar": "pkg:maven/org.apache.hadoop/hadoop-common@3.3.2", + "/packages/hazelcast-5.2.4.jar": "pkg:maven/com.hazelcast/hazelcast@5.2.4", "/packages/hazelcast-5.2.4.jar:com.fasterxml.jackson.core:jackson-core": "pkg:maven/com.fasterxml.jackson.core/jackson-core@2.15.2", "/packages/hazelcast-5.2.4.jar:com.fasterxml.jackson.jr:jackson-jr-annotation-support": "pkg:maven/com.fasterxml.jackson.jr/jackson-jr-annotation-support@2.15.2", "/packages/hazelcast-5.2.4.jar:com.fasterxml.jackson.jr:jackson-jr-objects": "pkg:maven/com.fasterxml.jackson.jr/jackson-jr-objects@2.15.2", @@ -148,7 +439,6 @@ var expectedPURLs = map[string]string{ "/packages/hazelcast-5.2.4.jar:io.github.classgraph:classgraph": "pkg:maven/io.github.classgraph/classgraph@4.8.149", "/packages/hazelcast-5.2.4.jar:org.json:json": "pkg:maven/org.json/json@20230227", "/packages/hazelcast-5.2.4.jar:org.snakeyaml:snakeyaml-engine": "pkg:maven/org.snakeyaml/snakeyaml-engine@2.3", - "/packages/hazelcast-5.2.4.jar": "pkg:maven/com.hazelcast/hazelcast@5.2.4", "/packages/hibernate-validator-6.1.3.Final.jar": "pkg:maven/org.hibernate.validator/hibernate-validator@6.1.3.Final", "/packages/http2-common-11.0.16.jar": "pkg:maven/org.eclipse.jetty.http2/http2-common@11.0.16", "/packages/hudson.war:WEB-INF/hudson-cli.jar:args4j:args4j": "pkg:maven/args4j/args4j@2.0.16", @@ -305,29 +595,105 @@ var expectedPURLs = map[string]string{ "/packages/jetty-server-12.0.0.alpha3.jar": "pkg:maven/org.eclipse.jetty/jetty-server@12.0.0.alpha3", "/packages/jetty-setuid-java-1.0.4.jar": "pkg:maven/org.eclipse.jetty.toolchain.setuid/jetty-setuid-java@1.0.4", "/packages/jmdns-3.4.1.jar": "pkg:maven/javax.jmdns/jmdns@3.4.1", - "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/jopenssl.jar:rubygems:jruby-openssl": "pkg:maven/rubygems/jruby-openssl@0.9.21", + "/packages/jruby-stdlib-9.1.15.0.jar": "pkg:maven/org.jruby/jruby-stdlib@9.1.15.0", "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/org/bouncycastle/bcpkix-jdk15on/1.56/bcpkix-jdk15on-1.56.jar": "pkg:maven/org.bouncycastle/bcpkix-jdk15on@1.56", "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/org/bouncycastle/bcprov-jdk15on/1.56/bcprov-jdk15on-1.56.jar": "pkg:maven/org.bouncycastle/bcprov-jdk15on@1.56", "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/org/yaml/snakeyaml/1.18/snakeyaml-1.18.jar": "pkg:maven/org.yaml/snakeyaml@1.18", - "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/readline.jar:jline:jline": "pkg:maven/jline/jline@2.11", - "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/readline.jar:rubygems:jruby-readline": "pkg:maven/rubygems/jruby-readline@1.2.0", - "/packages/jruby-stdlib-9.1.15.0.jar": "pkg:maven/org.jruby/jruby-stdlib@9.1.15.0", - "/packages/jsch-0.1.55.jar": "pkg:maven/com.jcraft/jsch@0.1.55", - "/packages/junit-4.13.1.jar": "pkg:maven/junit/junit@4.13.1", - "/packages/kafka_2.13-3.2.2.jar": "pkg:maven/org.apache.kafka/kafka_2.13@3.2.2", - "/packages/keycloak-core-22.0.2.jar": "pkg:maven/org.keycloak/keycloak-core@22.0.2", - "/packages/log4j-1.2.16.jar": "pkg:maven/log4j/log4j@1.2.16", - "/packages/log4j-core-2.17.0.jar": "pkg:maven/org.apache.logging.log4j/log4j-core@2.17.0", - "/packages/log4j-over-slf4j-1.7.36.jar": "pkg:maven/org.slf4j/log4j-over-slf4j@1.7.36", - "/packages/manager-pojo-1.8.0.jar": "pkg:maven/org.apache.inlong/manager-pojo@1.8.0", + "/packages/jsch-0.1.55.jar": "pkg:maven/com.jcraft/jsch@0.1.55", + "/packages/junit-4.13.1.jar": "pkg:maven/junit/junit@4.13.1", + "/packages/junit.hpi": "pkg:maven/org.jenkins-ci.plugins/junit@1.25", + "/packages/junit.hpi:WEB-INF/lib/junit.jar": "pkg:maven/org.jenkins-ci.plugins/junit@1.25", + "/packages/kafka_2.13-3.2.2.jar": "pkg:maven/org.apache.kafka/kafka_2.13@3.2.2", + "/packages/keycloak-core-22.0.2.jar": "pkg:maven/org.keycloak/keycloak-core@22.0.2", + "/packages/log4j-1.2.16.jar": "pkg:maven/log4j/log4j@1.2.16", + "/packages/log4j-core-2.17.0.jar": "pkg:maven/org.apache.logging.log4j/log4j-core@2.17.0", + "/packages/log4j-over-slf4j-1.7.36.jar": "pkg:maven/org.slf4j/log4j-over-slf4j@1.7.36", + "/packages/manager-pojo-1.8.0.jar": "pkg:maven/org.apache.inlong/manager-pojo@1.8.0", + "/packages/maven-plugin.hpi": "pkg:maven/org.jenkins-ci.main/maven-plugin@3.10.1", + "/packages/maven-plugin.hpi:WEB-INF/lib/annotations-3.0.1.jar": "pkg:maven/com.google.code.findbugs/annotations@3.0.1", + "/packages/maven-plugin.hpi:WEB-INF/lib/annotations-3.0.1.jar:com.google.code.findbugs:jsr305": "pkg:maven/com.google.code.findbugs/jsr305@3.0.1", + "/packages/maven-plugin.hpi:WEB-INF/lib/cdi-api-1.0.jar": "pkg:maven/javax.enterprise/cdi-api@1.0", + "/packages/maven-plugin.hpi:WEB-INF/lib/commons-cli-1.4.jar": "pkg:maven/commons-cli/commons-cli@1.4", + "/packages/maven-plugin.hpi:WEB-INF/lib/commons-lang3-3.11.jar": "pkg:maven/org.apache.commons/commons-lang3@3.11", + "/packages/maven-plugin.hpi:WEB-INF/lib/commons-net-3.6.jar": "pkg:maven/commons-net/commons-net@3.6", + "/packages/maven-plugin.hpi:WEB-INF/lib/doxia-sink-api-1.0.jar": "pkg:maven/org.apache.maven.doxia/doxia-sink-api@1.0", + "/packages/maven-plugin.hpi:WEB-INF/lib/jackrabbit-webdav-2.14.4.jar": "pkg:maven/org.apache.jackrabbit/jackrabbit-webdav@2.14.4", + "/packages/maven-plugin.hpi:WEB-INF/lib/jcl-over-slf4j-1.7.30.jar": "pkg:maven/org.slf4j/jcl-over-slf4j@1.7.30", + "/packages/maven-plugin.hpi:WEB-INF/lib/jna-platform-4.1.0.jar": "pkg:maven/com.sun.jna.platform/jna-platform@4.1.0", + "/packages/maven-plugin.hpi:WEB-INF/lib/jsch.agentproxy.connector-factory-0.0.9.jar": "pkg:maven/com.jcraft/jsch.agentproxy.connector-factory@0.0.9", + "/packages/maven-plugin.hpi:WEB-INF/lib/jsch.agentproxy.core-0.0.9.jar": "pkg:maven/com.jcraft/jsch.agentproxy.core@0.0.9", + "/packages/maven-plugin.hpi:WEB-INF/lib/jsch.agentproxy.jsch-0.0.9.jar": "pkg:maven/com.jcraft/jsch.agentproxy.jsch@0.0.9", + "/packages/maven-plugin.hpi:WEB-INF/lib/jsch.agentproxy.pageant-0.0.9.jar": "pkg:maven/com.jcraft/jsch.agentproxy.pageant@0.0.9", + "/packages/maven-plugin.hpi:WEB-INF/lib/jsch.agentproxy.sshagent-0.0.9.jar": "pkg:maven/com.jcraft/jsch.agentproxy.sshagent@0.0.9", + "/packages/maven-plugin.hpi:WEB-INF/lib/jsch.agentproxy.usocket-jna-0.0.9.jar": "pkg:maven/com.jcraft/jsch.agentproxy.usocket-jna@0.0.9", + "/packages/maven-plugin.hpi:WEB-INF/lib/jsch.agentproxy.usocket-nc-0.0.9.jar": "pkg:maven/com.jcraft/jsch.agentproxy.usocket-nc@0.0.9", + "/packages/maven-plugin.hpi:WEB-INF/lib/jsoup-1.12.1.jar": "pkg:maven/org.jsoup/jsoup@1.12.1", + "/packages/maven-plugin.hpi:WEB-INF/lib/lib-jenkins-maven-artifact-manager-1.2.jar": "pkg:maven/org.jenkins-ci.lib/lib-jenkins-maven-artifact-manager@1.2", + "/packages/maven-plugin.hpi:WEB-INF/lib/lib-jenkins-maven-embedder-3.15.jar": "pkg:maven/org.jenkins-ci.lib/lib-jenkins-maven-embedder@3.15", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-agent-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven-agent@1.13", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-artifact-3.5.4.jar": "pkg:maven/org.apache.maven/maven-artifact@3.5.4", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-builder-support-3.5.4.jar": "pkg:maven/org.apache.maven/maven-builder-support@3.5.4", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-compat-3.5.4.jar": "pkg:maven/org.apache.maven/maven-compat@3.5.4", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-core-3.5.4.jar": "pkg:maven/org.apache.maven/maven-core@3.5.4", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-embedder-3.5.4.jar": "pkg:maven/org.apache.maven/maven-embedder@3.5.4", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-interceptor-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven-interceptor@1.13", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-model-3.5.4.jar": "pkg:maven/org.apache.maven/maven-model@3.5.4", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-model-builder-3.5.4.jar": "pkg:maven/org.apache.maven/maven-model-builder@3.5.4", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-plugin-api-3.5.4.jar": "pkg:maven/org.apache.maven/maven-plugin-api@3.5.4", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-plugin.jar": "pkg:maven/org.jenkins-ci.main/maven-plugin@3.10.1", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-plugin.jar:classworlds.jar": "pkg:maven/org.codehaus.classworlds/classworlds@1.1", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-reporting-api-3.0.jar": "pkg:maven/org.apache.maven.reporting/maven-reporting-api@3.0", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-repository-metadata-3.5.4.jar": "pkg:maven/org.apache.maven/maven-repository-metadata@3.5.4", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-resolver-api-1.1.1.jar": "pkg:maven/org.apache.maven.resolver/maven-resolver-api@1.1.1", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-resolver-connector-basic-1.1.1.jar": "pkg:maven/org.apache.maven.resolver/maven-resolver-connector-basic@1.1.1", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-resolver-impl-1.1.1.jar": "pkg:maven/org.apache.maven.resolver/maven-resolver-impl@1.1.1", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-resolver-provider-3.5.4.jar": "pkg:maven/org.apache.maven/maven-resolver-provider@3.5.4", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-resolver-spi-1.1.1.jar": "pkg:maven/org.apache.maven.resolver/maven-resolver-spi@1.1.1", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-resolver-transport-wagon-1.1.1.jar": "pkg:maven/org.apache.maven.resolver/maven-resolver-transport-wagon@1.1.1", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-resolver-util-1.1.1.jar": "pkg:maven/org.apache.maven.resolver/maven-resolver-util@1.1.1", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-settings-3.5.4.jar": "pkg:maven/org.apache.maven/maven-settings@3.5.4", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-settings-builder-3.5.4.jar": "pkg:maven/org.apache.maven/maven-settings-builder@3.5.4", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven-shared-utils-3.2.1.jar": "pkg:maven/org.apache.maven.shared/maven-shared-utils@3.2.1", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven2.1-interceptor-1.2.jar": "pkg:maven/org.jvnet.hudson/maven2.1-interceptor@1.2", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven3-agent-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven3-agent@1.13", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven3-interceptor-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven3-interceptor@1.13", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven3-interceptor-commons-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven3-interceptor-commons@1.13", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven31-agent-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven31-agent@1.13", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven31-interceptor-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven31-interceptor@1.13", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven32-agent-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven32-agent@1.13", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven32-interceptor-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven32-interceptor@1.13", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven33-agent-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven33-agent@1.13", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven33-interceptor-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven33-interceptor@1.13", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven35-agent-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven35-agent@1.13", + "/packages/maven-plugin.hpi:WEB-INF/lib/maven35-interceptor-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven35-interceptor@1.13", + "/packages/maven-plugin.hpi:WEB-INF/lib/org.eclipse.sisu.inject-0.3.3.jar": "pkg:maven/org.eclipse.sisu.inject/org.eclipse.sisu.inject@0.3.3", + "/packages/maven-plugin.hpi:WEB-INF/lib/org.eclipse.sisu.plexus-0.3.3.jar": "pkg:maven/org.eclipse.sisu.plexus/org.eclipse.sisu.plexus@0.3.3", + "/packages/maven-plugin.hpi:WEB-INF/lib/plexus-cipher-1.8.jar": "pkg:maven/org.codehaus.plexus/plexus-cipher@1.8", + "/packages/maven-plugin.hpi:WEB-INF/lib/plexus-classworlds-2.6.0.jar": "pkg:maven/org.codehaus.plexus/plexus-classworlds@2.6.0", + "/packages/maven-plugin.hpi:WEB-INF/lib/plexus-component-annotations-2.1.0.jar": "pkg:maven/org.codehaus.plexus/plexus-component-annotations@2.1.0", + "/packages/maven-plugin.hpi:WEB-INF/lib/plexus-interactivity-api-1.0.jar": "pkg:maven/org.codehaus.plexus/plexus-interactivity-api@1.0", + "/packages/maven-plugin.hpi:WEB-INF/lib/plexus-interpolation-1.24.jar": "pkg:maven/org.codehaus.plexus/plexus-interpolation@1.24", + "/packages/maven-plugin.hpi:WEB-INF/lib/plexus-sec-dispatcher-1.4.jar": "pkg:maven/org.sonatype.plexus/plexus-sec-dispatcher@1.4", + "/packages/maven-plugin.hpi:WEB-INF/lib/plexus-utils-3.3.0.jar": "pkg:maven/org.codehaus.plexus/plexus-utils@3.3.0", + "/packages/maven-plugin.hpi:WEB-INF/lib/slf4j-api-1.7.30.jar": "pkg:maven/org.slf4j/slf4j-api@1.7.30", + "/packages/maven-plugin.hpi:WEB-INF/lib/wagon-file-3.4.3.jar": "pkg:maven/org.apache.maven.wagon/wagon-file@3.4.3", + "/packages/maven-plugin.hpi:WEB-INF/lib/wagon-ftp-3.4.3.jar": "pkg:maven/org.apache.maven.wagon/wagon-ftp@3.4.3", + "/packages/maven-plugin.hpi:WEB-INF/lib/wagon-http-3.4.3.jar": "pkg:maven/org.apache.maven.wagon/wagon-http@3.4.3", + "/packages/maven-plugin.hpi:WEB-INF/lib/wagon-http-shared-3.4.3.jar": "pkg:maven/org.apache.maven.wagon/wagon-http-shared@3.4.3", + "/packages/maven-plugin.hpi:WEB-INF/lib/wagon-provider-api-3.4.3.jar": "pkg:maven/org.apache.maven.wagon/wagon-provider-api@3.4.3", + "/packages/maven-plugin.hpi:WEB-INF/lib/wagon-ssh-3.4.3.jar": "pkg:maven/org.apache.maven.wagon/wagon-ssh@3.4.3", + "/packages/maven-plugin.hpi:WEB-INF/lib/wagon-ssh-common-3.4.3.jar": "pkg:maven/org.apache.maven.wagon/wagon-ssh-common@3.4.3", + "/packages/maven-plugin.hpi:WEB-INF/lib/wagon-ssh-external-3.4.3.jar": "pkg:maven/org.apache.maven.wagon/wagon-ssh-external@3.4.3", + "/packages/maven-plugin.hpi:WEB-INF/lib/wagon-webdav-jackrabbit-3.4.3.jar": "pkg:maven/org.apache.maven.wagon/wagon-webdav-jackrabbit@3.4.3", "/packages/maven-shared-utils-3.2.1.jar": "pkg:maven/org.apache.maven.shared/maven-shared-utils@3.2.1", "/packages/mesos-1.7.1.jar": "pkg:maven/org.apache.mesos/mesos@1.7.1", "/packages/minio-8.3.8.jar": "pkg:maven/io.minio/minio@8.3.8", "/packages/ms-mcms-5.3.1.jar": "pkg:maven/net.mingsoft/ms-mcms@5.3.1", - "/packages/my-app-1.jar:com.fasterxml:classmate": "pkg:maven/com.fasterxml/classmate@1.5.1", + "/packages/my-app-1.jar": "pkg:maven/com.mycompany.app/my-app@1", "/packages/my-app-1.jar:com.fasterxml.jackson.core:jackson-annotations": "pkg:maven/com.fasterxml.jackson.core/jackson-annotations@2.13.2", "/packages/my-app-1.jar:com.fasterxml.jackson.core:jackson-core": "pkg:maven/com.fasterxml.jackson.core/jackson-core@2.13.2", "/packages/my-app-1.jar:com.fasterxml.jackson.core:jackson-databind": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.0", + "/packages/my-app-1.jar:com.fasterxml:classmate": "pkg:maven/com.fasterxml/classmate@1.5.1", "/packages/my-app-1.jar:com.google.errorprone:error_prone_annotations": "pkg:maven/com.google.errorprone/error_prone_annotations@2.0.18", "/packages/my-app-1.jar:com.google.guava:guava": "pkg:maven/com.google.guava/guava@23.0", "/packages/my-app-1.jar:com.google.j2objc:j2objc-annotations": "pkg:maven/com.google.j2objc/j2objc-annotations@1.1", @@ -341,23 +707,23 @@ var expectedPURLs = map[string]string{ "/packages/my-app-1.jar:commons-logging:commons-logging": "pkg:maven/commons-logging/commons-logging@1.2", "/packages/my-app-1.jar:commons-validator:commons-validator": "pkg:maven/commons-validator/commons-validator@1.5.1", "/packages/my-app-1.jar:io.netty:netty-buffer": "pkg:maven/io.netty/netty-buffer@4.1.52.Final", + "/packages/my-app-1.jar:io.netty:netty-codec": "pkg:maven/io.netty/netty-codec@4.1.52.Final", "/packages/my-app-1.jar:io.netty:netty-codec-dns": "pkg:maven/io.netty/netty-codec-dns@4.1.63.Final", "/packages/my-app-1.jar:io.netty:netty-codec-http": "pkg:maven/io.netty/netty-codec-http@4.1.63.Final", "/packages/my-app-1.jar:io.netty:netty-codec-socks": "pkg:maven/io.netty/netty-codec-socks@4.1.63.Final", - "/packages/my-app-1.jar:io.netty:netty-codec": "pkg:maven/io.netty/netty-codec@4.1.52.Final", "/packages/my-app-1.jar:io.netty:netty-common": "pkg:maven/io.netty/netty-common@4.1.52.Final", - "/packages/my-app-1.jar:io.netty:netty-handler-proxy": "pkg:maven/io.netty/netty-handler-proxy@4.1.63.Final", "/packages/my-app-1.jar:io.netty:netty-handler": "pkg:maven/io.netty/netty-handler@4.1.52.Final", - "/packages/my-app-1.jar:io.netty:netty-resolver-dns-native-macos": "pkg:maven/io.netty/netty-resolver-dns-native-macos@4.1.63.Final", - "/packages/my-app-1.jar:io.netty:netty-resolver-dns": "pkg:maven/io.netty/netty-resolver-dns@4.1.63.Final", + "/packages/my-app-1.jar:io.netty:netty-handler-proxy": "pkg:maven/io.netty/netty-handler-proxy@4.1.63.Final", "/packages/my-app-1.jar:io.netty:netty-resolver": "pkg:maven/io.netty/netty-resolver@4.1.52.Final", + "/packages/my-app-1.jar:io.netty:netty-resolver-dns": "pkg:maven/io.netty/netty-resolver-dns@4.1.63.Final", + "/packages/my-app-1.jar:io.netty:netty-resolver-dns-native-macos": "pkg:maven/io.netty/netty-resolver-dns-native-macos@4.1.63.Final", + "/packages/my-app-1.jar:io.netty:netty-transport": "pkg:maven/io.netty/netty-transport@4.1.52.Final", "/packages/my-app-1.jar:io.netty:netty-transport-native-epoll": "pkg:maven/io.netty/netty-transport-native-epoll@4.1.63.Final", "/packages/my-app-1.jar:io.netty:netty-transport-native-unix-common": "pkg:maven/io.netty/netty-transport-native-unix-common@4.1.63.Final", - "/packages/my-app-1.jar:io.netty:netty-transport": "pkg:maven/io.netty/netty-transport@4.1.52.Final", - "/packages/my-app-1.jar:io.prometheus:simpleclient_common": "pkg:maven/io.prometheus/simpleclient_common@0.9.0", "/packages/my-app-1.jar:io.prometheus:simpleclient": "pkg:maven/io.prometheus/simpleclient@0.9.0", - "/packages/my-app-1.jar:io.vavr:vavr-match": "pkg:maven/io.vavr/vavr-match@0.10.2", + "/packages/my-app-1.jar:io.prometheus:simpleclient_common": "pkg:maven/io.prometheus/simpleclient_common@0.9.0", "/packages/my-app-1.jar:io.vavr:vavr": "pkg:maven/io.vavr/vavr@0.10.2", + "/packages/my-app-1.jar:io.vavr:vavr-match": "pkg:maven/io.vavr/vavr-match@0.10.2", "/packages/my-app-1.jar:jakarta.validation:jakarta.validation-api": "pkg:maven/jakarta.validation/jakarta.validation-api@2.0.2", "/packages/my-app-1.jar:javax.servlet:javax.servlet-api": "pkg:maven/javax.servlet/javax.servlet-api@3.1.0", "/packages/my-app-1.jar:org.apache.activemq.protobuf:activemq-protobuf": "pkg:maven/org.apache.activemq.protobuf/activemq-protobuf@1.1", @@ -365,14 +731,14 @@ var expectedPURLs = map[string]string{ "/packages/my-app-1.jar:org.apache.commons:commons-lang3": "pkg:maven/org.apache.commons/commons-lang3@3.10", "/packages/my-app-1.jar:org.apache.maven.shared:maven-shared-utils": "pkg:maven/org.apache.maven.shared/maven-shared-utils@3.3.4", "/packages/my-app-1.jar:org.codehaus.mojo:animal-sniffer-annotations": "pkg:maven/org.codehaus.mojo/animal-sniffer-annotations@1.14", + "/packages/my-app-1.jar:org.eclipse.jetty.http2:http2-common": "pkg:maven/org.eclipse.jetty.http2/http2-common@9.4.43.v20210629", + "/packages/my-app-1.jar:org.eclipse.jetty.http2:http2-hpack": "pkg:maven/org.eclipse.jetty.http2/http2-hpack@9.4.43.v20210629", + "/packages/my-app-1.jar:org.eclipse.jetty.toolchain.setuid:jetty-setuid-java": "pkg:maven/org.eclipse.jetty.toolchain.setuid/jetty-setuid-java@1.0.4", "/packages/my-app-1.jar:org.eclipse.jetty:jetty-client": "pkg:maven/org.eclipse.jetty/jetty-client@9.4.43.v20210629", "/packages/my-app-1.jar:org.eclipse.jetty:jetty-http": "pkg:maven/org.eclipse.jetty/jetty-http@9.4.43.v20210629", "/packages/my-app-1.jar:org.eclipse.jetty:jetty-io": "pkg:maven/org.eclipse.jetty/jetty-io@9.4.43.v20210629", "/packages/my-app-1.jar:org.eclipse.jetty:jetty-server": "pkg:maven/org.eclipse.jetty/jetty-server@9.1.0.M0", "/packages/my-app-1.jar:org.eclipse.jetty:jetty-util": "pkg:maven/org.eclipse.jetty/jetty-util@9.4.43.v20210629", - "/packages/my-app-1.jar:org.eclipse.jetty.http2:http2-common": "pkg:maven/org.eclipse.jetty.http2/http2-common@9.4.43.v20210629", - "/packages/my-app-1.jar:org.eclipse.jetty.http2:http2-hpack": "pkg:maven/org.eclipse.jetty.http2/http2-hpack@9.4.43.v20210629", - "/packages/my-app-1.jar:org.eclipse.jetty.toolchain.setuid:jetty-setuid-java": "pkg:maven/org.eclipse.jetty.toolchain.setuid/jetty-setuid-java@1.0.4", "/packages/my-app-1.jar:org.everit.json:org.everit.json.schema": "pkg:maven/org.everit.json/org.everit.json.schema@1.5.1", "/packages/my-app-1.jar:org.hibernate.validator:hibernate-validator": "pkg:maven/org.hibernate.validator/hibernate-validator@6.2.4.Final", "/packages/my-app-1.jar:org.jboss.logging:jboss-logging": "pkg:maven/org.jboss.logging/jboss-logging@3.4.1.Final", @@ -388,9 +754,9 @@ var expectedPURLs = map[string]string{ "/packages/my-app-1.jar:org.sonarsource.python:python-checks": "pkg:maven/org.sonarsource.python/python-checks@3.4.1.8066", "/packages/my-app-1.jar:org.sonarsource.python:python-frontend": "pkg:maven/org.sonarsource.python/python-frontend@3.4.1.8066", "/packages/my-app-1.jar:org.sonarsource.sslr:sslr-core": "pkg:maven/org.sonarsource.sslr/sslr-core@1.24.0.633", - "/packages/my-app-1.jar": "pkg:maven/com.mycompany.app/my-app@1", "/packages/netty-reactive-streams-2.0.6.jar": "pkg:maven/com.typesafe.netty/netty-reactive-streams@2.0.6", "/packages/nifi-utils-1.12.0.jar": "pkg:maven/org.apache.nifi/nifi-utils@1.12.0", + "/packages/nomad.hpi": "pkg:maven/org.jenkins-ci.plugins/nomad@0.7.4", "/packages/nomad.hpi:WEB-INF/lib/annotations-13.0.jar": "pkg:maven/org.jetbrains/annotations@13.0", "/packages/nomad.hpi:WEB-INF/lib/gson-2.8.6.jar": "pkg:maven/com.google.code.gson/gson@2.8.6", "/packages/nomad.hpi:WEB-INF/lib/json-20200518.jar": "pkg:maven/org.json/json@20200518", @@ -399,186 +765,197 @@ var expectedPURLs = map[string]string{ "/packages/nomad.hpi:WEB-INF/lib/nomad.jar": "pkg:maven/org.jenkins-ci.plugins/nomad@0.7.4", "/packages/nomad.hpi:WEB-INF/lib/okhttp-4.5.0.jar": "pkg:maven/com.squareup.okhttp3/okhttp@4.5.0", "/packages/nomad.hpi:WEB-INF/lib/okio-2.5.0.jar": "pkg:maven/com.squareup.okio/okio@2.5.0", - "/packages/nomad.hpi": "pkg:maven/org.jenkins-ci.plugins/nomad@0.7.4", - "/packages/openmeetings-util-4.0.9.jar": "pkg:maven/org.apache.openmeetings/openmeetings-util@4.0.9", - "/packages/org.eclipse.ant.core-3.7.0.jar": "pkg:maven/org.eclipse.platform/org.eclipse.ant.core@3.7.0", - "/packages/org.eclipse.osgi-3.18.0.jar": "pkg:maven/org.eclipse.platform/org.eclipse.osgi@3.18.0", - "/packages/org.everit.json.schema-1.5.1.jar": "pkg:maven/org.everit.json/org.everit.json.schema@1.5.1", - "/packages/original-my-app-1.jar:com.fasterxml:classmate": "pkg:maven/com.fasterxml/classmate@1.5.1", - "/packages/original-my-app-1.jar:com.fasterxml.jackson.core:jackson-annotations": "pkg:maven/com.fasterxml.jackson.core/jackson-annotations@2.13.2", - "/packages/original-my-app-1.jar:com.fasterxml.jackson.core:jackson-core": "pkg:maven/com.fasterxml.jackson.core/jackson-core@2.13.2", - "/packages/original-my-app-1.jar:com.fasterxml.jackson.core:jackson-databind": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.0", - "/packages/original-my-app-1.jar:com.google.errorprone:error_prone_annotations": "pkg:maven/com.google.errorprone/error_prone_annotations@2.0.18", - "/packages/original-my-app-1.jar:com.google.guava:guava": "pkg:maven/com.google.guava/guava@23.0", - "/packages/original-my-app-1.jar:com.google.j2objc:j2objc-annotations": "pkg:maven/com.google.j2objc/j2objc-annotations@1.1", - "/packages/original-my-app-1.jar:com.hazelcast:hazelcast-kubernetes": "pkg:maven/com.hazelcast/hazelcast-kubernetes@1.5.4", - "/packages/original-my-app-1.jar:com.hierynomus:asn-one": "pkg:maven/com.hierynomus/asn-one@0.5.0", - "/packages/original-my-app-1.jar:com.typesafe.netty:netty-reactive-streams": "pkg:maven/com.typesafe.netty/netty-reactive-streams@2.0.5", - "/packages/original-my-app-1.jar:commons-beanutils:commons-beanutils": "pkg:maven/commons-beanutils/commons-beanutils@1.9.2", - "/packages/original-my-app-1.jar:commons-collections:commons-collections": "pkg:maven/commons-collections/commons-collections@3.2.2", - "/packages/original-my-app-1.jar:commons-digester:commons-digester": "pkg:maven/commons-digester/commons-digester@1.8.1", - "/packages/original-my-app-1.jar:commons-io:commons-io": "pkg:maven/commons-io/commons-io@2.8.0", - "/packages/original-my-app-1.jar:commons-logging:commons-logging": "pkg:maven/commons-logging/commons-logging@1.2", - "/packages/original-my-app-1.jar:commons-validator:commons-validator": "pkg:maven/commons-validator/commons-validator@1.5.1", - "/packages/original-my-app-1.jar:io.netty:netty-buffer": "pkg:maven/io.netty/netty-buffer@4.1.52.Final", - "/packages/original-my-app-1.jar:io.netty:netty-codec-dns": "pkg:maven/io.netty/netty-codec-dns@4.1.63.Final", - "/packages/original-my-app-1.jar:io.netty:netty-codec-http": "pkg:maven/io.netty/netty-codec-http@4.1.63.Final", - "/packages/original-my-app-1.jar:io.netty:netty-codec-socks": "pkg:maven/io.netty/netty-codec-socks@4.1.63.Final", - "/packages/original-my-app-1.jar:io.netty:netty-codec": "pkg:maven/io.netty/netty-codec@4.1.52.Final", - "/packages/original-my-app-1.jar:io.netty:netty-common": "pkg:maven/io.netty/netty-common@4.1.52.Final", - "/packages/original-my-app-1.jar:io.netty:netty-handler-proxy": "pkg:maven/io.netty/netty-handler-proxy@4.1.63.Final", - "/packages/original-my-app-1.jar:io.netty:netty-handler": "pkg:maven/io.netty/netty-handler@4.1.52.Final", - "/packages/original-my-app-1.jar:io.netty:netty-resolver-dns-native-macos": "pkg:maven/io.netty/netty-resolver-dns-native-macos@4.1.63.Final", - "/packages/original-my-app-1.jar:io.netty:netty-resolver-dns": "pkg:maven/io.netty/netty-resolver-dns@4.1.63.Final", - "/packages/original-my-app-1.jar:io.netty:netty-resolver": "pkg:maven/io.netty/netty-resolver@4.1.52.Final", - "/packages/original-my-app-1.jar:io.netty:netty-transport-native-epoll": "pkg:maven/io.netty/netty-transport-native-epoll@4.1.63.Final", - "/packages/original-my-app-1.jar:io.netty:netty-transport-native-unix-common": "pkg:maven/io.netty/netty-transport-native-unix-common@4.1.63.Final", - "/packages/original-my-app-1.jar:io.netty:netty-transport": "pkg:maven/io.netty/netty-transport@4.1.52.Final", - "/packages/original-my-app-1.jar:io.prometheus:simpleclient_common": "pkg:maven/io.prometheus/simpleclient_common@0.9.0", - "/packages/original-my-app-1.jar:io.prometheus:simpleclient": "pkg:maven/io.prometheus/simpleclient@0.9.0", - "/packages/original-my-app-1.jar:io.vavr:vavr-match": "pkg:maven/io.vavr/vavr-match@0.10.2", - "/packages/original-my-app-1.jar:io.vavr:vavr": "pkg:maven/io.vavr/vavr@0.10.2", - "/packages/original-my-app-1.jar:jakarta.validation:jakarta.validation-api": "pkg:maven/jakarta.validation/jakarta.validation-api@2.0.2", - "/packages/original-my-app-1.jar:javax.servlet:javax.servlet-api": "pkg:maven/javax.servlet/javax.servlet-api@3.1.0", - "/packages/original-my-app-1.jar:org.apache.activemq.protobuf:activemq-protobuf": "pkg:maven/org.apache.activemq.protobuf/activemq-protobuf@1.1", - "/packages/original-my-app-1.jar:org.apache.commons:commons-compress": "pkg:maven/org.apache.commons/commons-compress@1.21", - "/packages/original-my-app-1.jar:org.apache.commons:commons-lang3": "pkg:maven/org.apache.commons/commons-lang3@3.10", - "/packages/original-my-app-1.jar:org.apache.maven.shared:maven-shared-utils": "pkg:maven/org.apache.maven.shared/maven-shared-utils@3.3.4", - "/packages/original-my-app-1.jar:org.codehaus.mojo:animal-sniffer-annotations": "pkg:maven/org.codehaus.mojo/animal-sniffer-annotations@1.14", - "/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-client": "pkg:maven/org.eclipse.jetty/jetty-client@9.4.43.v20210629", - "/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-http": "pkg:maven/org.eclipse.jetty/jetty-http@9.4.43.v20210629", - "/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-io": "pkg:maven/org.eclipse.jetty/jetty-io@9.4.43.v20210629", - "/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-server": "pkg:maven/org.eclipse.jetty/jetty-server@9.1.0.M0", - "/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-util": "pkg:maven/org.eclipse.jetty/jetty-util@9.4.43.v20210629", - "/packages/original-my-app-1.jar:org.eclipse.jetty.http2:http2-common": "pkg:maven/org.eclipse.jetty.http2/http2-common@9.4.43.v20210629", - "/packages/original-my-app-1.jar:org.eclipse.jetty.http2:http2-hpack": "pkg:maven/org.eclipse.jetty.http2/http2-hpack@9.4.43.v20210629", - "/packages/original-my-app-1.jar:org.eclipse.jetty.toolchain.setuid:jetty-setuid-java": "pkg:maven/org.eclipse.jetty.toolchain.setuid/jetty-setuid-java@1.0.4", - "/packages/original-my-app-1.jar:org.everit.json:org.everit.json.schema": "pkg:maven/org.everit.json/org.everit.json.schema@1.5.1", - "/packages/original-my-app-1.jar:org.hibernate.validator:hibernate-validator": "pkg:maven/org.hibernate.validator/hibernate-validator@6.2.4.Final", - "/packages/original-my-app-1.jar:org.jboss.logging:jboss-logging": "pkg:maven/org.jboss.logging/jboss-logging@3.4.1.Final", - "/packages/original-my-app-1.jar:org.jctools:jctools-core": "pkg:maven/org.jctools/jctools-core@3.1.0", - "/packages/original-my-app-1.jar:org.jetbrains:annotations": "pkg:maven/org.jetbrains/annotations@13.0", - "/packages/original-my-app-1.jar:org.json:json": "pkg:maven/org.json/json@20160810", - "/packages/original-my-app-1.jar:org.kohsuke:github-api": "pkg:maven/org.kohsuke/github-api@1.301", - "/packages/original-my-app-1.jar:org.slf4j:log4j-over-slf4j": "pkg:maven/org.slf4j/log4j-over-slf4j@1.7.33", - "/packages/original-my-app-1.jar:org.slf4j:slf4j-api": "pkg:maven/org.slf4j/slf4j-api@1.7.33", - "/packages/original-my-app-1.jar:org.sonarsource.analyzer-commons:sonar-analyzer-test-commons": "pkg:maven/org.sonarsource.analyzer-commons/sonar-analyzer-test-commons@1.14.1.690", - "/packages/original-my-app-1.jar:org.sonarsource.php:php-checks": "pkg:maven/org.sonarsource.php/php-checks@3.17.0.7439", - "/packages/original-my-app-1.jar:org.sonarsource.php:php-frontend": "pkg:maven/org.sonarsource.php/php-frontend@3.17.0.7439", - "/packages/original-my-app-1.jar:org.sonarsource.python:python-checks": "pkg:maven/org.sonarsource.python/python-checks@3.4.1.8066", - "/packages/original-my-app-1.jar:org.sonarsource.python:python-frontend": "pkg:maven/org.sonarsource.python/python-frontend@3.4.1.8066", - "/packages/original-my-app-1.jar:org.sonarsource.sslr:sslr-core": "pkg:maven/org.sonarsource.sslr/sslr-core@1.24.0.633", - "/packages/original-my-app-1.jar": "pkg:maven/com.mycompany.app/my-app@1", - "/packages/php-frontend-3.9.0.6331.jar": "pkg:maven/org.sonarsource.php/php-frontend@3.9.0.6331", - "/packages/postgresql-42.5.0.jar": "pkg:maven/org.postgresql/postgresql@42.5.0", - "/packages/protobuf-java-3.21.6.jar": "pkg:maven/com.google.protobuf/protobuf-java@3.21.6", - "/packages/python-frontend-3.24.0.10784.jar": "pkg:maven/org.sonarsource.python/python-frontend@3.24.0.10784", - "/packages/ratpack-core-1.8.2.jar": "pkg:maven/io.ratpack/ratpack-core@1.8.2", - "/packages/reactor-netty-core-1.0.35.jar": "pkg:maven/io.projectreactor.netty/reactor-netty-core@1.0.35", - "/packages/reactor-netty-http-1.1.9.jar": "pkg:maven/io.projectreactor.netty/reactor-netty-http@1.1.9", - "/packages/reactor-netty-incubator-quic-0.1.3.jar": "pkg:maven/io.projectreactor.netty.incubator/reactor-netty-incubator-quic@0.1.3", - "/packages/resilience4j-prometheus-0.17.0.jar": "pkg:maven/io.github.resilience4j.prometheus/resilience4j-prometheus@0.17.0", - "/packages/shiro-core-1.9.1.jar": "pkg:maven/org.apache.shiro/shiro-core@1.9.1", - "/packages/solr-core-8.8.1.jar": "pkg:maven/org.apache.solr/solr-core@8.8.1", - "/packages/spring-amqp-2.4.17.jar": "pkg:maven/org.springframework.amqp/spring-amqp@2.4.17", - "/packages/spring-analytics-2.0.0.RELEASE.jar": "pkg:maven/org.springframework.analytics/spring-analytics@2.0.0.RELEASE", - "/packages/spring-asm-3.0.7.RELEASE.jar": "pkg:maven/org.springframework/spring-asm@3.0.7.RELEASE", - "/packages/spring-batch-core-4.2.1.RELEASE.jar": "pkg:maven/org.springframework.batch/spring-batch-core@4.2.1.RELEASE", - "/packages/spring-boot-3.1.2.jar": "pkg:maven/org.springframework.boot/spring-boot@3.1.2", - "/packages/spring-cloud-app-broker-core-1.6.1.jar": "pkg:maven/org.springframework.cloud/spring-cloud-app-broker-core@1.6.1", - "/packages/spring-cql-1.5.11.RELEASE.jar": "pkg:maven/org.springframework.data/spring-cql@1.5.11.RELEASE", - "/packages/spring-credhub-core-1.0.1.RELEASE.jar": "pkg:maven/org.springframework.credhub/spring-credhub-core@1.0.1.RELEASE", - "/packages/spring-flex-1.0.3.RELEASE.jar": "pkg:maven/org.springframework.flex/spring-flex@1.0.3.RELEASE", - "/packages/spring-graphql-1.2.2.jar": "pkg:maven/org.springframework.graphql/spring-graphql@1.2.2", - "/packages/spring-hateoas-2.1.0.jar": "pkg:maven/org.springframework.hateoas/spring-hateoas@2.1.0", - "/packages/spring-integration-amqp-6.0.5.jar": "pkg:maven/org.springframework.integration/spring-integration-amqp@6.0.5", - "/packages/spring-kafka-3.0.9.jar": "pkg:maven/org.springframework.kafka/spring-kafka@3.0.9", - "/packages/spring-security-core-6.0.2.jar": "pkg:maven/org.springframework.security/spring-security-core@6.0.2", - "/packages/spring-security-kerberos-core-1.0.1.RELEASE.jar": "pkg:maven/org.springframework.security.kerberos/spring-security-kerberos-core@1.0.1.RELEASE", - "/packages/spring-security-oauth-2.5.1.RELEASE.jar": "pkg:maven/org.springframework.security.oauth/spring-security-oauth@2.5.1.RELEASE", - "/packages/spring-security-oauth2-autoconfigure-2.5.9.jar": "pkg:maven/org.springframework.security.oauth.boot/spring-security-oauth2-autoconfigure@2.5.9", - "/packages/spring-security-saml2-core-1.0.10.RELEASE.jar": "pkg:maven/org.springframework.security.extensions/spring-security-saml2-core@1.0.10.RELEASE", - "/packages/spring-session-core-3.0.0.jar": "pkg:maven/org.springframework.session/spring-session-core@3.0.0", - "/packages/spring-social-core-1.1.2.RELEASE.jar": "pkg:maven/org.springframework.social/spring-social-core@1.1.2.RELEASE", - "/packages/spring-vault-core-3.0.1.jar": "pkg:maven/org.springframework.vault/spring-vault-core@3.0.1", - "/packages/spring-webmvc-3.1.4.RELEASE.jar": "pkg:maven/org.springframework/spring-webmvc@3.1.4.RELEASE", - "/packages/spring-xml-3.0.3.RELEASE.jar": "pkg:maven/org.springframework.ws/spring-xml@3.0.3.RELEASE", - "/packages/storm-core-1.2.2.jar:cheshire:cheshire": "pkg:maven/cheshire/cheshire@5.3.1", - "/packages/storm-core-1.2.2.jar:clj-time:clj-time": "pkg:maven/clj-time/clj-time@0.8.0", - "/packages/storm-core-1.2.2.jar:clout:clout": "pkg:maven/clout/clout@1.2.0", - "/packages/storm-core-1.2.2.jar:com.fasterxml.jackson.core:jackson-core": "pkg:maven/com.fasterxml.jackson.core/jackson-core@2.9.4", - "/packages/storm-core-1.2.2.jar:com.fasterxml.jackson.dataformat:jackson-dataformat-smile": "pkg:maven/com.fasterxml.jackson.dataformat/jackson-dataformat-smile@2.9.4", - "/packages/storm-core-1.2.2.jar:com.google.guava:guava": "pkg:maven/com.google.guava/guava@16.0.1", - "/packages/storm-core-1.2.2.jar:com.twitter:carbonite": "pkg:maven/com.twitter/carbonite@1.5.0", - "/packages/storm-core-1.2.2.jar:commons-codec:commons-codec": "pkg:maven/commons-codec/commons-codec@1.6", - "/packages/storm-core-1.2.2.jar:commons-collections:commons-collections": "pkg:maven/commons-collections/commons-collections@3.2.2", - "/packages/storm-core-1.2.2.jar:commons-fileupload:commons-fileupload": "pkg:maven/commons-fileupload/commons-fileupload@1.3.2", - "/packages/storm-core-1.2.2.jar:commons-io:commons-io": "pkg:maven/commons-io/commons-io@2.5", - "/packages/storm-core-1.2.2.jar:commons-lang:commons-lang": "pkg:maven/commons-lang/commons-lang@2.5", - "/packages/storm-core-1.2.2.jar:compojure:compojure": "pkg:maven/compojure/compojure@1.1.9", - "/packages/storm-core-1.2.2.jar:hiccup:hiccup": "pkg:maven/hiccup/hiccup@0.3.6", - "/packages/storm-core-1.2.2.jar:io.netty:netty": "pkg:maven/io.netty/netty@3.9.9.Final", - "/packages/storm-core-1.2.2.jar:joda-time:joda-time": "pkg:maven/joda-time/joda-time@2.3", - "/packages/storm-core-1.2.2.jar:metrics-clojure:metrics-clojure": "pkg:maven/metrics-clojure/metrics-clojure@2.5.1", - "/packages/storm-core-1.2.2.jar:ns-tracker:ns-tracker": "pkg:maven/ns-tracker/ns-tracker@0.2.2", - "/packages/storm-core-1.2.2.jar:org.apache.commons:commons-compress": "pkg:maven/org.apache.commons/commons-compress@1.4.1", - "/packages/storm-core-1.2.2.jar:org.apache.commons:commons-exec": "pkg:maven/org.apache.commons/commons-exec@1.1", - "/packages/storm-core-1.2.2.jar:org.apache.curator:curator-client": "pkg:maven/org.apache.curator/curator-client@4.0.1", - "/packages/storm-core-1.2.2.jar:org.apache.curator:curator-framework": "pkg:maven/org.apache.curator/curator-framework@4.0.1", - "/packages/storm-core-1.2.2.jar:org.apache.curator:curator-recipes": "pkg:maven/org.apache.curator/curator-recipes@4.0.1", - "/packages/storm-core-1.2.2.jar:org.apache.hadoop:hadoop-auth": "pkg:maven/org.apache.hadoop/hadoop-auth@2.6.1", - "/packages/storm-core-1.2.2.jar:org.apache.httpcomponents:httpclient": "pkg:maven/org.apache.httpcomponents/httpclient@4.3.3", - "/packages/storm-core-1.2.2.jar:org.apache.httpcomponents:httpcore": "pkg:maven/org.apache.httpcomponents/httpcore@4.4.1", - "/packages/storm-core-1.2.2.jar:org.clojure:java.jmx": "pkg:maven/org.clojure/java.jmx@0.3.1", - "/packages/storm-core-1.2.2.jar:org.clojure:math.numeric-tower": "pkg:maven/org.clojure/math.numeric-tower@0.0.1", - "/packages/storm-core-1.2.2.jar:org.clojure:tools.cli": "pkg:maven/org.clojure/tools.cli@0.2.4", - "/packages/storm-core-1.2.2.jar:org.clojure:tools.logging": "pkg:maven/org.clojure/tools.logging@0.2.3", - "/packages/storm-core-1.2.2.jar:org.clojure:tools.macro": "pkg:maven/org.clojure/tools.macro@0.1.0", - "/packages/storm-core-1.2.2.jar:org.clojure:tools.namespace": "pkg:maven/org.clojure/tools.namespace@0.2.4", - "/packages/storm-core-1.2.2.jar:org.eclipse.jetty:jetty-client": "pkg:maven/org.eclipse.jetty/jetty-client@7.6.13.v20130916", - "/packages/storm-core-1.2.2.jar:org.eclipse.jetty:jetty-continuation": "pkg:maven/org.eclipse.jetty/jetty-continuation@7.6.13.v20130916", - "/packages/storm-core-1.2.2.jar:org.eclipse.jetty:jetty-http": "pkg:maven/org.eclipse.jetty/jetty-http@7.6.13.v20130916", - "/packages/storm-core-1.2.2.jar:org.eclipse.jetty:jetty-io": "pkg:maven/org.eclipse.jetty/jetty-io@7.6.13.v20130916", - "/packages/storm-core-1.2.2.jar:org.eclipse.jetty:jetty-security": "pkg:maven/org.eclipse.jetty/jetty-security@7.6.13.v20130916", - "/packages/storm-core-1.2.2.jar:org.eclipse.jetty:jetty-server": "pkg:maven/org.eclipse.jetty/jetty-server@7.6.13.v20130916", - "/packages/storm-core-1.2.2.jar:org.eclipse.jetty:jetty-servlet": "pkg:maven/org.eclipse.jetty/jetty-servlet@7.6.13.v20130916", - "/packages/storm-core-1.2.2.jar:org.eclipse.jetty:jetty-servlets": "pkg:maven/org.eclipse.jetty/jetty-servlets@7.6.13.v20130916", - "/packages/storm-core-1.2.2.jar:org.eclipse.jetty:jetty-util": "pkg:maven/org.eclipse.jetty/jetty-util@7.6.13.v20130916", - "/packages/storm-core-1.2.2.jar:org.jgrapht:jgrapht-core": "pkg:maven/org.jgrapht/jgrapht-core@0.9.0", - "/packages/storm-core-1.2.2.jar:org.yaml:snakeyaml": "pkg:maven/org.yaml/snakeyaml@1.11", - "/packages/storm-core-1.2.2.jar:ring:ring-codec": "pkg:maven/ring/ring-codec@1.0.0", - "/packages/storm-core-1.2.2.jar:ring:ring-core": "pkg:maven/ring/ring-core@1.3.1", - "/packages/storm-core-1.2.2.jar:ring:ring-devel": "pkg:maven/ring/ring-devel@1.3.1", - "/packages/storm-core-1.2.2.jar:ring:ring-jetty-adapter": "pkg:maven/ring/ring-jetty-adapter@1.3.1", - "/packages/storm-core-1.2.2.jar:ring:ring-json": "pkg:maven/ring/ring-json@0.3.1", - "/packages/storm-core-1.2.2.jar:ring:ring-servlet": "pkg:maven/ring/ring-servlet@1.3.1", - "/packages/storm-core-1.2.2.jar": "pkg:maven/org.apache.storm/storm-core@1.2.2", - "/packages/tapestry-core-5.8.1.jar": "pkg:maven/org.apache.tapestry/tapestry-core@5.8.1", - "/packages/tika-core-1.26.jar": "pkg:maven/org.apache.tika/tika-core@1.26", - "/packages/tomcat-catalina-11.0.0-M1.jar": "pkg:maven/org.apache.tomcat/tomcat-catalina@11.0.0-M1", - "/packages/tomcat-embed-core-11.0.0-M7.jar": "pkg:maven/org.apache.tomcat.embed/tomcat-embed-core@11.0.0-M7", - "/packages/TwilioNotifier.hpi:WEB-INF/lib/commons-codec-1.2.jar": "pkg:maven/commons-codec/commons-codec@1.2", - "/packages/TwilioNotifier.hpi:WEB-INF/lib/commons-httpclient-3.1.jar": "pkg:maven/org.apache/commons-httpclient@3.1", - "/packages/TwilioNotifier.hpi:WEB-INF/lib/commons-logging-1.0.4.jar": "pkg:maven/commons-logging/commons-logging@1.0.4", - "/packages/TwilioNotifier.hpi:WEB-INF/lib/log4j-1.2.9.jar": "pkg:maven/log4j/log4j@1.2.9", - "/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:commons-codec:commons-codec": "pkg:maven/commons-codec/commons-codec@1.4", - "/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:commons-lang:commons-lang": "pkg:maven/commons-lang/commons-lang@2.5", - "/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:commons-logging:commons-logging": "pkg:maven/commons-logging/commons-logging@1.1.1", - "/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:org.apache.httpcomponents:httpclient": "pkg:maven/org.apache.httpcomponents/httpclient@4.1.1", - "/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:org.apache.httpcomponents:httpcore": "pkg:maven/org.apache.httpcomponents/httpcore@4.1", - "/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:org.easymock:easymock": "pkg:maven/org.easymock/easymock@2.4", - "/packages/TwilioNotifier.hpi": "pkg:maven/com.twilio.jenkins/TwilioNotifier@0.2.1", - "/packages/undertow-core-2.3.4.Final.jar": "pkg:maven/io.undertow/undertow-core@2.3.4.Final", - "/packages/vaadin-client-8.11.3.jar": "pkg:maven/com.vaadin/vaadin-client@8.11.3", - "/packages/velocity-1.7.jar": "pkg:maven/org.apache.velocity/velocity@1.7", - "/packages/vertx-web-4.3.7.jar": "pkg:maven/io.vertx/vertx-web@4.3.7", - "/packages/wicket-core-9.2.0.jar": "pkg:maven/org.apache.wicket/wicket-core@9.2.0", - "/packages/xalan-2.7.2.jar": "pkg:maven/xalan/xalan@2.7.2", - "/packages/xmlpull-1.1.3.1.jar": "pkg:maven/xmlpull/xmlpull@1.1.3.1", - // "/packages/xpp3_min-1.1.4c.jar": "pkg:maven/xpp3/xpp3_min@1.1.4c", - "/packages/xstream-1.4.11.1.jar": "pkg:maven/com.thoughtworks.xstream/xstream@1.4.11.1", - "/packages/xstream-1.4.19.jar": "pkg:maven/com.thoughtworks.xstream/xstream@1.4.19", - "/packages/xwiki-commons-xml-15.1.jar": "pkg:maven/org.xwiki.commons/xwiki-commons-xml@15.1", - "/packages/xwiki-platform-oldcore-15.3.jar": "pkg:maven/org.xwiki.platform/xwiki-platform-oldcore@15.3", - "/packages/zookeeper-3.7.1.jar": "pkg:maven/org.apache.zookeeper/zookeeper@3.7.1", + "/packages/nuget.hpi": "pkg:maven/org.jenkins-ci.plugins/nuget@1.0", + "/packages/nuget.hpi:WEB-INF/lib/envinject-lib-1.19.jar": "pkg:maven/org.jenkins-ci.lib/envinject-lib@1.19", + "/packages/nuget.hpi:WEB-INF/lib/nuget.jar": "pkg:maven/org.jenkins-ci.plugins/nuget@1.0", + "/packages/nuget.hpi:WEB-INF/lib/xtrigger-lib-0.33.jar": "pkg:maven/org.jenkins-ci.lib/xtrigger-lib@0.33", + "/packages/openmeetings-util-4.0.9.jar": "pkg:maven/org.apache.openmeetings/openmeetings-util@4.0.9", + "/packages/org.eclipse.ant.core-3.7.0.jar": "pkg:maven/org.eclipse.platform/org.eclipse.ant.core@3.7.0", + "/packages/org.eclipse.osgi-3.18.0.jar": "pkg:maven/org.eclipse.platform/org.eclipse.osgi@3.18.0", + "/packages/org.everit.json.schema-1.5.1.jar": "pkg:maven/org.everit.json/org.everit.json.schema@1.5.1", + "/packages/original-my-app-1.jar": "pkg:maven/com.mycompany.app/my-app@1", + "/packages/original-my-app-1.jar:com.fasterxml.jackson.core:jackson-annotations": "pkg:maven/com.fasterxml.jackson.core/jackson-annotations@2.13.2", + "/packages/original-my-app-1.jar:com.fasterxml.jackson.core:jackson-core": "pkg:maven/com.fasterxml.jackson.core/jackson-core@2.13.2", + "/packages/original-my-app-1.jar:com.fasterxml.jackson.core:jackson-databind": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.0", + "/packages/original-my-app-1.jar:com.fasterxml:classmate": "pkg:maven/com.fasterxml/classmate@1.5.1", + "/packages/original-my-app-1.jar:com.google.errorprone:error_prone_annotations": "pkg:maven/com.google.errorprone/error_prone_annotations@2.0.18", + "/packages/original-my-app-1.jar:com.google.guava:guava": "pkg:maven/com.google.guava/guava@23.0", + "/packages/original-my-app-1.jar:com.google.j2objc:j2objc-annotations": "pkg:maven/com.google.j2objc/j2objc-annotations@1.1", + "/packages/original-my-app-1.jar:com.hazelcast:hazelcast-kubernetes": "pkg:maven/com.hazelcast/hazelcast-kubernetes@1.5.4", + "/packages/original-my-app-1.jar:com.hierynomus:asn-one": "pkg:maven/com.hierynomus/asn-one@0.5.0", + "/packages/original-my-app-1.jar:com.typesafe.netty:netty-reactive-streams": "pkg:maven/com.typesafe.netty/netty-reactive-streams@2.0.5", + "/packages/original-my-app-1.jar:commons-beanutils:commons-beanutils": "pkg:maven/commons-beanutils/commons-beanutils@1.9.2", + "/packages/original-my-app-1.jar:commons-collections:commons-collections": "pkg:maven/commons-collections/commons-collections@3.2.2", + "/packages/original-my-app-1.jar:commons-digester:commons-digester": "pkg:maven/commons-digester/commons-digester@1.8.1", + "/packages/original-my-app-1.jar:commons-io:commons-io": "pkg:maven/commons-io/commons-io@2.8.0", + "/packages/original-my-app-1.jar:commons-logging:commons-logging": "pkg:maven/commons-logging/commons-logging@1.2", + "/packages/original-my-app-1.jar:commons-validator:commons-validator": "pkg:maven/commons-validator/commons-validator@1.5.1", + "/packages/original-my-app-1.jar:io.netty:netty-buffer": "pkg:maven/io.netty/netty-buffer@4.1.52.Final", + "/packages/original-my-app-1.jar:io.netty:netty-codec": "pkg:maven/io.netty/netty-codec@4.1.52.Final", + "/packages/original-my-app-1.jar:io.netty:netty-codec-dns": "pkg:maven/io.netty/netty-codec-dns@4.1.63.Final", + "/packages/original-my-app-1.jar:io.netty:netty-codec-http": "pkg:maven/io.netty/netty-codec-http@4.1.63.Final", + "/packages/original-my-app-1.jar:io.netty:netty-codec-socks": "pkg:maven/io.netty/netty-codec-socks@4.1.63.Final", + "/packages/original-my-app-1.jar:io.netty:netty-common": "pkg:maven/io.netty/netty-common@4.1.52.Final", + "/packages/original-my-app-1.jar:io.netty:netty-handler": "pkg:maven/io.netty/netty-handler@4.1.52.Final", + "/packages/original-my-app-1.jar:io.netty:netty-handler-proxy": "pkg:maven/io.netty/netty-handler-proxy@4.1.63.Final", + "/packages/original-my-app-1.jar:io.netty:netty-resolver": "pkg:maven/io.netty/netty-resolver@4.1.52.Final", + "/packages/original-my-app-1.jar:io.netty:netty-resolver-dns": "pkg:maven/io.netty/netty-resolver-dns@4.1.63.Final", + "/packages/original-my-app-1.jar:io.netty:netty-resolver-dns-native-macos": "pkg:maven/io.netty/netty-resolver-dns-native-macos@4.1.63.Final", + "/packages/original-my-app-1.jar:io.netty:netty-transport": "pkg:maven/io.netty/netty-transport@4.1.52.Final", + "/packages/original-my-app-1.jar:io.netty:netty-transport-native-epoll": "pkg:maven/io.netty/netty-transport-native-epoll@4.1.63.Final", + "/packages/original-my-app-1.jar:io.netty:netty-transport-native-unix-common": "pkg:maven/io.netty/netty-transport-native-unix-common@4.1.63.Final", + "/packages/original-my-app-1.jar:io.prometheus:simpleclient": "pkg:maven/io.prometheus/simpleclient@0.9.0", + "/packages/original-my-app-1.jar:io.prometheus:simpleclient_common": "pkg:maven/io.prometheus/simpleclient_common@0.9.0", + "/packages/original-my-app-1.jar:io.vavr:vavr": "pkg:maven/io.vavr/vavr@0.10.2", + "/packages/original-my-app-1.jar:io.vavr:vavr-match": "pkg:maven/io.vavr/vavr-match@0.10.2", + "/packages/original-my-app-1.jar:jakarta.validation:jakarta.validation-api": "pkg:maven/jakarta.validation/jakarta.validation-api@2.0.2", + "/packages/original-my-app-1.jar:javax.servlet:javax.servlet-api": "pkg:maven/javax.servlet/javax.servlet-api@3.1.0", + "/packages/original-my-app-1.jar:org.apache.activemq.protobuf:activemq-protobuf": "pkg:maven/org.apache.activemq.protobuf/activemq-protobuf@1.1", + "/packages/original-my-app-1.jar:org.apache.commons:commons-compress": "pkg:maven/org.apache.commons/commons-compress@1.21", + "/packages/original-my-app-1.jar:org.apache.commons:commons-lang3": "pkg:maven/org.apache.commons/commons-lang3@3.10", + "/packages/original-my-app-1.jar:org.apache.maven.shared:maven-shared-utils": "pkg:maven/org.apache.maven.shared/maven-shared-utils@3.3.4", + "/packages/original-my-app-1.jar:org.codehaus.mojo:animal-sniffer-annotations": "pkg:maven/org.codehaus.mojo/animal-sniffer-annotations@1.14", + "/packages/original-my-app-1.jar:org.eclipse.jetty.http2:http2-common": "pkg:maven/org.eclipse.jetty.http2/http2-common@9.4.43.v20210629", + "/packages/original-my-app-1.jar:org.eclipse.jetty.http2:http2-hpack": "pkg:maven/org.eclipse.jetty.http2/http2-hpack@9.4.43.v20210629", + "/packages/original-my-app-1.jar:org.eclipse.jetty.toolchain.setuid:jetty-setuid-java": "pkg:maven/org.eclipse.jetty.toolchain.setuid/jetty-setuid-java@1.0.4", + "/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-client": "pkg:maven/org.eclipse.jetty/jetty-client@9.4.43.v20210629", + "/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-http": "pkg:maven/org.eclipse.jetty/jetty-http@9.4.43.v20210629", + "/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-io": "pkg:maven/org.eclipse.jetty/jetty-io@9.4.43.v20210629", + "/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-server": "pkg:maven/org.eclipse.jetty/jetty-server@9.1.0.M0", + "/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-util": "pkg:maven/org.eclipse.jetty/jetty-util@9.4.43.v20210629", + "/packages/original-my-app-1.jar:org.everit.json:org.everit.json.schema": "pkg:maven/org.everit.json/org.everit.json.schema@1.5.1", + "/packages/original-my-app-1.jar:org.hibernate.validator:hibernate-validator": "pkg:maven/org.hibernate.validator/hibernate-validator@6.2.4.Final", + "/packages/original-my-app-1.jar:org.jboss.logging:jboss-logging": "pkg:maven/org.jboss.logging/jboss-logging@3.4.1.Final", + "/packages/original-my-app-1.jar:org.jctools:jctools-core": "pkg:maven/org.jctools/jctools-core@3.1.0", + "/packages/original-my-app-1.jar:org.jetbrains:annotations": "pkg:maven/org.jetbrains/annotations@13.0", + "/packages/original-my-app-1.jar:org.json:json": "pkg:maven/org.json/json@20160810", + "/packages/original-my-app-1.jar:org.kohsuke:github-api": "pkg:maven/org.kohsuke/github-api@1.301", + "/packages/original-my-app-1.jar:org.slf4j:log4j-over-slf4j": "pkg:maven/org.slf4j/log4j-over-slf4j@1.7.33", + "/packages/original-my-app-1.jar:org.slf4j:slf4j-api": "pkg:maven/org.slf4j/slf4j-api@1.7.33", + "/packages/original-my-app-1.jar:org.sonarsource.analyzer-commons:sonar-analyzer-test-commons": "pkg:maven/org.sonarsource.analyzer-commons/sonar-analyzer-test-commons@1.14.1.690", + "/packages/original-my-app-1.jar:org.sonarsource.php:php-checks": "pkg:maven/org.sonarsource.php/php-checks@3.17.0.7439", + "/packages/original-my-app-1.jar:org.sonarsource.php:php-frontend": "pkg:maven/org.sonarsource.php/php-frontend@3.17.0.7439", + "/packages/original-my-app-1.jar:org.sonarsource.python:python-checks": "pkg:maven/org.sonarsource.python/python-checks@3.4.1.8066", + "/packages/original-my-app-1.jar:org.sonarsource.python:python-frontend": "pkg:maven/org.sonarsource.python/python-frontend@3.4.1.8066", + "/packages/original-my-app-1.jar:org.sonarsource.sslr:sslr-core": "pkg:maven/org.sonarsource.sslr/sslr-core@1.24.0.633", + "/packages/php-frontend-3.9.0.6331.jar": "pkg:maven/org.sonarsource.php/php-frontend@3.9.0.6331", + "/packages/postgresql-42.5.0.jar": "pkg:maven/org.postgresql/postgresql@42.5.0", + "/packages/protobuf-java-3.21.6.jar": "pkg:maven/com.google.protobuf/protobuf-java@3.21.6", + "/packages/python-frontend-3.24.0.10784.jar": "pkg:maven/org.sonarsource.python/python-frontend@3.24.0.10784", + "/packages/ratpack-core-1.8.2.jar": "pkg:maven/io.ratpack/ratpack-core@1.8.2", + "/packages/reactor-netty-core-1.0.35.jar": "pkg:maven/io.projectreactor.netty/reactor-netty-core@1.0.35", + "/packages/reactor-netty-http-1.1.9.jar": "pkg:maven/io.projectreactor.netty/reactor-netty-http@1.1.9", + "/packages/reactor-netty-incubator-quic-0.1.3.jar": "pkg:maven/io.projectreactor.netty.incubator/reactor-netty-incubator-quic@0.1.3", + "/packages/resilience4j-prometheus-0.17.0.jar": "pkg:maven/io.github.resilience4j.prometheus/resilience4j-prometheus@0.17.0", + "/packages/script-security.hpi": "pkg:maven/org.jenkins-ci.plugins/script-security@1.74", + "/packages/script-security.hpi:WEB-INF/lib/caffeine-2.8.2.jar": "pkg:maven/com.github.ben-manes.caffeine/caffeine@2.8.2", + "/packages/script-security.hpi:WEB-INF/lib/checker-qual-3.3.0.jar": "pkg:maven/org.checkerframework.checker.qual/checker-qual@3.3.0", + "/packages/script-security.hpi:WEB-INF/lib/error_prone_annotations-2.3.4.jar": "pkg:maven/com.google.errorprone/error_prone_annotations@2.3.4", + "/packages/script-security.hpi:WEB-INF/lib/groovy-sandbox-1.26.jar": "pkg:maven/org.kohsuke/groovy-sandbox@1.26", + "/packages/script-security.hpi:WEB-INF/lib/script-security.jar": "pkg:maven/org.jenkins-ci.plugins/script-security@1.74", + "/packages/shiro-core-1.9.1.jar": "pkg:maven/org.apache.shiro/shiro-core@1.9.1", + "/packages/solr-core-8.8.1.jar": "pkg:maven/org.apache.solr/solr-core@8.8.1", + "/packages/spring-amqp-2.4.17.jar": "pkg:maven/org.springframework.amqp/spring-amqp@2.4.17", + "/packages/spring-analytics-2.0.0.RELEASE.jar": "pkg:maven/org.springframework.analytics/spring-analytics@2.0.0.RELEASE", + "/packages/spring-asm-3.0.7.RELEASE.jar": "pkg:maven/org.springframework/spring-asm@3.0.7.RELEASE", + "/packages/spring-batch-core-4.2.1.RELEASE.jar": "pkg:maven/org.springframework.batch/spring-batch-core@4.2.1.RELEASE", + "/packages/spring-boot-3.1.2.jar": "pkg:maven/org.springframework.boot/spring-boot@3.1.2", + "/packages/spring-cloud-app-broker-core-1.6.1.jar": "pkg:maven/org.springframework.cloud/spring-cloud-app-broker-core@1.6.1", + "/packages/spring-cql-1.5.11.RELEASE.jar": "pkg:maven/org.springframework.data/spring-cql@1.5.11.RELEASE", + "/packages/spring-credhub-core-1.0.1.RELEASE.jar": "pkg:maven/org.springframework.credhub/spring-credhub-core@1.0.1.RELEASE", + "/packages/spring-flex-1.0.3.RELEASE.jar": "pkg:maven/org.springframework.flex/spring-flex@1.0.3.RELEASE", + "/packages/spring-graphql-1.2.2.jar": "pkg:maven/org.springframework.graphql/spring-graphql@1.2.2", + "/packages/spring-hateoas-2.1.0.jar": "pkg:maven/org.springframework.hateoas/spring-hateoas@2.1.0", + "/packages/spring-integration-amqp-6.0.5.jar": "pkg:maven/org.springframework.integration/spring-integration-amqp@6.0.5", + "/packages/spring-kafka-3.0.9.jar": "pkg:maven/org.springframework.kafka/spring-kafka@3.0.9", + "/packages/spring-security-core-6.0.2.jar": "pkg:maven/org.springframework.security/spring-security-core@6.0.2", + "/packages/spring-security-kerberos-core-1.0.1.RELEASE.jar": "pkg:maven/org.springframework.security.kerberos/spring-security-kerberos-core@1.0.1.RELEASE", + "/packages/spring-security-oauth-2.5.1.RELEASE.jar": "pkg:maven/org.springframework.security.oauth/spring-security-oauth@2.5.1.RELEASE", + "/packages/spring-security-oauth2-autoconfigure-2.5.9.jar": "pkg:maven/org.springframework.security.oauth.boot/spring-security-oauth2-autoconfigure@2.5.9", + "/packages/spring-security-saml2-core-1.0.10.RELEASE.jar": "pkg:maven/org.springframework.security.extensions/spring-security-saml2-core@1.0.10.RELEASE", + "/packages/spring-session-core-3.0.0.jar": "pkg:maven/org.springframework.session/spring-session-core@3.0.0", + "/packages/spring-social-core-1.1.2.RELEASE.jar": "pkg:maven/org.springframework.social/spring-social-core@1.1.2.RELEASE", + "/packages/spring-vault-core-3.0.1.jar": "pkg:maven/org.springframework.vault/spring-vault-core@3.0.1", + "/packages/spring-webmvc-3.1.4.RELEASE.jar": "pkg:maven/org.springframework/spring-webmvc@3.1.4.RELEASE", + "/packages/spring-xml-3.0.3.RELEASE.jar": "pkg:maven/org.springframework.ws/spring-xml@3.0.3.RELEASE", + "/packages/ssh-credentials.hpi": "pkg:maven/org.jenkins-ci.plugins/ssh-credentials@1.18.1", + "/packages/ssh-credentials.hpi:WEB-INF/lib/ssh-credentials.jar": "pkg:maven/org.jenkins-ci.plugins/ssh-credentials@1.18.1", + "/packages/storm-core-1.2.2.jar": "pkg:maven/org.apache.storm/storm-core@1.2.2", + "/packages/storm-core-1.2.2.jar:cheshire:cheshire": "pkg:maven/cheshire/cheshire@5.3.1", + "/packages/storm-core-1.2.2.jar:clj-time:clj-time": "pkg:maven/clj-time/clj-time@0.8.0", + "/packages/storm-core-1.2.2.jar:clout:clout": "pkg:maven/clout/clout@1.2.0", + "/packages/storm-core-1.2.2.jar:com.fasterxml.jackson.core:jackson-core": "pkg:maven/com.fasterxml.jackson.core/jackson-core@2.9.4", + "/packages/storm-core-1.2.2.jar:com.fasterxml.jackson.dataformat:jackson-dataformat-smile": "pkg:maven/com.fasterxml.jackson.dataformat/jackson-dataformat-smile@2.9.4", + "/packages/storm-core-1.2.2.jar:com.google.guava:guava": "pkg:maven/com.google.guava/guava@16.0.1", + "/packages/storm-core-1.2.2.jar:com.twitter:carbonite": "pkg:maven/com.twitter/carbonite@1.5.0", + "/packages/storm-core-1.2.2.jar:commons-codec:commons-codec": "pkg:maven/commons-codec/commons-codec@1.6", + "/packages/storm-core-1.2.2.jar:commons-collections:commons-collections": "pkg:maven/commons-collections/commons-collections@3.2.2", + "/packages/storm-core-1.2.2.jar:commons-fileupload:commons-fileupload": "pkg:maven/commons-fileupload/commons-fileupload@1.3.2", + "/packages/storm-core-1.2.2.jar:commons-io:commons-io": "pkg:maven/commons-io/commons-io@2.5", + "/packages/storm-core-1.2.2.jar:commons-lang:commons-lang": "pkg:maven/commons-lang/commons-lang@2.5", + "/packages/storm-core-1.2.2.jar:compojure:compojure": "pkg:maven/compojure/compojure@1.1.9", + "/packages/storm-core-1.2.2.jar:hiccup:hiccup": "pkg:maven/hiccup/hiccup@0.3.6", + "/packages/storm-core-1.2.2.jar:io.netty:netty": "pkg:maven/io.netty/netty@3.9.9.Final", + "/packages/storm-core-1.2.2.jar:joda-time:joda-time": "pkg:maven/joda-time/joda-time@2.3", + "/packages/storm-core-1.2.2.jar:metrics-clojure:metrics-clojure": "pkg:maven/metrics-clojure/metrics-clojure@2.5.1", + "/packages/storm-core-1.2.2.jar:ns-tracker:ns-tracker": "pkg:maven/ns-tracker/ns-tracker@0.2.2", + "/packages/storm-core-1.2.2.jar:org.apache.commons:commons-compress": "pkg:maven/org.apache.commons/commons-compress@1.4.1", + "/packages/storm-core-1.2.2.jar:org.apache.commons:commons-exec": "pkg:maven/org.apache.commons/commons-exec@1.1", + "/packages/storm-core-1.2.2.jar:org.apache.curator:curator-client": "pkg:maven/org.apache.curator/curator-client@4.0.1", + "/packages/storm-core-1.2.2.jar:org.apache.curator:curator-framework": "pkg:maven/org.apache.curator/curator-framework@4.0.1", + "/packages/storm-core-1.2.2.jar:org.apache.curator:curator-recipes": "pkg:maven/org.apache.curator/curator-recipes@4.0.1", + "/packages/storm-core-1.2.2.jar:org.apache.hadoop:hadoop-auth": "pkg:maven/org.apache.hadoop/hadoop-auth@2.6.1", + "/packages/storm-core-1.2.2.jar:org.apache.httpcomponents:httpclient": "pkg:maven/org.apache.httpcomponents/httpclient@4.3.3", + "/packages/storm-core-1.2.2.jar:org.apache.httpcomponents:httpcore": "pkg:maven/org.apache.httpcomponents/httpcore@4.4.1", + "/packages/storm-core-1.2.2.jar:org.clojure:java.jmx": "pkg:maven/org.clojure/java.jmx@0.3.1", + "/packages/storm-core-1.2.2.jar:org.clojure:math.numeric-tower": "pkg:maven/org.clojure/math.numeric-tower@0.0.1", + "/packages/storm-core-1.2.2.jar:org.clojure:tools.cli": "pkg:maven/org.clojure/tools.cli@0.2.4", + "/packages/storm-core-1.2.2.jar:org.clojure:tools.logging": "pkg:maven/org.clojure/tools.logging@0.2.3", + "/packages/storm-core-1.2.2.jar:org.clojure:tools.macro": "pkg:maven/org.clojure/tools.macro@0.1.0", + "/packages/storm-core-1.2.2.jar:org.clojure:tools.namespace": "pkg:maven/org.clojure/tools.namespace@0.2.4", + "/packages/storm-core-1.2.2.jar:org.eclipse.jetty:jetty-client": "pkg:maven/org.eclipse.jetty/jetty-client@7.6.13.v20130916", + "/packages/storm-core-1.2.2.jar:org.eclipse.jetty:jetty-continuation": "pkg:maven/org.eclipse.jetty/jetty-continuation@7.6.13.v20130916", + "/packages/storm-core-1.2.2.jar:org.eclipse.jetty:jetty-http": "pkg:maven/org.eclipse.jetty/jetty-http@7.6.13.v20130916", + "/packages/storm-core-1.2.2.jar:org.eclipse.jetty:jetty-io": "pkg:maven/org.eclipse.jetty/jetty-io@7.6.13.v20130916", + "/packages/storm-core-1.2.2.jar:org.eclipse.jetty:jetty-security": "pkg:maven/org.eclipse.jetty/jetty-security@7.6.13.v20130916", + "/packages/storm-core-1.2.2.jar:org.eclipse.jetty:jetty-server": "pkg:maven/org.eclipse.jetty/jetty-server@7.6.13.v20130916", + "/packages/storm-core-1.2.2.jar:org.eclipse.jetty:jetty-servlet": "pkg:maven/org.eclipse.jetty/jetty-servlet@7.6.13.v20130916", + "/packages/storm-core-1.2.2.jar:org.eclipse.jetty:jetty-servlets": "pkg:maven/org.eclipse.jetty/jetty-servlets@7.6.13.v20130916", + "/packages/storm-core-1.2.2.jar:org.eclipse.jetty:jetty-util": "pkg:maven/org.eclipse.jetty/jetty-util@7.6.13.v20130916", + "/packages/storm-core-1.2.2.jar:org.jgrapht:jgrapht-core": "pkg:maven/org.jgrapht/jgrapht-core@0.9.0", + "/packages/storm-core-1.2.2.jar:org.yaml:snakeyaml": "pkg:maven/org.yaml/snakeyaml@1.11", + "/packages/storm-core-1.2.2.jar:ring:ring-codec": "pkg:maven/ring/ring-codec@1.0.0", + "/packages/storm-core-1.2.2.jar:ring:ring-core": "pkg:maven/ring/ring-core@1.3.1", + "/packages/storm-core-1.2.2.jar:ring:ring-devel": "pkg:maven/ring/ring-devel@1.3.1", + "/packages/storm-core-1.2.2.jar:ring:ring-jetty-adapter": "pkg:maven/ring/ring-jetty-adapter@1.3.1", + "/packages/storm-core-1.2.2.jar:ring:ring-json": "pkg:maven/ring/ring-json@0.3.1", + "/packages/storm-core-1.2.2.jar:ring:ring-servlet": "pkg:maven/ring/ring-servlet@1.3.1", + "/packages/tapestry-core-5.8.1.jar": "pkg:maven/org.apache.tapestry/tapestry-core@5.8.1", + "/packages/tika-core-1.26.jar": "pkg:maven/org.apache.tika/tika-core@1.26", + "/packages/tomcat-catalina-11.0.0-M1.jar": "pkg:maven/org.apache.tomcat/tomcat-catalina@11.0.0-M1", + "/packages/tomcat-embed-core-11.0.0-M7.jar": "pkg:maven/org.apache.tomcat.embed/tomcat-embed-core@11.0.0-M7", + "/packages/TwilioNotifier.hpi": "pkg:maven/com.twilio.jenkins/TwilioNotifier@0.2.1", + "/packages/TwilioNotifier.hpi:WEB-INF/lib/commons-codec-1.2.jar": "pkg:maven/commons-codec/commons-codec@1.2", + "/packages/TwilioNotifier.hpi:WEB-INF/lib/commons-logging-1.0.4.jar": "pkg:maven/commons-logging/commons-logging@1.0.4", + "/packages/TwilioNotifier.hpi:WEB-INF/lib/log4j-1.2.9.jar": "pkg:maven/log4j/log4j@1.2.9", + "/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:commons-codec:commons-codec": "pkg:maven/commons-codec/commons-codec@1.4", + "/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:commons-lang:commons-lang": "pkg:maven/commons-lang/commons-lang@2.5", + "/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:commons-logging:commons-logging": "pkg:maven/commons-logging/commons-logging@1.1.1", + "/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:org.apache.httpcomponents:httpclient": "pkg:maven/org.apache.httpcomponents/httpclient@4.1.1", + "/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:org.apache.httpcomponents:httpcore": "pkg:maven/org.apache.httpcomponents/httpcore@4.1", + "/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:org.easymock:easymock": "pkg:maven/org.easymock/easymock@2.4", + "/packages/undertow-core-2.3.4.Final.jar": "pkg:maven/io.undertow/undertow-core@2.3.4.Final", + "/packages/vaadin-client-8.11.3.jar": "pkg:maven/com.vaadin/vaadin-client@8.11.3", + "/packages/velocity-1.7.jar": "pkg:maven/org.apache.velocity/velocity@1.7", + "/packages/vertx-web-4.3.7.jar": "pkg:maven/io.vertx/vertx-web@4.3.7", + "/packages/wicket-core-9.2.0.jar": "pkg:maven/org.apache.wicket/wicket-core@9.2.0", + "/packages/xalan-2.7.2.jar": "pkg:maven/xalan/xalan@2.7.2", + "/packages/xmlpull-1.1.3.1.jar": "pkg:maven/xmlpull/xmlpull@1.1.3.1", + "/packages/xstream-1.4.11.1.jar": "pkg:maven/com.thoughtworks.xstream/xstream@1.4.11.1", + "/packages/xstream-1.4.19.jar": "pkg:maven/com.thoughtworks.xstream/xstream@1.4.19", + "/packages/xwiki-commons-xml-15.1.jar": "pkg:maven/org.xwiki.commons/xwiki-commons-xml@15.1", + "/packages/xwiki-platform-oldcore-15.3.jar": "pkg:maven/org.xwiki.platform/xwiki-platform-oldcore@15.3", + "/packages/zookeeper-3.7.1.jar": "pkg:maven/org.apache.zookeeper/zookeeper@3.7.1", + "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/readline.jar:jline:jline": "pkg:maven/jline/jline@2.11", + "/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/readline.jar:rubygems:jruby-readline": "pkg:maven/rubygems/jruby-readline@1.2.0", } diff --git a/cmd/syft/internal/test/integration/test-fixtures/image-test-java-purls/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-test-java-purls/Dockerfile index 9d9b93041..16f074b36 100644 --- a/cmd/syft/internal/test/integration/test-fixtures/image-test-java-purls/Dockerfile +++ b/cmd/syft/internal/test/integration/test-fixtures/image-test-java-purls/Dockerfile @@ -1 +1,3 @@ -FROM anchore/test_images:java-1abc58f@sha256:3add9f90e9ed35739cc99b7830767e09eec921052e2412adf4491648c741f066 +FROM docker.io/anchore/test_images:java-88948cc@sha256:dea0e6c24636937f53bdc997d9960c2a18966d1e38bcd8ebd0c395d4e169b806 + +RUN rm /packages/gradle-7.1.1-bin.zip \ No newline at end of file diff --git a/syft/pkg/cataloger/internal/cpegenerate/java.go b/syft/pkg/cataloger/internal/cpegenerate/java.go index 8ccd38059..4099effb3 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/java.go +++ b/syft/pkg/cataloger/internal/cpegenerate/java.go @@ -23,6 +23,7 @@ var ( } PrimaryJavaManifestGroupIDFields = []string{ + "Group-Id", "Bundle-SymbolicName", "Extension-Name", "Specification-Vendor", diff --git a/syft/pkg/cataloger/java/archive_parser.go b/syft/pkg/cataloger/java/archive_parser.go index 1de3ab80a..d2e16898c 100644 --- a/syft/pkg/cataloger/java/archive_parser.go +++ b/syft/pkg/cataloger/java/archive_parser.go @@ -155,9 +155,14 @@ func (j *archiveParser) parse(ctx context.Context) ([]pkg.Package, []artifact.Re p := &pkgs[i] if m, ok := p.Metadata.(pkg.JavaArchive); ok { p.PURL = packageURL(p.Name, p.Version, m) + + if strings.Contains(p.PURL, "io.jenkins.plugins") || strings.Contains(p.PURL, "org.jenkins-ci.plugins") { + p.Type = pkg.JenkinsPluginPkg + } } else { log.WithFields("package", p.String()).Warn("unable to extract java metadata to generate purl") } + p.SetID() } diff --git a/syft/pkg/cataloger/java/archive_parser_test.go b/syft/pkg/cataloger/java/archive_parser_test.go index ccddc8c75..2faf003d2 100644 --- a/syft/pkg/cataloger/java/archive_parser_test.go +++ b/syft/pkg/cataloger/java/archive_parser_test.go @@ -65,7 +65,7 @@ func TestSearchMavenForLicenses(t *testing.T) { // this fixture has a pomProjectObject and has a parent object // it has no licenses on either which is the condition for testing // the searchMavenForLicenses functionality - jarName := generateJavaMetadataJarFixture(t, tc.fixture) + jarName := generateJavaMetadataJarFixture(t, tc.fixture, "jar") fixture, err := os.Open(jarName) require.NoError(t, err) @@ -1082,6 +1082,7 @@ func Test_parseJavaArchive_regressions(t *testing.T) { tests := []struct { name string fixtureName string + fileExtension string expectedPkgs []pkg.Package expectedRelationships []artifact.Relationship assignParent bool @@ -1274,6 +1275,45 @@ func Test_parseJavaArchive_regressions(t *testing.T) { fixtureName: "spring-instrumentation-4.3.0-1.0", expectedPkgs: nil, // we expect no packages to be discovered when Weave-Classes present in the manifest }, + { + name: "Jenkins plugins assigned jenkins-plugin package type", + fixtureName: "gradle", + fileExtension: "hpi", + expectedPkgs: []pkg.Package{ + { + Name: "gradle", + Version: "2.11", + Type: pkg.JenkinsPluginPkg, + Language: pkg.Java, + PURL: "pkg:maven/org.jenkins-ci.plugins/gradle@2.11", + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/jar-metadata/cache/gradle.hpi")), + Metadata: pkg.JavaArchive{ + VirtualPath: "test-fixtures/jar-metadata/cache/gradle.hpi", + Manifest: &pkg.JavaManifest{ + Main: pkg.KeyValues{ + {Key: "Manifest-Version", Value: "1.0"}, + { + Key: "Plugin-Dependencies", + Value: "maven-plugin:3.14;resolution:=optional...snip", + }, + {Key: "Group-Id", Value: "org.jenkins-ci.plugins"}, + {Key: "Minimum-Java-Version", Value: "1.8"}, + {Key: "Short-Name", Value: "gradle"}, + {Key: "Extension-Name", Value: "gradle"}, + {Key: "Long-Name", Value: "Gradle Plugin"}, + {Key: "Jenkins-Version", Value: "2.303.3"}, + {Key: "Url", Value: "https://github.com/jenkinsci/gradle-plugin"}, + {Key: "Compatible-Since-Version", Value: "1.0"}, + {Key: "Plugin-Version", Value: "2.11"}, + {Key: "Plugin-Developers", Value: "Stefan Wolf:wolfs:"}, + }, + }, + // not under test + //ArchiveDigests: []file.Digest{{Algorithm: "sha1", Value: "d8bc1d9c428c96fe447e2c429fc4304d141024df"}}, + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -1285,7 +1325,7 @@ func Test_parseJavaArchive_regressions(t *testing.T) { tt.expectedPkgs[i].SetID() } pkgtest.NewCatalogTester(). - FromFile(t, generateJavaMetadataJarFixture(t, tt.fixtureName)). + FromFile(t, generateJavaMetadataJarFixture(t, tt.fixtureName, tt.fileExtension)). Expects(tt.expectedPkgs, tt.expectedRelationships). WithCompareOptions( cmpopts.IgnoreFields(pkg.JavaArchive{}, "ArchiveDigests"), @@ -1318,7 +1358,7 @@ func Test_deterministicMatchingPomProperties(t *testing.T) { for _, test := range tests { t.Run(test.fixture, func(t *testing.T) { - fixturePath := generateJavaMetadataJarFixture(t, test.fixture) + fixturePath := generateJavaMetadataJarFixture(t, test.fixture, "jar") for i := 0; i < 5; i++ { func() { @@ -1372,14 +1412,18 @@ func generateJavaBuildFixture(t *testing.T, fixturePath string) { run(t, cmd) } -func generateJavaMetadataJarFixture(t *testing.T, fixtureName string) string { - fixturePath := filepath.Join("test-fixtures/jar-metadata/cache/", fixtureName+".jar") +func generateJavaMetadataJarFixture(t *testing.T, fixtureName string, fileExtension string) string { + if fileExtension == "" { + fileExtension = "jar" + } + + fixturePath := filepath.Join("test-fixtures/jar-metadata/cache/", fixtureName+"."+fileExtension) if _, err := os.Stat(fixturePath); !os.IsNotExist(err) { // fixture already exists... return fixturePath } - makeTask := filepath.Join("cache", fixtureName+".jar") + makeTask := filepath.Join("cache", fixtureName+"."+fileExtension) t.Logf(color.Bold.Sprintf("Generating Fixture from 'make %s'", makeTask)) cwd, err := os.Getwd() diff --git a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/Makefile b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/Makefile index c5d3c52a3..980839042 100644 --- a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/Makefile +++ b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/Makefile @@ -28,3 +28,8 @@ $(CACHE_DIR)/$(SPRING_INSTRUMENTATION).jar: $(CACHE_DIR) $(CACHE_DIR)/$(MULTIPLE_MATCHING).jar: $(CACHE_DIR) cd $(MULTIPLE_MATCHING) && zip -r $(CACHE_PATH)/$(MULTIPLE_MATCHING).jar . + +# Jenkins plugins typically do not have the version included in the archive name, +# so it is important to not include it in the generated test fixture +$(CACHE_DIR)/gradle.hpi: $(CACHE_DIR) + cd jenkins-plugins/gradle/2.11 && zip -r $(CACHE_PATH)/gradle.hpi . \ No newline at end of file diff --git a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/jenkins-plugins/gradle/2.11/META-INF/MANIFEST.MF b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/jenkins-plugins/gradle/2.11/META-INF/MANIFEST.MF new file mode 100644 index 000000000..eb2ed2177 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/jenkins-plugins/gradle/2.11/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Plugin-Dependencies: maven-plugin:3.14;resolution:=optional...snip +Group-Id: org.jenkins-ci.plugins +Minimum-Java-Version: 1.8 +Short-Name: gradle +Extension-Name: gradle +Long-Name: Gradle Plugin +Jenkins-Version: 2.303.3 +Url: https://github.com/jenkinsci/gradle-plugin +Compatible-Since-Version: 1.0 +Plugin-Version: 2.11 +Plugin-Developers: Stefan Wolf:wolfs: + From 3161e1847efab3815b51eceb2f1a81cd8944eb34 Mon Sep 17 00:00:00 2001 From: Lukas Voetmand Date: Mon, 12 Aug 2024 22:37:23 +0200 Subject: [PATCH 144/284] fix: read CycloneDX BOM components from metadata (#3092) Signed-off-by: dervoeti --- .../sbom_metadata_component_test.go | 25 +++++++++++++++ .../image-sbom-metadata-component/Dockerfile | 2 ++ .../test.cdx.json | 32 +++++++++++++++++++ .../internal/cyclonedxutil/helpers/decoder.go | 19 ++++++++--- 4 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 cmd/syft/internal/test/integration/sbom_metadata_component_test.go create mode 100644 cmd/syft/internal/test/integration/test-fixtures/image-sbom-metadata-component/Dockerfile create mode 100644 cmd/syft/internal/test/integration/test-fixtures/image-sbom-metadata-component/test.cdx.json diff --git a/cmd/syft/internal/test/integration/sbom_metadata_component_test.go b/cmd/syft/internal/test/integration/sbom_metadata_component_test.go new file mode 100644 index 000000000..d45a2f1cd --- /dev/null +++ b/cmd/syft/internal/test/integration/sbom_metadata_component_test.go @@ -0,0 +1,25 @@ +package integration + +import ( + "reflect" + "testing" + + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/source" +) + +func TestSbomMetadataComponent(t *testing.T) { + sbom, _ := catalogFixtureImage(t, "image-sbom-metadata-component", source.SquashedScope, "+sbom-cataloger") + + expectedPkgs := []string{"first-subcomponent", "main-component"} + foundPkgs := []string{} + + for sbomPkg := range sbom.Artifacts.Packages.Enumerate(pkg.JavaPkg) { + foundPkgs = append(foundPkgs, sbomPkg.Name) + } + + // check if both the package in `.metadata.component` and the one in `.components` were found + if !reflect.DeepEqual(expectedPkgs, foundPkgs) { + t.Errorf("expected packages %v, got %v", expectedPkgs, foundPkgs) + } +} diff --git a/cmd/syft/internal/test/integration/test-fixtures/image-sbom-metadata-component/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-sbom-metadata-component/Dockerfile new file mode 100644 index 000000000..6861c4d63 --- /dev/null +++ b/cmd/syft/internal/test/integration/test-fixtures/image-sbom-metadata-component/Dockerfile @@ -0,0 +1,2 @@ +FROM scratch +COPY test.cdx.json / diff --git a/cmd/syft/internal/test/integration/test-fixtures/image-sbom-metadata-component/test.cdx.json b/cmd/syft/internal/test/integration/test-fixtures/image-sbom-metadata-component/test.cdx.json new file mode 100644 index 000000000..6695b7c0a --- /dev/null +++ b/cmd/syft/internal/test/integration/test-fixtures/image-sbom-metadata-component/test.cdx.json @@ -0,0 +1,32 @@ +{ + "bomFormat" : "CycloneDX", + "specVersion" : "1.5", + "serialNumber" : "urn:uuid:dc807d4b-0415-35ab-ba61-49b5d39bc2d9", + "version" : 1, + "metadata" : { + "component" : { + "name" : "main-component", + "version" : "1.2.3", + "purl" : "pkg:maven/org.example/main-component@1.2.3", + "type" : "library", + "bom-ref" : "pkg:maven/org.example/main-component@1.2.3" + } + }, + "components" : [ + { + "name" : "first-subcomponent", + "version" : "2.3.4", + "purl" : "pkg:maven/org.example/first-subcomponent@2.3.4", + "type" : "library", + "bom-ref" : "pkg:maven/org.example/first-subcomponent@2.3.4" + } + ], + "dependencies" : [ + { + "ref" : "pkg:maven/org.example/main-component-assembly@1.2.3", + "dependsOn" : [ + "pkg:maven/org.example/first-subcomponent@2.3.4" + ] + } + ] +} \ No newline at end of file diff --git a/syft/format/internal/cyclonedxutil/helpers/decoder.go b/syft/format/internal/cyclonedxutil/helpers/decoder.go index fdf8ffe98..c4c706e38 100644 --- a/syft/format/internal/cyclonedxutil/helpers/decoder.go +++ b/syft/format/internal/cyclonedxutil/helpers/decoder.go @@ -39,12 +39,23 @@ func ToSyftModel(bom *cyclonedx.BOM) (*sbom.SBOM, error) { } func collectBomPackages(bom *cyclonedx.BOM, s *sbom.SBOM, idMap map[string]interface{}) error { - if bom.Components == nil { - return fmt.Errorf("no components are defined in the CycloneDX BOM") + componentsPresent := false + if bom.Components != nil { + for i := range *bom.Components { + collectPackages(&(*bom.Components)[i], s, idMap) + } + componentsPresent = true } - for i := range *bom.Components { - collectPackages(&(*bom.Components)[i], s, idMap) + + if bom.Metadata != nil && bom.Metadata.Component != nil { + collectPackages(bom.Metadata.Component, s, idMap) + componentsPresent = true } + + if !componentsPresent { + return fmt.Errorf("no components are defined in the CycloneDX BOM") + } + return nil } From cd3b828905ec2bf0620ceab529c9f3734bcc234a Mon Sep 17 00:00:00 2001 From: Lucas Rodriguez Date: Tue, 13 Aug 2024 15:02:15 -0500 Subject: [PATCH 145/284] fix: add nil check to CycloneDX toBomProperties (#3119) Signed-off-by: Lucas Rodriguez --- .../cyclonedxhelpers/to_format_model.go | 6 +++ .../cyclonedxhelpers/to_format_model_test.go | 47 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/syft/format/common/cyclonedxhelpers/to_format_model.go b/syft/format/common/cyclonedxhelpers/to_format_model.go index e2f3a285f..ba93a367e 100644 --- a/syft/format/common/cyclonedxhelpers/to_format_model.go +++ b/syft/format/common/cyclonedxhelpers/to_format_model.go @@ -211,6 +211,12 @@ func toBomProperties(srcMetadata source.Description) *[]cyclonedx.Property { metadata, ok := srcMetadata.Metadata.(source.ImageMetadata) if ok { props := helpers.EncodeProperties(metadata.Labels, "syft:image:labels") + // return nil if props is nil to avoid creating a pointer to a nil slice, + // which results in a null JSON value that does not comply with the CycloneDX schema. + // https://github.com/anchore/grype/issues/1759 + if props == nil { + return nil + } return &props } return nil diff --git a/syft/format/common/cyclonedxhelpers/to_format_model_test.go b/syft/format/common/cyclonedxhelpers/to_format_model_test.go index de3408082..c3ac1f3b8 100644 --- a/syft/format/common/cyclonedxhelpers/to_format_model_test.go +++ b/syft/format/common/cyclonedxhelpers/to_format_model_test.go @@ -236,6 +236,53 @@ func Test_toBomDescriptor(t *testing.T) { } } +func Test_toBomProperties(t *testing.T) { + tests := []struct { + name string + srcMetadata source.Description + props *[]cyclonedx.Property + }{ + { + name: "ImageMetadata without labels", + srcMetadata: source.Description{ + Metadata: source.ImageMetadata{ + Labels: map[string]string{}, + }, + }, + props: nil, + }, + { + name: "ImageMetadata with labels", + srcMetadata: source.Description{ + Metadata: source.ImageMetadata{ + Labels: map[string]string{ + "label1": "value1", + "label2": "value2", + }, + }, + }, + props: &[]cyclonedx.Property{ + {Name: "syft:image:labels:label1", Value: "value1"}, + {Name: "syft:image:labels:label2", Value: "value2"}, + }, + }, + { + name: "not ImageMetadata", + srcMetadata: source.Description{ + Metadata: source.FileMetadata{}, + }, + props: nil, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + props := toBomProperties(test.srcMetadata) + require.Equal(t, test.props, props) + }) + } +} + func Test_toOsComponent(t *testing.T) { tests := []struct { name string From a447884084fbdca657cfb25297104675a610a5be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2024 13:16:39 -0400 Subject: [PATCH 146/284] chore(deps): bump github/codeql-action from 3.26.0 to 3.26.2 (#3129) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.0 to 3.26.2. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/eb055d739abdc2e8de2e5f4ba1a8b246daa779aa...429e1977040da7a23b6822b13c129cd1ba93dbb2) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 46fc84963..54b4633e1 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa #v3.26.0 + uses: github/codeql-action/init@429e1977040da7a23b6822b13c129cd1ba93dbb2 #v3.26.2 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa #v3.26.0 + uses: github/codeql-action/autobuild@429e1977040da7a23b6822b13c129cd1ba93dbb2 #v3.26.2 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa #v3.26.0 + uses: github/codeql-action/analyze@429e1977040da7a23b6822b13c129cd1ba93dbb2 #v3.26.2 From 965000dcbb86656b6d7b9f7731b0a9065e104d9b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2024 13:16:47 -0400 Subject: [PATCH 147/284] chore(deps): bump anchore/sbom-action from 0.17.0 to 0.17.1 (#3124) Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.17.0 to 0.17.1. - [Release notes](https://github.com/anchore/sbom-action/releases) - [Commits](https://github.com/anchore/sbom-action/compare/d94f46e13c6c62f59525ac9a1e147a99dc0b9bf5...ab9d16d4b419c9d1a02df5213fa0ebe965ca5a57) --- updated-dependencies: - dependency-name: anchore/sbom-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 734fc7a32..dc79d685f 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -148,7 +148,7 @@ jobs: # for updating brew formula in anchore/homebrew-syft GITHUB_BREW_TOKEN: ${{ secrets.ANCHOREOPS_GITHUB_OSS_WRITE_TOKEN }} - - uses: anchore/sbom-action@d94f46e13c6c62f59525ac9a1e147a99dc0b9bf5 #v0.17.0 + - uses: anchore/sbom-action@ab9d16d4b419c9d1a02df5213fa0ebe965ca5a57 #v0.17.1 continue-on-error: true with: artifact-name: sbom.spdx.json From 4ff60ee83714614272512d8bf9fa174cfd6a4d2f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2024 13:50:51 -0400 Subject: [PATCH 148/284] chore(deps): bump github.com/docker/docker (#3123) Bumps [github.com/docker/docker](https://github.com/docker/docker) from 27.1.1+incompatible to 27.1.2+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.1.1...v27.1.2) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 56b075e10..0e7cfbc54 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/dave/jennifer v1.7.0 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da github.com/distribution/reference v0.6.0 - github.com/docker/docker v27.1.1+incompatible + github.com/docker/docker v27.1.2+incompatible github.com/dustin/go-humanize v1.0.1 github.com/elliotchance/phpserialize v1.4.0 github.com/facebookincubator/nvdtools v0.1.5 diff --git a/go.sum b/go.sum index 15800d2ab..6d6bbd458 100644 --- a/go.sum +++ b/go.sum @@ -231,8 +231,8 @@ github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2 github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= -github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.2+incompatible h1:AhGzR1xaQIy53qCkxARaFluI00WPGtXn0AJuoQsVYTY= +github.com/docker/docker v27.1.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= From 4b7ae0ed3b8f41dbaf03b14c1af4db3d26a8c5bb Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Fri, 16 Aug 2024 17:56:36 +0000 Subject: [PATCH 149/284] chore(deps): update tools to latest versions (#3121) * chore(deps): update tools to latest versions Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * chore: update code to reflect new linter settings for error messages Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> --------- Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 4 ++-- cmd/syft/internal/commands/scan.go | 2 +- internal/cache/error_resolver.go | 2 +- syft/internal/packagemetadata/discover_type_names.go | 3 ++- syft/internal/sourcemetadata/discover_type_names.go | 3 ++- syft/pkg/cataloger/cpp/parse_conanfile.go | 2 +- syft/pkg/cataloger/cpp/parse_conaninfo.go | 2 +- syft/pkg/cataloger/elixir/parse_mix_lock.go | 2 +- syft/pkg/cataloger/haskell/parse_cabal_freeze.go | 2 +- 9 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.binny.yaml b/.binny.yaml index 42ea5c760..686e946ec 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -26,7 +26,7 @@ tools: # used for linting - name: golangci-lint version: - want: v1.59.1 + want: v1.60.1 method: github-release with: repo: golangci/golangci-lint @@ -58,7 +58,7 @@ tools: # used to release all artifacts - name: goreleaser version: - want: v2.1.0 + want: v2.2.0 method: github-release with: repo: goreleaser/goreleaser diff --git a/cmd/syft/internal/commands/scan.go b/cmd/syft/internal/commands/scan.go index ff5b4254f..efec9dd5b 100644 --- a/cmd/syft/internal/commands/scan.go +++ b/cmd/syft/internal/commands/scan.go @@ -161,7 +161,7 @@ func validateArgs(cmd *cobra.Command, args []string, error string) error { if err := cmd.Help(); err != nil { return fmt.Errorf("unable to display help: %w", err) } - return fmt.Errorf(error) + return fmt.Errorf("%v", error) } return cobra.MaximumNArgs(1)(cmd, args) diff --git a/internal/cache/error_resolver.go b/internal/cache/error_resolver.go index 614d707f1..efbf915aa 100644 --- a/internal/cache/error_resolver.go +++ b/internal/cache/error_resolver.go @@ -34,7 +34,7 @@ func (r *errorResolver[T]) Resolve(key string, resolver resolverFunc[T]) (T, err return v.Value, err } if v.Error != "" { - return v.Value, fmt.Errorf(v.Error) + return v.Value, fmt.Errorf("failed to resolve cache: %s", v.Error) } return v.Value, nil } diff --git a/syft/internal/packagemetadata/discover_type_names.go b/syft/internal/packagemetadata/discover_type_names.go index ca9b2c9dd..03f8a4cc6 100644 --- a/syft/internal/packagemetadata/discover_type_names.go +++ b/syft/internal/packagemetadata/discover_type_names.go @@ -78,7 +78,8 @@ func findMetadataDefinitionNames(paths ...string) ([]string, error) { // note: 35 is a point-in-time gut check. This number could be updated if new metadata definitions are added, but is not required. // it is really intended to catch any major issues with the generation process that would generate, say, 0 definitions. if len(strNames) < 35 { - return nil, fmt.Errorf("not enough metadata definitions found (discovered: " + fmt.Sprintf("%d", len(strNames)) + ")") + msg := fmt.Sprintf("not enough metadata definitions found (discovered %d)", len(strNames)) + return nil, fmt.Errorf("%v", msg) } return strNames, nil diff --git a/syft/internal/sourcemetadata/discover_type_names.go b/syft/internal/sourcemetadata/discover_type_names.go index 9b1ac2f58..905de200a 100644 --- a/syft/internal/sourcemetadata/discover_type_names.go +++ b/syft/internal/sourcemetadata/discover_type_names.go @@ -68,7 +68,8 @@ func findMetadataDefinitionNames(paths ...string) ([]string, error) { // note: 3 is a point-in-time gut check. This number could be updated if new metadata definitions are added, but is not required. // it is really intended to catch any major issues with the generation process that would generate, say, 0 definitions. if len(strNames) < 3 { - return nil, fmt.Errorf("not enough metadata definitions found (discovered: " + fmt.Sprintf("%d", len(strNames)) + ")") + msg := fmt.Sprintf("not enough metadata definitions found (discovered %d)", len(strNames)) + return nil, fmt.Errorf("%v", msg) } return strNames, nil diff --git a/syft/pkg/cataloger/cpp/parse_conanfile.go b/syft/pkg/cataloger/cpp/parse_conanfile.go index dc22f80bd..622acbdcb 100644 --- a/syft/pkg/cataloger/cpp/parse_conanfile.go +++ b/syft/pkg/cataloger/cpp/parse_conanfile.go @@ -24,7 +24,7 @@ func parseConanfile(_ context.Context, _ file.Resolver, _ *generic.Environment, for { line, err := r.ReadString('\n') switch { - case errors.Is(io.EOF, err): + case errors.Is(err, io.EOF): return pkgs, nil, nil case err != nil: return nil, nil, fmt.Errorf("failed to parse conanfile.txt file: %w", err) diff --git a/syft/pkg/cataloger/cpp/parse_conaninfo.go b/syft/pkg/cataloger/cpp/parse_conaninfo.go index 7140e47c9..8094b3406 100644 --- a/syft/pkg/cataloger/cpp/parse_conaninfo.go +++ b/syft/pkg/cataloger/cpp/parse_conaninfo.go @@ -99,7 +99,7 @@ func parseConaninfo(_ context.Context, _ file.Resolver, _ *generic.Environment, for { line, err := r.ReadString('\n') switch { - case errors.Is(io.EOF, err): + case errors.Is(err, io.EOF): mainPackage := newConaninfoPackage( mainMetadata, reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), diff --git a/syft/pkg/cataloger/elixir/parse_mix_lock.go b/syft/pkg/cataloger/elixir/parse_mix_lock.go index 28ba38c3d..dcd4a7858 100644 --- a/syft/pkg/cataloger/elixir/parse_mix_lock.go +++ b/syft/pkg/cataloger/elixir/parse_mix_lock.go @@ -28,7 +28,7 @@ func parseMixLock(_ context.Context, _ file.Resolver, _ *generic.Environment, re for { line, err := r.ReadString('\n') switch { - case errors.Is(io.EOF, err): + case errors.Is(err, io.EOF): return packages, nil, nil case err != nil: return nil, nil, fmt.Errorf("failed to parse mix.lock file: %w", err) diff --git a/syft/pkg/cataloger/haskell/parse_cabal_freeze.go b/syft/pkg/cataloger/haskell/parse_cabal_freeze.go index 6bedc3e69..614524cae 100644 --- a/syft/pkg/cataloger/haskell/parse_cabal_freeze.go +++ b/syft/pkg/cataloger/haskell/parse_cabal_freeze.go @@ -23,7 +23,7 @@ func parseCabalFreeze(_ context.Context, _ file.Resolver, _ *generic.Environment for { line, err := r.ReadString('\n') switch { - case errors.Is(io.EOF, err): + case errors.Is(err, io.EOF): return pkgs, nil, nil case err != nil: return nil, nil, fmt.Errorf("failed to parse cabal.project.freeze file: %w", err) From 360983f75b18d4fbdd42ea05c3d04a2cd4c9836a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 12:48:24 -0400 Subject: [PATCH 150/284] chore(deps): bump github.com/charmbracelet/bubbletea (#3137) Bumps [github.com/charmbracelet/bubbletea](https://github.com/charmbracelet/bubbletea) from 0.26.6 to 0.27.0. - [Release notes](https://github.com/charmbracelet/bubbletea/releases) - [Changelog](https://github.com/charmbracelet/bubbletea/blob/master/.goreleaser.yml) - [Commits](https://github.com/charmbracelet/bubbletea/compare/v0.26.6...v0.27.0) --- updated-dependencies: - dependency-name: github.com/charmbracelet/bubbletea dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 0e7cfbc54..d1173d9c1 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 github.com/bmatcuk/doublestar/v4 v4.6.1 github.com/charmbracelet/bubbles v0.18.0 - github.com/charmbracelet/bubbletea v0.26.6 + github.com/charmbracelet/bubbletea v0.27.0 github.com/charmbracelet/lipgloss v0.12.1 github.com/dave/jennifer v1.7.0 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da @@ -232,7 +232,7 @@ require ( go.uber.org/multierr v1.9.0 // indirect golang.org/x/crypto v0.26.0 // indirect golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.23.0 // indirect + golang.org/x/sys v0.24.0 // indirect golang.org/x/term v0.23.0 // indirect golang.org/x/text v0.17.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect diff --git a/go.sum b/go.sum index 6d6bbd458..eda4db73c 100644 --- a/go.sum +++ b/go.sum @@ -157,8 +157,8 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0= github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw= -github.com/charmbracelet/bubbletea v0.26.6 h1:zTCWSuST+3yZYZnVSvbXwKOPRSNZceVeqpzOLN2zq1s= -github.com/charmbracelet/bubbletea v0.26.6/go.mod h1:dz8CWPlfCCGLFbBlTY4N7bjLiyOGDJEnd2Muu7pOWhk= +github.com/charmbracelet/bubbletea v0.27.0 h1:Mznj+vvYuYagD9Pn2mY7fuelGvP0HAXtZYGgRBCbHvU= +github.com/charmbracelet/bubbletea v0.27.0/go.mod h1:5MdP9XH6MbQkgGhnlxUqCNmBXf9I74KRQ8HIidRxV1Y= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v0.12.1 h1:/gmzszl+pedQpjCOH+wFkZr/N90Snz40J/NR7A0zQcs= @@ -1081,8 +1081,8 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= -golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= From 511cc9c2d5f80a770dc3ec0880cce08e9f80796b Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 12:49:43 -0400 Subject: [PATCH 151/284] chore(deps): update CPE dictionary index (#3135) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: wagoodman <590471+wagoodman@users.noreply.github.com> --- .../internal/cpegenerate/dictionary/data/cpe-index.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index 586be8f3e..8fd77ee19 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -2080,6 +2080,9 @@ "@braintree/sanitize-url": [ "cpe:2.3:a:paypal:braintree\\/sanitize-url:*:*:*:*:*:node.js:*:*" ], + "@builder.io/qwik": [ + "cpe:2.3:a:qwik:qwik:*:*:*:*:*:node.js:*:*" + ], "@chainsafe/libp2p-noise": [ "cpe:2.3:a:chainsafe:js-libp2p-noise:*:*:*:*:*:node.js:*:*" ], @@ -5273,6 +5276,9 @@ "weather.swlyons": [ "cpe:2.3:a:weather.swlyons_project:weather.swlyons:*:*:*:*:*:node.js:*:*" ], + "webcrack": [ + "cpe:2.3:a:j4k0xb:webcrack:*:*:*:*:*:node.js:*:*" + ], "webdriver-launcher": [ "cpe:2.3:a:webdriver-launcher_project:webdriver-launcher:*:*:*:*:*:node.js:*:*" ], @@ -6307,6 +6313,9 @@ "secure_headers": [ "cpe:2.3:a:twitter:secure_headers:*:*:*:*:*:ruby:*:*" ], + "sequenceserver": [ + "cpe:2.3:a:wurmlab:sequenceserver:*:*:*:*:*:ruby:*:*" + ], "sfpagent": [ "cpe:2.3:a:herry:sfpagent:*:*:*:*:*:ruby:*:*" ], From 95b4a88256bddebb91831250f28f602f8c36552a Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Tue, 20 Aug 2024 11:45:33 -0400 Subject: [PATCH 152/284] fix: logging for remote network calls (#3140) Signed-off-by: Keith Zantow --- internal/spdxlicense/license_list.go | 15 +++++++++++++-- syft/pkg/cataloger/golang/licenses.go | 4 ++++ syft/pkg/cataloger/javascript/package.go | 6 +++--- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/internal/spdxlicense/license_list.go b/internal/spdxlicense/license_list.go index 18e2a88ca..05a78d95c 100644 --- a/internal/spdxlicense/license_list.go +++ b/internal/spdxlicense/license_list.go @@ -1,9 +1,9 @@ // Code generated by go generate; DO NOT EDIT. -// This file was generated by robots at 2024-05-23 08:47:23.204981 -0400 EDT m=+0.050881068 +// This file was generated by robots at 2024-08-20 11:33:49.349625 -0400 EDT m=+0.383911876 // using data from https://spdx.org/licenses/licenses.json package spdxlicense -const Version = "3.24.0" +const Version = "3.25.0" var licenseIDs = map[string]string{ "0bsd": "0BSD", @@ -501,6 +501,8 @@ var licenseIDs = map[string]string{ "dldezero2.0": "DL-DE-ZERO-2.0", "dldezero2.0.0": "DL-DE-ZERO-2.0", "doc": "DOC", + "docbookschema": "DocBook-Schema", + "docbookxml": "DocBook-XML", "dotseqn": "Dotseqn", "drl1": "DRL-1.0", "drl1.0": "DRL-1.0", @@ -714,6 +716,7 @@ var licenseIDs = map[string]string{ "gutmann": "Gutmann", "haskellreport": "HaskellReport", "hdparm": "hdparm", + "hidapi": "HIDAPI", "hippocratic2": "Hippocratic-2.1", "hippocratic2.1": "Hippocratic-2.1", "hippocratic2.1.0": "Hippocratic-2.1", @@ -740,6 +743,7 @@ var licenseIDs = map[string]string{ "hpndmarkuskuhn": "HPND-Markus-Kuhn", "hpndmerchantabilityvariant": "HPND-merchantability-variant", "hpndmitdisclaimer": "HPND-MIT-disclaimer", + "hpndnetrek": "HPND-Netrek", "hpndpbmplus": "HPND-Pbmplus", "hpndsellmitdisclaimerxserver": "HPND-sell-MIT-disclaimer-xserver", "hpndsellregexpr": "HPND-sell-regexpr", @@ -1165,6 +1169,7 @@ var licenseIDs = map[string]string{ "rsamd": "RSA-MD", "rscpl": "RSCPL", "ruby": "Ruby", + "rubypty": "Ruby-pty", "saxpath": "Saxpath", "saxpd": "SAX-PD", "saxpd2": "SAX-PD-2.0", @@ -1265,6 +1270,9 @@ var licenseIDs = map[string]string{ "tuberlin2": "TU-Berlin-2.0", "tuberlin2.0": "TU-Berlin-2.0", "tuberlin2.0.0": "TU-Berlin-2.0", + "ubuntufont1": "Ubuntu-font-1.0", + "ubuntufont1.0": "Ubuntu-font-1.0", + "ubuntufont1.0.0": "Ubuntu-font-1.0", "ucar": "UCAR", "ucl1": "UCL-1.0", "ucl1.0": "UCL-1.0", @@ -1315,8 +1323,11 @@ var licenseIDs = map[string]string{ "x11.0": "X11", "x11.0.0": "X11", "x11.0.0distributemodificationsvariant": "X11-distribute-modifications-variant", + "x11.0.0swapped": "X11-swapped", "x11.0distributemodificationsvariant": "X11-distribute-modifications-variant", + "x11.0swapped": "X11-swapped", "x11distributemodificationsvariant": "X11-distribute-modifications-variant", + "x11swapped": "X11-swapped", "xdebug1": "Xdebug-1.03", "xdebug1.03": "Xdebug-1.03", "xdebug1.03.0": "Xdebug-1.03", diff --git a/syft/pkg/cataloger/golang/licenses.go b/syft/pkg/cataloger/golang/licenses.go index f53246314..0b02c6581 100644 --- a/syft/pkg/cataloger/golang/licenses.go +++ b/syft/pkg/cataloger/golang/licenses.go @@ -251,6 +251,7 @@ func getModule(proxies []string, moduleName, moduleVersion string) (urlPrefix st case "file": p := filepath.Join(u.Path, moduleName, "@v", moduleVersion) urlPrefix = path.Join("file://", p) + "/" + log.WithFields("path", p).Info("looking for go module in filesystem") fsys = os.DirFS(p) } if fsys != nil { @@ -264,6 +265,7 @@ func getModuleProxy(proxy string, moduleName string, moduleVersion string) (modu u := fmt.Sprintf("%s/%s/@v/%s.zip", proxy, moduleName, moduleVersion) // get the module zip + log.WithFields("url", u).Info("downloading go module from proxy") resp, err := http.Get(u) //nolint:gosec if err != nil { return "", nil, err @@ -334,6 +336,8 @@ func getModuleRepository(moduleName string, moduleVersion string) (string, fs.FS f := memfs.New() buf := &bytes.Buffer{} repoURL := fmt.Sprintf("https://%s", repoName) + + log.WithFields("repoURL", repoURL, "ref", cloneRefName).Info("cloning go module repository") r, err := git.Clone(memory.NewStorage(), f, &git.CloneOptions{ URL: repoURL, ReferenceName: cloneRefName, diff --git a/syft/pkg/cataloger/javascript/package.go b/syft/pkg/cataloger/javascript/package.go index 57df406b1..19114c99f 100644 --- a/syft/pkg/cataloger/javascript/package.go +++ b/syft/pkg/cataloger/javascript/package.go @@ -178,13 +178,13 @@ func formatNpmRegistryURL(baseURL, packageName, version string) (requestURL stri return requestURL, nil } -func getLicenseFromNpmRegistry(basURL, packageName, version string) (string, error) { +func getLicenseFromNpmRegistry(baseURL, packageName, version string) (string, error) { // "https://registry.npmjs.org/%s/%s", packageName, version - requestURL, err := formatNpmRegistryURL(basURL, packageName, version) + requestURL, err := formatNpmRegistryURL(baseURL, packageName, version) if err != nil { return "", fmt.Errorf("unable to format npm request for pkg:version %s%s; %w", packageName, version, err) } - log.Tracef("trying to fetch remote package %s", requestURL) + log.WithFields("url", requestURL).Info("downloading javascript package from npm") npmRequest, err := http.NewRequest(http.MethodGet, requestURL, nil) if err != nil { From f786233e979a46623c509d38ae3dd57553fbe52c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Aug 2024 23:04:58 +0000 Subject: [PATCH 153/284] chore(deps): bump github/codeql-action from 3.26.2 to 3.26.3 (#3139) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.2 to 3.26.3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/429e1977040da7a23b6822b13c129cd1ba93dbb2...883d8588e56d1753a8a58c1c86e88976f0c23449) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 54b4633e1..0ef325acd 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@429e1977040da7a23b6822b13c129cd1ba93dbb2 #v3.26.2 + uses: github/codeql-action/init@883d8588e56d1753a8a58c1c86e88976f0c23449 #v3.26.3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@429e1977040da7a23b6822b13c129cd1ba93dbb2 #v3.26.2 + uses: github/codeql-action/autobuild@883d8588e56d1753a8a58c1c86e88976f0c23449 #v3.26.3 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@429e1977040da7a23b6822b13c129cd1ba93dbb2 #v3.26.2 + uses: github/codeql-action/analyze@883d8588e56d1753a8a58c1c86e88976f0c23449 #v3.26.3 From 73b9d5aa4262186bd343ffc58f138382a0b5db0f Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Wed, 21 Aug 2024 09:48:28 -0400 Subject: [PATCH 154/284] fix: mysql 8.0.3x binary detection (#3142) Signed-off-by: Keith Zantow --- .../binary/classifier_cataloger_test.go | 11 +++++++++++ syft/pkg/cataloger/binary/classifiers.go | 8 ++++++-- .../snippets/mysql/8.0.34/linux-amd64/mysql | Bin 329 -> 349 bytes .../snippets/mysql/8.0.37/linux-amd64/mysql | Bin 0 -> 349 bytes .../cataloger/binary/test-fixtures/config.yaml | 7 +++++++ 5 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/mysql/8.0.37/linux-amd64/mysql diff --git a/syft/pkg/cataloger/binary/classifier_cataloger_test.go b/syft/pkg/cataloger/binary/classifier_cataloger_test.go index dcc9849c6..721ee9ee0 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger_test.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger_test.go @@ -116,6 +116,17 @@ func Test_Cataloger_PositiveCases(t *testing.T) { Metadata: metadata("mysql-binary"), }, }, + { + logicalFixture: "mysql/8.0.37/linux-amd64", + expected: pkg.Package{ + Name: "mysql", + Version: "8.0.37", + Type: "binary", + PURL: "pkg:generic/mysql@8.0.37", + Locations: locations("mysql"), + Metadata: metadata("mysql-binary"), + }, + }, { logicalFixture: "percona-server/8.0.35/linux-amd64", expected: pkg.Package{ diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index 0d491f25f..5f4d3aa66 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -294,8 +294,12 @@ func DefaultClassifiers() []Classifier { { Class: "mysql-binary", FileGlob: "**/mysql", - EvidenceMatcher: FileContentsVersionMatcher( - `(?m).*/mysql-(?P[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)`), + EvidenceMatcher: evidenceMatchers( + // shutdown[NUL]8.0.37[NUL][NUL][NUL][NUL][NUL]mysql_real_esc + FileContentsVersionMatcher(`\x00(?P[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)\x00+mysql`), + // /export/home/pb2/build/sb_0-26781090-1516292385.58/release/mysql-8.0.4-rc/mysys_ssl/my_default.cc + FileContentsVersionMatcher(`(?m).*/mysql-(?P[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)`), + ), Package: "mysql", PURL: mustPURL("pkg:generic/mysql@version"), CPEs: singleCPE("cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*"), diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/mysql/8.0.34/linux-amd64/mysql b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/mysql/8.0.34/linux-amd64/mysql index 571e977876d514a60f30550a982ec3942e92497f..9ff7ddd39cee298be9fcdaf561a6df90cd313d1e 100644 GIT binary patch delta 227 zcmZ{ZOAdlC6aa}!FW{CFkhYXk+`BTtL}Ogm*YXM`SkTs}x6osG2+!eXB^Pj#Sxn|J zdX8?BEzL+VZqe1DnZ}fnv3I+^$FOREWnvmznGp_l2%uW#R01cA5o5Ff0lGqAq())$ z6bsI5Wi(ct7rDiZ<{Z-d*K?VIBP#GVgiU_GmWS{NoB`wL_}*vm z9y}+z1hg5Iq26DL*%YK4we_KC!ew1Jg?2X0fmj8V*Z@SHHA+?<1Co@4o+&4fE-1<& zaB4uK(vE_|)KJDL!RuE0uHOy2{xR-)adl@=9#}N2M9W)<04PCaWCWHHqYYRcODoPz dCFYyuY9Xq7dnzM}WvtCVexDty>R5}c`~v5jKnnl> diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/mysql/8.0.37/linux-amd64/mysql b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/mysql/8.0.37/linux-amd64/mysql new file mode 100644 index 0000000000000000000000000000000000000000..45109e6f731ebcb52bb16f15e011ad92c23cf834 GIT binary patch literal 349 zcmZ`!O>4t249(fU!q9v1ryS?L)1ZTuv19Ou+yv4%ZCpx!`94lFTgOh5csz+GJ*3$k zv7^V^dYVX1X~oh}u9X31$b|Eu47C@Gtn;`mSoVVx8agUH0|U-8Q3s<*(T5gL3hhne z$~vw&xCkOx6e(KmeJ~20V@c?cWF%>v@Yf7w^k9TmyfvOB00gT8kFHIqICzMxl|jau zCPZ-PqwuXY(rVCJSwc3O4fVHz^nNBSnWj8V`AVxq9(PZ#yZ&YW@Z7A!rNn%ln|8~# r(lkHu{eOQ(H}$v%w_v}P^Ee;+(Cw& literal 0 HcmV?d00001 diff --git a/syft/pkg/cataloger/binary/test-fixtures/config.yaml b/syft/pkg/cataloger/binary/test-fixtures/config.yaml index 50dd6bcc8..9ea3c2de7 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/config.yaml +++ b/syft/pkg/cataloger/binary/test-fixtures/config.yaml @@ -157,6 +157,13 @@ from-images: paths: - /usr/bin/mysql + - version: 8.0.37 + images: + - ref: mysql:8.0.37-bookworm@sha256:bad55a5bb69d6710927792384b5eb55669ee15dc85dca1888874e4a7993eecd8 + platform: linux/amd64 + paths: + - /usr/bin/mysql + - name: percona-server version: 8.0.35 images: From bd80eeafac6457b511a6037ee0934121a79cbdcc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 13:51:50 -0400 Subject: [PATCH 155/284] chore(deps): bump github.com/anchore/stereoscope (#3153) Bumps [github.com/anchore/stereoscope](https://github.com/anchore/stereoscope) from 0.0.3-0.20240725180315-50ce3be7aa1f to 0.0.3. - [Release notes](https://github.com/anchore/stereoscope/releases) - [Changelog](https://github.com/anchore/stereoscope/blob/main/.goreleaser.yaml) - [Commits](https://github.com/anchore/stereoscope/commits/v0.0.3) --- updated-dependencies: - dependency-name: github.com/anchore/stereoscope dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d1173d9c1..da6e60c3d 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f - github.com/anchore/stereoscope v0.0.3-0.20240725180315-50ce3be7aa1f + github.com/anchore/stereoscope v0.0.3 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // we are hinting brotli to latest due to warning when installing archiver v3: // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption diff --git a/go.sum b/go.sum index eda4db73c..6cbac3fc7 100644 --- a/go.sum +++ b/go.sum @@ -113,8 +113,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f h1:B/E9ixKNCasntpoch61NDaQyGPDXLEJlL+B9B/PbdbA= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.3-0.20240725180315-50ce3be7aa1f h1:xuBvotcht1Ns8IdaC4UuYV1U8MFln9c5ELeo5bzDEO8= -github.com/anchore/stereoscope v0.0.3-0.20240725180315-50ce3be7aa1f/go.mod h1:DcQdMes8SwpFli3rDH0v+Vd9qU9Jariq7JSHNJV5X/A= +github.com/anchore/stereoscope v0.0.3 h1:JRPHySy8S6P+Ff3IDiQ29ap1i8/laUQxDk9K1eFh/2U= +github.com/anchore/stereoscope v0.0.3/go.mod h1:5DJheGPjVRsSqegTB24Zi6SCHnYQnA519yeIG+RG+I4= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= From 78d48b420967b23665510d5f86610c64bfdadc82 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 13:51:57 -0400 Subject: [PATCH 156/284] chore(deps): bump github.com/charmbracelet/lipgloss (#3147) Bumps [github.com/charmbracelet/lipgloss](https://github.com/charmbracelet/lipgloss) from 0.12.1 to 0.13.0. - [Release notes](https://github.com/charmbracelet/lipgloss/releases) - [Changelog](https://github.com/charmbracelet/lipgloss/blob/master/.goreleaser.yml) - [Commits](https://github.com/charmbracelet/lipgloss/compare/v0.12.1...v0.13.0) --- updated-dependencies: - dependency-name: github.com/charmbracelet/lipgloss dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index da6e60c3d..a0ff4faab 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/bmatcuk/doublestar/v4 v4.6.1 github.com/charmbracelet/bubbles v0.18.0 github.com/charmbracelet/bubbletea v0.27.0 - github.com/charmbracelet/lipgloss v0.12.1 + github.com/charmbracelet/lipgloss v0.13.0 github.com/dave/jennifer v1.7.0 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da github.com/distribution/reference v0.6.0 diff --git a/go.sum b/go.sum index 6cbac3fc7..912862b5a 100644 --- a/go.sum +++ b/go.sum @@ -161,8 +161,8 @@ github.com/charmbracelet/bubbletea v0.27.0 h1:Mznj+vvYuYagD9Pn2mY7fuelGvP0HAXtZY github.com/charmbracelet/bubbletea v0.27.0/go.mod h1:5MdP9XH6MbQkgGhnlxUqCNmBXf9I74KRQ8HIidRxV1Y= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= -github.com/charmbracelet/lipgloss v0.12.1 h1:/gmzszl+pedQpjCOH+wFkZr/N90Snz40J/NR7A0zQcs= -github.com/charmbracelet/lipgloss v0.12.1/go.mod h1:V2CiwIuhx9S1S1ZlADfOj9HmxeMAORuz5izHb0zGbB8= +github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= +github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY= github.com/charmbracelet/x/ansi v0.1.4 h1:IEU3D6+dWwPSgZ6HBH+v6oUuZ/nVawMiWj5831KfiLM= github.com/charmbracelet/x/ansi v0.1.4/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/input v0.1.0 h1:TEsGSfZYQyOtp+STIjyBq6tpRaorH0qpwZUj8DavAhQ= From ac977246c970a93d330cfdd9da9c826a68634420 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 13:52:06 -0400 Subject: [PATCH 157/284] chore(deps): bump github.com/charmbracelet/bubbles from 0.18.0 to 0.19.0 (#3148) Bumps [github.com/charmbracelet/bubbles](https://github.com/charmbracelet/bubbles) from 0.18.0 to 0.19.0. - [Release notes](https://github.com/charmbracelet/bubbles/releases) - [Changelog](https://github.com/charmbracelet/bubbles/blob/master/.goreleaser.yml) - [Commits](https://github.com/charmbracelet/bubbles/compare/v0.18.0...v0.19.0) --- updated-dependencies: - dependency-name: github.com/charmbracelet/bubbles dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 7 +++---- go.sum | 16 ++++++---------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index a0ff4faab..f6d03ab6c 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 github.com/bmatcuk/doublestar/v4 v4.6.1 - github.com/charmbracelet/bubbles v0.18.0 + github.com/charmbracelet/bubbles v0.19.0 github.com/charmbracelet/bubbletea v0.27.0 github.com/charmbracelet/lipgloss v0.13.0 github.com/dave/jennifer v1.7.0 @@ -169,7 +169,7 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect @@ -179,7 +179,6 @@ require ( github.com/moby/sys/signal v0.7.0 // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect - github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/termenv v0.15.2 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect github.com/nwaples/rardecode v1.1.0 // indirect @@ -199,7 +198,7 @@ require ( github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f // indirect + github.com/sahilm/fuzzy v0.1.1 // indirect github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d // indirect github.com/shopspring/decimal v1.2.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect diff --git a/go.sum b/go.sum index 912862b5a..a9c8256cf 100644 --- a/go.sum +++ b/go.sum @@ -155,8 +155,8 @@ github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0= -github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw= +github.com/charmbracelet/bubbles v0.19.0 h1:gKZkKXPP6GlDk6EcfujDK19PCQqRjaJZQ7QRERx1UF0= +github.com/charmbracelet/bubbles v0.19.0/go.mod h1:WILteEqZ+krG5c3ntGEMeG99nCupcuIk7V0/zOP0tOA= github.com/charmbracelet/bubbletea v0.27.0 h1:Mznj+vvYuYagD9Pn2mY7fuelGvP0HAXtZYGgRBCbHvU= github.com/charmbracelet/bubbletea v0.27.0/go.mod h1:5MdP9XH6MbQkgGhnlxUqCNmBXf9I74KRQ8HIidRxV1Y= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= @@ -552,9 +552,8 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75 h1:P8UmIzZMYDR+NGImiFvErt6VWfIRPuGM+vyjiEdkmIw= github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= @@ -603,8 +602,6 @@ github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= -github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= -github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -673,7 +670,6 @@ github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -692,8 +688,8 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= -github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f h1:MvTmaQdww/z0Q4wrYjDSCcZ78NoftLQyHBSLW/Cx79Y= -github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= +github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA= +github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA= github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= From 691f34ce278d530997a3af26ee854da24f35511c Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 13:52:34 -0400 Subject: [PATCH 158/284] chore(deps): update stereoscope to e6d086e8bef5fab4fcfbd60c9a759c4cb229decf (#3152) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: kzantow <3009477+kzantow@users.noreply.github.com> From 6f0230879a385a4708e8431e57a66fd579d07cd2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 13:52:48 -0400 Subject: [PATCH 159/284] chore(deps): bump github/codeql-action from 3.26.3 to 3.26.4 (#3154) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.3 to 3.26.4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/883d8588e56d1753a8a58c1c86e88976f0c23449...f0f3afee809481da311ca3a6ff1ff51d81dbeb24) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 0ef325acd..29d639451 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@883d8588e56d1753a8a58c1c86e88976f0c23449 #v3.26.3 + uses: github/codeql-action/init@f0f3afee809481da311ca3a6ff1ff51d81dbeb24 #v3.26.4 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@883d8588e56d1753a8a58c1c86e88976f0c23449 #v3.26.3 + uses: github/codeql-action/autobuild@f0f3afee809481da311ca3a6ff1ff51d81dbeb24 #v3.26.4 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@883d8588e56d1753a8a58c1c86e88976f0c23449 #v3.26.3 + uses: github/codeql-action/analyze@f0f3afee809481da311ca3a6ff1ff51d81dbeb24 #v3.26.4 From 9ab3de18198f1b86bb2446f983b3d80d7f5b231b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 13:52:58 -0400 Subject: [PATCH 160/284] chore(deps): bump anchore/sbom-action from 0.17.1 to 0.17.2 (#3155) Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.17.1 to 0.17.2. - [Release notes](https://github.com/anchore/sbom-action/releases) - [Commits](https://github.com/anchore/sbom-action/compare/ab9d16d4b419c9d1a02df5213fa0ebe965ca5a57...61119d458adab75f756bc0b9e4bde25725f86a7a) --- updated-dependencies: - dependency-name: anchore/sbom-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index dc79d685f..bf3e7db49 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -148,7 +148,7 @@ jobs: # for updating brew formula in anchore/homebrew-syft GITHUB_BREW_TOKEN: ${{ secrets.ANCHOREOPS_GITHUB_OSS_WRITE_TOKEN }} - - uses: anchore/sbom-action@ab9d16d4b419c9d1a02df5213fa0ebe965ca5a57 #v0.17.1 + - uses: anchore/sbom-action@61119d458adab75f756bc0b9e4bde25725f86a7a #v0.17.2 continue-on-error: true with: artifact-name: sbom.spdx.json From cff9d494df431d8ef15c56f72a494bcd0aacfbd0 Mon Sep 17 00:00:00 2001 From: KrysGor <108719245+KrysGor@users.noreply.github.com> Date: Fri, 23 Aug 2024 20:41:08 +0200 Subject: [PATCH 161/284] feat: detect curl binaries (#3146) --- syft/pkg/cataloger/binary/classifiers.go | 10 ++++++++++ syft/pkg/cataloger/binary/test-fixtures/config.yaml | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index 5f4d3aa66..563a39cfa 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -529,6 +529,16 @@ func DefaultClassifiers() []Classifier { PURL: mustPURL("pkg:generic/wp-cli@version"), CPEs: singleCPE("cpe:2.3:a:wp-cli:wp-cli:*:*:*:*:*:*:*:*"), }, + { + Class: "curl-binary", + FileGlob: "**/curl", + EvidenceMatcher: FileContentsVersionMatcher( + `curl/(?P[0-9]+\.[0-9]+\.[0-9]+)`, + ), + Package: "curl", + PURL: mustPURL("pkg:generic/curl@version"), + CPEs: singleCPE("cpe:2.3:a:curl:curl:*:*:*:*:*:*:*:*"), + }, } } diff --git a/syft/pkg/cataloger/binary/test-fixtures/config.yaml b/syft/pkg/cataloger/binary/test-fixtures/config.yaml index 9ea3c2de7..15273d33d 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/config.yaml +++ b/syft/pkg/cataloger/binary/test-fixtures/config.yaml @@ -577,3 +577,12 @@ from-images: platform: linux/arm64 paths: - /usr/local/openresty/openssl/bin/openssl + + - name: curl + version: 8.9.1 + images: + - ref: curlimages/curl:8.9.1@sha256:8addc281f0ea517409209f76832b6ddc2cabc3264feb1ebbec2a2521ffad24e4 + platform: linux/amd64 + paths: + - /usr/bin/curl + From dad253785e40914ad84589fb5b590dad0cbc3560 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2024 14:42:12 -0400 Subject: [PATCH 162/284] chore(deps): update tools to latest versions (#3144) --- .binny.yaml | 4 ++-- .golangci.yaml | 4 ++-- cmd/syft/internal/commands/attest.go | 3 +-- cmd/syft/internal/commands/convert.go | 1 - cmd/syft/internal/commands/scan.go | 7 +++---- internal/file/zip_read_closer.go | 16 ++++++++++------ internal/task/package_task_factory.go | 2 -- syft/file/cataloger/executable/elf.go | 2 +- .../internal/cyclonedxutil/helpers/component.go | 2 +- .../internal/cyclonedxutil/helpers/licenses.go | 1 - .../cyclonedxutil/helpers/property_encoder.go | 2 +- .../spdxutil/helpers/originator_supplier.go | 2 +- syft/format/syftjson/to_syft_model.go | 2 +- .../fileresolver/container_image_all_layers.go | 3 ++- .../fileresolver/container_image_squash.go | 3 ++- syft/pkg/cataloger/alpine/parse_apk_db.go | 2 +- syft/pkg/cataloger/binary/classifier.go | 1 - .../manager/internal/download_from_image.go | 4 ++-- syft/pkg/cataloger/debian/package.go | 2 -- syft/pkg/cataloger/debian/parse_dpkg_db.go | 2 +- .../internal/pkgtest/test_generic_parser.go | 1 - .../java/graalvm_native_image_cataloger.go | 6 +++--- syft/pkg/cataloger/java/maven_resolver.go | 2 +- syft/pkg/cataloger/php/parse_pecl_serialized.go | 4 ++-- syft/pkg/cataloger/redhat/parse_rpm_archive.go | 4 ++-- syft/pkg/cataloger/redhat/parse_rpm_db.go | 3 ++- syft/pkg/cataloger/rust/package.go | 1 - 27 files changed, 41 insertions(+), 45 deletions(-) diff --git a/.binny.yaml b/.binny.yaml index 686e946ec..2277f197d 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -26,7 +26,7 @@ tools: # used for linting - name: golangci-lint version: - want: v1.60.1 + want: v1.60.3 method: github-release with: repo: golangci/golangci-lint @@ -111,7 +111,7 @@ tools: # used for triggering a release - name: gh version: - want: v2.54.0 + want: v2.55.0 method: github-release with: repo: cli/cli diff --git a/.golangci.yaml b/.golangci.yaml index 50df7cb73..3ea4697ae 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -12,10 +12,10 @@ linters: enable: - asciicheck - bodyclose + - copyloopvar - dogsled - dupl - errcheck - - exportloopref - funlen - gocognit - goconst @@ -30,6 +30,7 @@ linters: - ineffassign - misspell - nakedret + - nolintlint - revive - staticcheck - stylecheck @@ -80,7 +81,6 @@ run: # - lll # without a way to specify per-line exception cases, this is not usable # - maligned # this is an excellent linter, but tricky to optimize and we are not sensitive to memory layout optimizations # - nestif -# - nolintlint # as of go1.19 this conflicts with the behavior of gofmt, which is a deal-breaker (lint-fix will still fail when running lint) # - prealloc # following this rule isn't consistently a good idea, as it sometimes forces unnecessary allocations that result in less idiomatic code # - rowserrcheck # not in a repo with sql, so this is not useful # - scopelint # deprecated diff --git a/cmd/syft/internal/commands/attest.go b/cmd/syft/internal/commands/attest.go index 374945eff..fa3b5ceef 100644 --- a/cmd/syft/internal/commands/attest.go +++ b/cmd/syft/internal/commands/attest.go @@ -93,14 +93,13 @@ func defaultAttestOutputOptions() options.Output { string(spdxtagvalue.ID), }, Outputs: []string{syftjson.ID.String()}, - OutputFile: options.OutputFile{ // nolint:staticcheck + OutputFile: options.OutputFile{ //nolint:staticcheck Enabled: false, // explicitly not allowed }, Format: options.DefaultFormat(), } } -//nolint:funlen func runAttest(ctx context.Context, id clio.Identification, opts *attestOptions, userInput string) error { // TODO: what other validation here besides binary name? if !commandExists(cosignBinName) { diff --git a/cmd/syft/internal/commands/convert.go b/cmd/syft/internal/commands/convert.go index 2a1e67256..510027ce7 100644 --- a/cmd/syft/internal/commands/convert.go +++ b/cmd/syft/internal/commands/convert.go @@ -28,7 +28,6 @@ type ConvertOptions struct { options.UpdateCheck `yaml:",inline" mapstructure:",squash"` } -//nolint:dupl func Convert(app clio.Application) *cobra.Command { id := app.ID() diff --git a/cmd/syft/internal/commands/scan.go b/cmd/syft/internal/commands/scan.go index efec9dd5b..48fcc8c1e 100644 --- a/cmd/syft/internal/commands/scan.go +++ b/cmd/syft/internal/commands/scan.go @@ -80,7 +80,6 @@ func defaultScanOptions() *scanOptions { } } -//nolint:dupl func Scan(app clio.Application) *cobra.Command { id := app.ID() @@ -396,13 +395,13 @@ func getExplanation(expErr task.ErrInvalidExpression) string { if errors.Is(err, task.ErrNamesNotAllowed) { if expErr.Operation == task.SubSelectOperation { - return "However, " + err.Error() + ".\nIt seems like you are intending to add a cataloger in addition to the default set." // nolint:goconst + return "However, " + err.Error() + ".\nIt seems like you are intending to add a cataloger in addition to the default set." } - return "However, " + err.Error() + "." // nolint:goconst + return "However, " + err.Error() + "." } if errors.Is(err, task.ErrTagsNotAllowed) { - return "However, " + err.Error() + ".\nAdding groups of catalogers may result in surprising behavior (create inaccurate SBOMs)." // nolint:goconst + return "However, " + err.Error() + ".\nAdding groups of catalogers may result in surprising behavior (create inaccurate SBOMs)." } if errors.Is(err, task.ErrAllNotAllowed) { diff --git a/internal/file/zip_read_closer.go b/internal/file/zip_read_closer.go index 5722092db..5f82a2127 100644 --- a/internal/file/zip_read_closer.go +++ b/internal/file/zip_read_closer.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "math" "os" ) @@ -52,9 +53,14 @@ func OpenZip(filepath string) (*ZipReadCloser, error) { return nil, fmt.Errorf("unable to seek to beginning of archive: %w", err) } - size := fi.Size() - int64(offset) + if offset > math.MaxInt64 { + return nil, fmt.Errorf("archive start offset too large: %v", offset) + } + offset64 := int64(offset) //nolint:gosec // lint bug, checked above: https://github.com/securego/gosec/issues/1187 + + size := fi.Size() - offset64 - r, err := zip.NewReader(io.NewSectionReader(f, int64(offset), size), size) + r, err := zip.NewReader(io.NewSectionReader(f, offset64, size), size) if err != nil { return nil, fmt.Errorf("unable to open ZipReadCloser @ %q: %w", filepath, err) } @@ -95,8 +101,6 @@ type directoryEnd struct { } // note: this is derived from readDirectoryEnd within the archive/zip package -// -//nolint:gocognit func findArchiveStartOffset(r io.ReaderAt, size int64) (startOfArchive uint64, err error) { // look for directoryEndSignature in the last 1k, then in the last 65k var buf []byte @@ -150,7 +154,7 @@ func findArchiveStartOffset(r io.ReaderAt, size int64) (startOfArchive uint64, e startOfArchive = uint64(directoryEndOffset) - d.directorySize - d.directoryOffset // Make sure directoryOffset points to somewhere in our file. - if o := int64(d.directoryOffset); o < 0 || o >= size { + if d.directoryOffset >= uint64(size) { return 0, zip.ErrFormat } return startOfArchive, nil @@ -179,7 +183,7 @@ func findDirectory64End(r io.ReaderAt, directoryEndOffset int64) (int64, error) if b.uint32() != 1 { // total number of disks return -1, nil // the file is not a valid zip64-file } - return int64(p), nil + return int64(p), nil //nolint:gosec } // readDirectory64End reads the zip64 directory end and updates the diff --git a/internal/task/package_task_factory.go b/internal/task/package_task_factory.go index 0ee59810f..4fdb1121e 100644 --- a/internal/task/package_task_factory.go +++ b/internal/task/package_task_factory.go @@ -81,8 +81,6 @@ func (f PackageTaskFactories) Tasks(cfg CatalogingFactoryConfig) ([]Task, error) } // NewPackageTask creates a Task function for a generic pkg.Cataloger, honoring the common configuration options. -// -//nolint:funlen func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string) Task { fn := func(ctx context.Context, resolver file.Resolver, sbom sbomsync.Builder) error { catalogerName := c.Name() diff --git a/syft/file/cataloger/executable/elf.go b/syft/file/cataloger/executable/elf.go index dec6abd34..9c6ad6151 100644 --- a/syft/file/cataloger/executable/elf.go +++ b/syft/file/cataloger/executable/elf.go @@ -175,7 +175,7 @@ func hasElfDynTag(f *elf.File, tag elf.DynTag) bool { t = elf.DynTag(f.ByteOrder.Uint32(d[0:4])) d = d[8:] case elf.ELFCLASS64: - t = elf.DynTag(f.ByteOrder.Uint64(d[0:8])) + t = elf.DynTag(f.ByteOrder.Uint64(d[0:8])) //nolint:gosec d = d[16:] } if t == tag { diff --git a/syft/format/internal/cyclonedxutil/helpers/component.go b/syft/format/internal/cyclonedxutil/helpers/component.go index fa6dd75fa..526094ac5 100644 --- a/syft/format/internal/cyclonedxutil/helpers/component.go +++ b/syft/format/internal/cyclonedxutil/helpers/component.go @@ -124,7 +124,7 @@ func decodePackageMetadata(vals map[string]string, c *cyclonedx.Component, typeN if metadataType == nil { return nil } - metaPtrTyp := reflect.PtrTo(metadataType) + metaPtrTyp := reflect.PointerTo(metadataType) metaPtr := Decode(metaPtrTyp, vals, "syft:metadata", CycloneDXFields) // Map all explicit metadata properties diff --git a/syft/format/internal/cyclonedxutil/helpers/licenses.go b/syft/format/internal/cyclonedxutil/helpers/licenses.go index fb63b6510..a092d3abd 100644 --- a/syft/format/internal/cyclonedxutil/helpers/licenses.go +++ b/syft/format/internal/cyclonedxutil/helpers/licenses.go @@ -72,7 +72,6 @@ func decodeLicenses(c *cyclonedx.Component) []pkg.License { return licenses } -// nolint:funlen func separateLicenses(p pkg.Package) (spdx, other cyclonedx.Licenses, expressions []string) { ex := make([]string, 0) spdxc := cyclonedx.Licenses{} diff --git a/syft/format/internal/cyclonedxutil/helpers/property_encoder.go b/syft/format/internal/cyclonedxutil/helpers/property_encoder.go index fb9a201d1..79d614e35 100644 --- a/syft/format/internal/cyclonedxutil/helpers/property_encoder.go +++ b/syft/format/internal/cyclonedxutil/helpers/property_encoder.go @@ -165,7 +165,7 @@ func Decode(typ reflect.Type, values map[string]string, prefix string, fn FieldN isSlice := false if typ.Kind() == reflect.Slice { - typ = reflect.PtrTo(typ) + typ = reflect.PointerTo(typ) isSlice = true } diff --git a/syft/format/internal/spdxutil/helpers/originator_supplier.go b/syft/format/internal/spdxutil/helpers/originator_supplier.go index d2af96971..478cef377 100644 --- a/syft/format/internal/spdxutil/helpers/originator_supplier.go +++ b/syft/format/internal/spdxutil/helpers/originator_supplier.go @@ -34,7 +34,7 @@ const ( // // Available options are: , NOASSERTION, Person: , Organization: // return values are: , -func Originator(p pkg.Package) (typ string, author string) { // nolint: funlen +func Originator(p pkg.Package) (typ string, author string) { //nolint: funlen if !hasMetadata(p) { return typ, author } diff --git a/syft/format/syftjson/to_syft_model.go b/syft/format/syftjson/to_syft_model.go index b2b1916e2..289e91fda 100644 --- a/syft/format/syftjson/to_syft_model.go +++ b/syft/format/syftjson/to_syft_model.go @@ -146,7 +146,7 @@ func safeFileModeConvert(val int) (fs.FileMode, error) { if err != nil { return 0, err } - return os.FileMode(mode), nil + return os.FileMode(mode), nil //nolint:gosec } func toSyftLicenses(m []model.License) (p []pkg.License) { diff --git a/syft/internal/fileresolver/container_image_all_layers.go b/syft/internal/fileresolver/container_image_all_layers.go index c1120956b..4bad1ef1b 100644 --- a/syft/internal/fileresolver/container_image_all_layers.go +++ b/syft/internal/fileresolver/container_image_all_layers.go @@ -120,7 +120,8 @@ func (r *ContainerImageAllLayers) FilesByPath(paths ...string) ([]file.Location, } // FilesByGlob returns all file.References that match the given path glob pattern from any layer in the image. -// nolint:gocognit +// +//nolint:gocognit func (r *ContainerImageAllLayers) FilesByGlob(patterns ...string) ([]file.Location, error) { uniqueFileIDs := stereoscopeFile.NewFileReferenceSet() uniqueLocations := make([]file.Location, 0) diff --git a/syft/internal/fileresolver/container_image_squash.go b/syft/internal/fileresolver/container_image_squash.go index b3a5ded89..d3593c969 100644 --- a/syft/internal/fileresolver/container_image_squash.go +++ b/syft/internal/fileresolver/container_image_squash.go @@ -79,7 +79,8 @@ func (r *ContainerImageSquash) FilesByPath(paths ...string) ([]file.Location, er } // FilesByGlob returns all file.References that match the given path glob pattern within the squashed representation of the image. -// nolint:gocognit +// +//nolint:gocognit func (r *ContainerImageSquash) FilesByGlob(patterns ...string) ([]file.Location, error) { uniqueFileIDs := stereoscopeFile.NewFileReferenceSet() uniqueLocations := make([]file.Location, 0) diff --git a/syft/pkg/cataloger/alpine/parse_apk_db.go b/syft/pkg/cataloger/alpine/parse_apk_db.go index 5948e3035..227d93bcb 100644 --- a/syft/pkg/cataloger/alpine/parse_apk_db.go +++ b/syft/pkg/cataloger/alpine/parse_apk_db.go @@ -34,7 +34,7 @@ type parsedData struct { // parseApkDB parses packages from a given APK "installed" flat-file DB. For more // information on specific fields, see https://wiki.alpinelinux.org/wiki/Apk_spec. // -//nolint:funlen,gocognit +//nolint:funlen func parseApkDB(_ context.Context, resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { scanner := bufio.NewScanner(reader) diff --git a/syft/pkg/cataloger/binary/classifier.go b/syft/pkg/cataloger/binary/classifier.go index 196306793..998242b66 100644 --- a/syft/pkg/cataloger/binary/classifier.go +++ b/syft/pkg/cataloger/binary/classifier.go @@ -196,7 +196,6 @@ func matchExcluding(matcher EvidenceMatcher, contentPatternsToExclude ...string) } } -//nolint:gocognit func sharedLibraryLookup(sharedLibraryPattern string, sharedLibraryMatcher EvidenceMatcher) EvidenceMatcher { pat := regexp.MustCompile(sharedLibraryPattern) return func(classifier Classifier, context matcherContext) (packages []pkg.Package, _ error) { diff --git a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/download_from_image.go b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/download_from_image.go index 49fa70286..32b9c83d6 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/download_from_image.go +++ b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/download_from_image.go @@ -157,7 +157,7 @@ func copyBinariesFromDockerImage(config config.BinaryFromImage, destination stri defer func() { cmd := exec.Command("docker", "rm", containerName) - cmd.Run() // nolint:errcheck + cmd.Run() //nolint:errcheck }() for i, destinationPath := range config.AllStorePathsForImage(image, destination) { @@ -182,7 +182,7 @@ func copyBinaryFromContainer(containerName, containerPath, destinationPath, fing return err } - cmd := exec.Command("docker", "cp", fmt.Sprintf("%s:%s", containerName, containerPath), destinationPath) // nolint:gosec + cmd := exec.Command("docker", "cp", fmt.Sprintf("%s:%s", containerName, containerPath), destinationPath) //nolint:gosec // reason for gosec exception: this is for processing test fixtures only, not used in production if err := cmd.Run(); err != nil { return err diff --git a/syft/pkg/cataloger/debian/package.go b/syft/pkg/cataloger/debian/package.go index bc0db7bcf..d31830e87 100644 --- a/syft/pkg/cataloger/debian/package.go +++ b/syft/pkg/cataloger/debian/package.go @@ -169,7 +169,6 @@ func getAdditionalFileListing(resolver file.Resolver, dbLocation file.Location, return files, locations } -//nolint:dupl func fetchMd5Contents(resolver file.Resolver, dbLocation file.Location, m pkg.DpkgDBEntry) (io.ReadCloser, *file.Location) { var md5Reader io.ReadCloser var err error @@ -213,7 +212,6 @@ func fetchMd5Contents(resolver file.Resolver, dbLocation file.Location, m pkg.Dp return md5Reader, &l } -//nolint:dupl func fetchConffileContents(resolver file.Resolver, dbLocation file.Location, m pkg.DpkgDBEntry) (io.ReadCloser, *file.Location) { var reader io.ReadCloser var err error diff --git a/syft/pkg/cataloger/debian/parse_dpkg_db.go b/syft/pkg/cataloger/debian/parse_dpkg_db.go index 077e5bef9..87428d608 100644 --- a/syft/pkg/cataloger/debian/parse_dpkg_db.go +++ b/syft/pkg/cataloger/debian/parse_dpkg_db.go @@ -230,7 +230,7 @@ func handleNewKeyValue(line string) (key string, val interface{}, err error) { if err != nil { return "", nil, fmt.Errorf("bad installed-size value=%q: %w", val, err) } - return key, int(s), nil + return key, int(s), nil //nolint:gosec default: return key, val, nil } diff --git a/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go b/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go index 2dcbb7f8b..ae26bb6d1 100644 --- a/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go +++ b/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go @@ -264,7 +264,6 @@ func (p *CatalogTester) TestCataloger(t *testing.T, cataloger pkg.Cataloger) { } } -// nolint:funlen func (p *CatalogTester) assertPkgs(t *testing.T, pkgs []pkg.Package, relationships []artifact.Relationship) { t.Helper() diff --git a/syft/pkg/cataloger/java/graalvm_native_image_cataloger.go b/syft/pkg/cataloger/java/graalvm_native_image_cataloger.go index add09a458..5dd74a654 100644 --- a/syft/pkg/cataloger/java/graalvm_native_image_cataloger.go +++ b/syft/pkg/cataloger/java/graalvm_native_image_cataloger.go @@ -268,7 +268,7 @@ func newPE(filename string, r io.ReaderAt) (nativeImage, error) { } exportSymbolsOffset := uint64(exportSymbolsDataDirectory.VirtualAddress) exports := make([]byte, exportSymbolsDataDirectory.Size) - _, err = r.ReadAt(exports, int64(exportSymbolsOffset)) + _, err = r.ReadAt(exports, int64(exportSymbolsOffset)) //nolint:gosec if err != nil { return fileError(filename, fmt.Errorf("could not read the exported symbols data directory: %w", err)) } @@ -412,7 +412,7 @@ func (ni nativeImagePE) fetchExportAttribute(i int) (uint32, error) { func (ni nativeImagePE) fetchExportFunctionPointer(functionsBase uint32, i uint32) (uint32, error) { var pointer uint32 - n := uint32(len(ni.exports)) + n := uint32(len(ni.exports)) //nolint:gosec sz := uint32(unsafe.Sizeof(ni.t.functionPointer)) j := functionsBase + i*sz if j+sz >= n { @@ -457,7 +457,7 @@ func (ni nativeImagePE) fetchSbomSymbols(content *exportContentPE) { sbomBytes := []byte(nativeImageSbomSymbol + "\x00") sbomLengthBytes := []byte(nativeImageSbomLengthSymbol + "\x00") svmVersionInfoBytes := []byte(nativeImageSbomVersionSymbol + "\x00") - n := uint32(len(ni.exports)) + n := uint32(len(ni.exports)) //nolint:gosec // Find SBOM, SBOM Length, and SVM Version Symbol for i := uint32(0); i < content.numberOfNames; i++ { diff --git a/syft/pkg/cataloger/java/maven_resolver.go b/syft/pkg/cataloger/java/maven_resolver.go index 5fddccc31..e7e73b0be 100644 --- a/syft/pkg/cataloger/java/maven_resolver.go +++ b/syft/pkg/cataloger/java/maven_resolver.go @@ -342,7 +342,7 @@ func (r *mavenResolver) findPomInRemoteRepository(ctx context.Context, groupID, Timeout: r.remoteRequestTimeout, } - resp, err := client.Do(req) //nolint:bodyclose + resp, err := client.Do(req) if err != nil { return nil, fmt.Errorf("unable to get pom from Maven repository %v: %w", requestURL, err) } diff --git a/syft/pkg/cataloger/php/parse_pecl_serialized.go b/syft/pkg/cataloger/php/parse_pecl_serialized.go index 7f48f2096..84c5c4c3b 100644 --- a/syft/pkg/cataloger/php/parse_pecl_serialized.go +++ b/syft/pkg/cataloger/php/parse_pecl_serialized.go @@ -60,10 +60,10 @@ func readStruct(metadata any, fields ...string) string { if len(fields) > 0 { value, ok := metadata.(map[any]any) if !ok { - log.Tracef("unable to read '%s' from: %v", fields[0], metadata) + log.Tracef("unable to read '%s' from: %v", fields[0], metadata) //nolint:gosec return "" } - return readStruct(value[fields[0]], fields[1:]...) + return readStruct(value[fields[0]], fields[1:]...) //nolint:gosec } value, ok := metadata.(string) if !ok { diff --git a/syft/pkg/cataloger/redhat/parse_rpm_archive.go b/syft/pkg/cataloger/redhat/parse_rpm_archive.go index 8c4b395a7..e7d4b2287 100644 --- a/syft/pkg/cataloger/redhat/parse_rpm_archive.go +++ b/syft/pkg/cataloger/redhat/parse_rpm_archive.go @@ -88,12 +88,12 @@ func mapFiles(files []rpmutils.FileInfo, digestAlgorithm string) []pkg.RpmFileRe } out = append(out, pkg.RpmFileRecord{ Path: f.Name(), - Mode: pkg.RpmFileMode(f.Mode()), + Mode: pkg.RpmFileMode(f.Mode()), //nolint:gosec Size: int(f.Size()), Digest: digest, UserName: f.UserName(), GroupName: f.GroupName(), - Flags: rpmdb.FileFlags(f.Flags()).String(), + Flags: rpmdb.FileFlags(f.Flags()).String(), //nolint:gosec }) } return out diff --git a/syft/pkg/cataloger/redhat/parse_rpm_db.go b/syft/pkg/cataloger/redhat/parse_rpm_db.go index d29542137..23c5dd487 100644 --- a/syft/pkg/cataloger/redhat/parse_rpm_db.go +++ b/syft/pkg/cataloger/redhat/parse_rpm_db.go @@ -17,7 +17,8 @@ import ( ) // parseRpmDb parses an "Packages" RPM DB and returns the Packages listed within it. -// nolint:funlen +// +//nolint:funlen func parseRpmDB(_ context.Context, resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { f, err := os.CreateTemp("", "rpmdb") if err != nil { diff --git a/syft/pkg/cataloger/rust/package.go b/syft/pkg/cataloger/rust/package.go index 93d1eeaee..be67d96a9 100644 --- a/syft/pkg/cataloger/rust/package.go +++ b/syft/pkg/cataloger/rust/package.go @@ -29,7 +29,6 @@ func newPackagesFromAudit(location file.Location, versionInfo rustaudit.VersionI var pkgs []pkg.Package for _, dep := range versionInfo.Packages { - dep := dep p := newPackageFromAudit(&dep, location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)) if pkg.IsValid(&p) && dep.Kind == rustaudit.Runtime { pkgs = append(pkgs, p) From b6b5c8e3084327f118abdd4c7d3b41e8fe9efec7 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Mon, 26 Aug 2024 08:44:39 -0400 Subject: [PATCH 163/284] fix ELF package correlations (#3151) --- .../binary/binary_dependencies.go | 5 ++-- .../binary/binary_dependencies_test.go | 30 ++++++++++++++++--- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/internal/relationship/binary/binary_dependencies.go b/internal/relationship/binary/binary_dependencies.go index b23b42b9a..210f88114 100644 --- a/internal/relationship/binary/binary_dependencies.go +++ b/internal/relationship/binary/binary_dependencies.go @@ -36,8 +36,7 @@ func generateRelationships(resolver file.Resolver, accessor sbomsync.Accessor, i newRelationships.Add(r) } } - - for _, parentPkg := range s.Artifacts.Packages.Sorted(pkg.BinaryPkg) { + for _, parentPkg := range allElfPackages(s) { for _, evidentLocation := range parentPkg.Locations.ToSlice() { if evidentLocation.Annotations[pkg.EvidenceAnnotationKey] != pkg.PrimaryEvidenceAnnotation { continue @@ -101,7 +100,7 @@ func onlyPrimaryEvidenceLocations(p pkg.Package) []file.Location { func allElfPackages(s *sbom.SBOM) []pkg.Package { var elfPkgs []pkg.Package - for _, p := range s.Artifacts.Packages.Sorted(pkg.BinaryPkg) { + for _, p := range s.Artifacts.Packages.Sorted() { if !isElfPackage(p) { continue } diff --git a/internal/relationship/binary/binary_dependencies_test.go b/internal/relationship/binary/binary_dependencies_test.go index 33c6436c3..ea524fa1f 100644 --- a/internal/relationship/binary/binary_dependencies_test.go +++ b/internal/relationship/binary/binary_dependencies_test.go @@ -50,6 +50,22 @@ func TestPackagesToRemove(t *testing.T) { } glibCBinaryELFPackage.SetID() + glibCBinaryELFPackageAsRPM := pkg.Package{ + Name: "glibc", + Locations: file.NewLocationSet( + file.NewLocation(glibcCoordinate.RealPath).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + Type: pkg.RpmPkg, // note: the elf package claims it is a RPM, not binary + Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ + Type: "rpm", + Vendor: "syft", + System: "syftsys", + SourceRepo: "https://github.com/someone/somewhere.git", + Commit: "5534c38d0ffef9a3f83154f0b7a7fb6ab0ab6dbb", + }, + } + glibCBinaryELFPackageAsRPM.SetID() + glibCBinaryClassifierPackage := pkg.Package{ Name: "glibc", Locations: file.NewLocationSet( @@ -83,9 +99,15 @@ func TestPackagesToRemove(t *testing.T) { want: []artifact.ID{glibCBinaryELFPackage.ID()}, }, { - name: "remove no packages when there is a single binary package", + name: "keep packages that are overlapping rpm --> binary when the binary self identifies as an RPM", resolver: file.NewMockResolverForPaths(glibcCoordinate.RealPath), - accessor: newAccessor([]pkg.Package{glibCBinaryELFPackage}, map[file.Coordinates]file.Executable{}, nil), + accessor: newAccessor([]pkg.Package{glibCPackage, glibCBinaryELFPackageAsRPM}, map[file.Coordinates]file.Executable{}, nil), + want: []artifact.ID{}, + }, + { + name: "remove no packages when there is a single binary package (or self identifying RPM)", + resolver: file.NewMockResolverForPaths(glibcCoordinate.RealPath), + accessor: newAccessor([]pkg.Package{glibCBinaryELFPackage, glibCBinaryELFPackageAsRPM}, map[file.Coordinates]file.Executable{}, nil), want: []artifact.ID{}, }, { @@ -173,9 +195,9 @@ func TestNewDependencyRelationships(t *testing.T) { file.NewLocation(parallelLibCoordinate.RealPath).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation), ), Language: "", - Type: pkg.BinaryPkg, + Type: pkg.RpmPkg, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ - Type: "testfixture", + Type: "rpm", Vendor: "syft", System: "syftsys", SourceRepo: "https://github.com/someone/somewhere.git", From 6549ec9831ac3fd5ca23b615c54cab5201ead180 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 10:07:18 -0400 Subject: [PATCH 164/284] chore(deps): bump github/codeql-action from 3.26.4 to 3.26.5 (#3162) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.4 to 3.26.5. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/f0f3afee809481da311ca3a6ff1ff51d81dbeb24...2c779ab0d087cd7fe7b826087247c2c81f27bfa6) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 29d639451..768415473 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f0f3afee809481da311ca3a6ff1ff51d81dbeb24 #v3.26.4 + uses: github/codeql-action/init@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 #v3.26.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@f0f3afee809481da311ca3a6ff1ff51d81dbeb24 #v3.26.4 + uses: github/codeql-action/autobuild@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 #v3.26.5 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f0f3afee809481da311ca3a6ff1ff51d81dbeb24 #v3.26.4 + uses: github/codeql-action/analyze@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 #v3.26.5 From 0cd618571633ebb5887ae3cd8ada045bcaae7722 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 10:07:44 -0400 Subject: [PATCH 165/284] chore(deps): update CPE dictionary index (#3161) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: wagoodman <590471+wagoodman@users.noreply.github.com> --- .../internal/cpegenerate/dictionary/data/cpe-index.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index 8fd77ee19..20dee5938 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -6075,6 +6075,9 @@ "ftpd": [ "cpe:2.3:a:ftpd_project:ftpd:*:*:*:*:*:ruby:*:*" ], + "fugit": [ + "cpe:2.3:a:floraison:fugit:*:*:*:*:*:ruby:*:*" + ], "geminabox": [ "cpe:2.3:a:geminabox_project:geminabox:*:*:*:*:*:ruby:*:*" ], @@ -7970,7 +7973,10 @@ "cpe:2.3:a:bcorp_shortcodes_project:bcorp_shortcodes:*:*:*:*:*:wordpress:*:*" ], "bdthemes-element-pack-lite": [ - "cpe:2.3:a:bdthemes:element_pack_elementor_addons:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:bdthemes:element_pack:*:*:*:*:lite:wordpress:*:*" + ], + "bdthemes-element-pack-lite#tags": [ + "cpe:2.3:a:bdthemes:element_pack:*:*:*:*:lite:wordpress:*:*" ], "bdvs-password-reset": [ "cpe:2.3:a:bedevious:password_reset_with_code_for_wordpress_rest_api:*:*:*:*:*:wordpress:*:*" From cf9bb13f2bfeb737ca89be67e1b44fdab4adb2d1 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 10:07:59 -0400 Subject: [PATCH 166/284] chore(deps): update tools to latest versions (#3160) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index 2277f197d..a9a374393 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -34,7 +34,7 @@ tools: # used for showing the changelog at release - name: glow version: - want: v1.5.1 + want: v2.0.0 method: github-release with: repo: charmbracelet/glow From 99be365f625fc49f2c4f9b7a4dbbb56af5d71b6e Mon Sep 17 00:00:00 2001 From: Weston Steimel Date: Tue, 27 Aug 2024 14:03:19 +0100 Subject: [PATCH 167/284] fix: use official CPE for curl binary cataloger (#3164) The official CPE for curl is `cpe:2.3:a:haxx:curl:*:*:*:*:*:*:*:*` Signed-off-by: Weston Steimel --- syft/pkg/cataloger/binary/classifiers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index 563a39cfa..b9df7aa46 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -537,7 +537,7 @@ func DefaultClassifiers() []Classifier { ), Package: "curl", PURL: mustPURL("pkg:generic/curl@version"), - CPEs: singleCPE("cpe:2.3:a:curl:curl:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:haxx:curl:*:*:*:*:*:*:*:*"), }, } } From 4ee6c179f8002158cbddb64fee484a9a8f606ddc Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Tue, 27 Aug 2024 09:23:43 -0400 Subject: [PATCH 168/284] set cataloger names within package cataloger task (#3165) Signed-off-by: Alex Goodman --- internal/task/package_task_factory.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/internal/task/package_task_factory.go b/internal/task/package_task_factory.go index 4fdb1121e..d220a2bea 100644 --- a/internal/task/package_task_factory.go +++ b/internal/task/package_task_factory.go @@ -81,7 +81,7 @@ func (f PackageTaskFactories) Tasks(cfg CatalogingFactoryConfig) ([]Task, error) } // NewPackageTask creates a Task function for a generic pkg.Cataloger, honoring the common configuration options. -func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string) Task { +func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string) Task { //nolint: funlen fn := func(ctx context.Context, resolver file.Resolver, sbom sbomsync.Builder) error { catalogerName := c.Name() log.WithFields("name", catalogerName).Trace("starting package cataloger") @@ -100,12 +100,15 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string pkgs, relationships, err := c.Catalog(ctx, resolver) if err != nil { - return fmt.Errorf("unable to catalog packages with %q: %w", c.Name(), err) + return fmt.Errorf("unable to catalog packages with %q: %w", catalogerName, err) } - log.WithFields("cataloger", c.Name()).Debugf("discovered %d packages", len(pkgs)) + log.WithFields("cataloger", catalogerName).Debugf("discovered %d packages", len(pkgs)) for i, p := range pkgs { + if p.FoundBy == "" { + p.FoundBy = catalogerName + } if cfg.DataGenerationConfig.GenerateCPEs { // generate CPEs (note: this is excluded from package ID, so is safe to mutate) // we might have binary classified CPE already with the package so we want to append here @@ -143,7 +146,7 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string t.Add(int64(len(pkgs))) t.SetCompleted() - log.WithFields("name", c.Name()).Trace("package cataloger completed") + log.WithFields("name", catalogerName).Trace("package cataloger completed") return nil } From e9a8c27be123d03561a54f2755822c0bf872c35d Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Tue, 27 Aug 2024 10:26:35 -0400 Subject: [PATCH 169/284] respond to authoratative CPEs from catalogers (#3166) Signed-off-by: Alex Goodman --- internal/task/package_task_factory.go | 19 ++++++-- internal/task/package_task_factory_test.go | 55 ++++++++++++++++++++++ syft/pkg/cataloger/binary/classifier.go | 8 +++- syft/pkg/cataloger/binary/classifiers.go | 2 +- 4 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 internal/task/package_task_factory_test.go diff --git a/internal/task/package_task_factory.go b/internal/task/package_task_factory.go index d220a2bea..8a31c0483 100644 --- a/internal/task/package_task_factory.go +++ b/internal/task/package_task_factory.go @@ -15,10 +15,11 @@ import ( "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/cataloging" "github.com/anchore/syft/syft/cataloging/pkgcataloging" + "github.com/anchore/syft/syft/cpe" "github.com/anchore/syft/syft/event/monitor" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" - "github.com/anchore/syft/syft/pkg/cataloger/common/cpe" + cpeutils "github.com/anchore/syft/syft/pkg/cataloger/common/cpe" ) type packageTaskFactory func(cfg CatalogingFactoryConfig) Task @@ -109,15 +110,16 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string if p.FoundBy == "" { p.FoundBy = catalogerName } - if cfg.DataGenerationConfig.GenerateCPEs { + + if cfg.DataGenerationConfig.GenerateCPEs && !hasAuthoritativeCPE(p.CPEs) { // generate CPEs (note: this is excluded from package ID, so is safe to mutate) // we might have binary classified CPE already with the package so we want to append here - dictionaryCPEs, ok := cpe.DictionaryFind(p) + dictionaryCPEs, ok := cpeutils.DictionaryFind(p) if ok { log.Tracef("used CPE dictionary to find CPEs for %s package %q: %s", p.Type, p.Name, dictionaryCPEs) p.CPEs = append(p.CPEs, dictionaryCPEs...) } else { - p.CPEs = append(p.CPEs, cpe.Generate(p)...) + p.CPEs = append(p.CPEs, cpeutils.Generate(p)...) } } @@ -155,6 +157,15 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string return NewTask(c.Name(), fn, tags...) } +func hasAuthoritativeCPE(cpes []cpe.CPE) bool { + for _, c := range cpes { + if c.Source != cpe.GeneratedSource { + return true + } + } + return false +} + func prettyName(s string) string { if s == "" { return "" diff --git a/internal/task/package_task_factory_test.go b/internal/task/package_task_factory_test.go new file mode 100644 index 000000000..2876afb56 --- /dev/null +++ b/internal/task/package_task_factory_test.go @@ -0,0 +1,55 @@ +package task + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/anchore/syft/syft/cpe" +) + +func Test_hasAuthoritativeCPE(t *testing.T) { + tests := []struct { + name string + cpes []cpe.CPE + want bool + }{ + { + name: "no cpes", + cpes: []cpe.CPE{}, + want: false, + }, + { + name: "no authoritative cpes", + cpes: []cpe.CPE{ + { + Source: cpe.GeneratedSource, + }, + }, + want: false, + }, + { + name: "has declared (authoritative) cpe", + cpes: []cpe.CPE{ + { + Source: cpe.DeclaredSource, + }, + }, + want: true, + }, + { + name: "has lookup (authoritative) cpe", + cpes: []cpe.CPE{ + { + Source: cpe.NVDDictionaryLookupSource, + }, + }, + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.want, hasAuthoritativeCPE(tt.cpes)) + }) + } +} diff --git a/syft/pkg/cataloger/binary/classifier.go b/syft/pkg/cataloger/binary/classifier.go index 998242b66..490df82b3 100644 --- a/syft/pkg/cataloger/binary/classifier.go +++ b/syft/pkg/cataloger/binary/classifier.go @@ -274,9 +274,13 @@ func getContents(context matcherContext) ([]byte, error) { // singleCPE returns a []cpe.CPE with Source: Generated based on the cpe string or panics if the // cpe string cannot be parsed into valid CPE Attributes -func singleCPE(cpeString string) []cpe.CPE { +func singleCPE(cpeString string, source ...cpe.Source) []cpe.CPE { + src := cpe.GeneratedSource + if len(source) > 0 { + src = source[0] + } return []cpe.CPE{ - cpe.Must(cpeString, cpe.GeneratedSource), + cpe.Must(cpeString, src), } } diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index b9df7aa46..b8ecc991f 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -537,7 +537,7 @@ func DefaultClassifiers() []Classifier { ), Package: "curl", PURL: mustPURL("pkg:generic/curl@version"), - CPEs: singleCPE("cpe:2.3:a:haxx:curl:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:haxx:curl:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, } } From 5ab43bafecb2fddd698c5c3c9aef315b47515d5f Mon Sep 17 00:00:00 2001 From: Weston Steimel Date: Tue, 27 Aug 2024 17:36:34 +0100 Subject: [PATCH 170/284] fix: improve known CPEs and set NVD as source for all current binary classifiers (#3167) Signed-off-by: Weston Steimel --- syft/pkg/cataloger/binary/classifiers.go | 103 ++++++++++++----------- 1 file changed, 54 insertions(+), 49 deletions(-) diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index b8ecc991f..24c514c7e 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -23,8 +23,8 @@ func DefaultClassifiers() []Classifier { Package: "python", PURL: mustPURL("pkg:generic/python@version"), CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:python_software_foundation:python:*:*:*:*:*:*:*:*", cpe.GeneratedSource), - cpe.Must("cpe:2.3:a:python:python:*:*:*:*:*:*:*:*", cpe.GeneratedSource), + cpe.Must("cpe:2.3:a:python_software_foundation:python:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + cpe.Must("cpe:2.3:a:python:python:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, }, { @@ -34,8 +34,8 @@ func DefaultClassifiers() []Classifier { Package: "python", PURL: mustPURL("pkg:generic/python@version"), CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:python_software_foundation:python:*:*:*:*:*:*:*:*", cpe.GeneratedSource), - cpe.Must("cpe:2.3:a:python:python:*:*:*:*:*:*:*:*", cpe.GeneratedSource), + cpe.Must("cpe:2.3:a:python_software_foundation:python:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + cpe.Must("cpe:2.3:a:python:python:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, }, { @@ -53,7 +53,7 @@ func DefaultClassifiers() []Classifier { `(?m)go(?P[0-9]+\.[0-9]+(\.[0-9]+|beta[0-9]+|alpha[0-9]+|rc[0-9]+)?)\x00`), Package: "go", PURL: mustPURL("pkg:generic/go@version"), - CPEs: singleCPE("cpe:2.3:a:golang:go:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:golang:go:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "julia-binary", @@ -62,7 +62,7 @@ func DefaultClassifiers() []Classifier { `(?m)__init__\x00(?P[0-9]+\.[0-9]+\.[0-9]+)\x00verify`), Package: "julia", PURL: mustPURL("pkg:generic/julia@version"), - CPEs: singleCPE("cpe:2.3:a:julialang:julia:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:julialang:julia:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "helm", @@ -71,7 +71,7 @@ func DefaultClassifiers() []Classifier { `(?m)\x00v(?P[0-9]+\.[0-9]+\.[0-9]+)\x00`), Package: "helm", PURL: mustPURL("pkg:golang/helm.sh/helm@version"), - CPEs: singleCPE("cpe:2.3:a:helm:helm:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:helm:helm:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "redis-binary", @@ -82,7 +82,10 @@ func DefaultClassifiers() []Classifier { ), Package: "redis", PURL: mustPURL("pkg:generic/redis@version"), - CPEs: singleCPE("cpe:2.3:a:redislabs:redis:*:*:*:*:*:*:*:*"), + CPEs: []cpe.CPE{ + cpe.Must("cpe:2.3:a:redislabs:redis:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + cpe.Must("cpe:2.3:a:redis:redis:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, }, { Class: "java-binary-openjdk", @@ -103,7 +106,7 @@ func DefaultClassifiers() []Classifier { Package: "java/jre", PURL: mustPURL("pkg:generic/java/jre@version"), // TODO the updates might need to be part of the CPE Attributes, like: 1.8.0:update152 - CPEs: singleCPE("cpe:2.3:a:oracle:openjdk:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:oracle:openjdk:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "java-binary-ibm", @@ -113,7 +116,7 @@ func DefaultClassifiers() []Classifier { `(?m)\x00java\x00(?P[0-9]+[.0-9]+)\x00{4}(?P[0-9]+[-._a-zA-Z0-9]+)\x00`), Package: "java/jre", PURL: mustPURL("pkg:generic/java/jre@version"), - CPEs: singleCPE("cpe:2.3:a:ibm:java:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:ibm:java:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "java-binary-oracle", @@ -127,7 +130,7 @@ func DefaultClassifiers() []Classifier { ), Package: "java/jre", PURL: mustPURL("pkg:generic/java/jre@version"), - CPEs: singleCPE("cpe:2.3:a:oracle:jre:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:oracle:jre:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "java-binary-graalvm", @@ -136,7 +139,7 @@ func DefaultClassifiers() []Classifier { `(?m)\x00(?P[0-9]+[.0-9]+[.0-9]+\+[0-9]+-jvmci-[0-9]+[.0-9]+-b[0-9]+)\x00`), Package: "java/graalvm", PURL: mustPURL("pkg:generic/java/graalvm@version"), - CPEs: singleCPE("cpe:2.3:a:oracle:graalvm:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:oracle:graalvm:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "java-binary-jdk", @@ -145,7 +148,7 @@ func DefaultClassifiers() []Classifier { `(?m)\x00(?P[0-9]+\.[0-9]+\.[0-9]+(\+[0-9]+)?([-._a-zA-Z0-9]+)?)\x00`), Package: "java/jdk", PURL: mustPURL("pkg:generic/java/jdk@version"), - CPEs: singleCPE("cpe:2.3:a:oracle:jdk:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:oracle:jdk:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "nodejs-binary", @@ -154,7 +157,7 @@ func DefaultClassifiers() []Classifier { `(?m)node\.js\/v(?P[0-9]+\.[0-9]+\.[0-9]+)`), Package: "node", PURL: mustPURL("pkg:generic/node@version"), - CPEs: singleCPE("cpe:2.3:a:nodejs:node.js:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:nodejs:node.js:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "go-binary-hint", @@ -163,6 +166,7 @@ func DefaultClassifiers() []Classifier { `(?m)go(?P[0-9]+\.[0-9]+(\.[0-9]+|beta[0-9]+|alpha[0-9]+|rc[0-9]+)?)`), Package: "go", PURL: mustPURL("pkg:generic/go@version"), + CPEs: singleCPE("cpe:2.3:a:golang:go:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "busybox-binary", @@ -171,7 +175,7 @@ func DefaultClassifiers() []Classifier { `(?m)BusyBox\s+v(?P[0-9]+\.[0-9]+\.[0-9]+)`), Package: "busybox", PURL: mustPURL("pkg:generic/busybox@version"), - CPEs: singleCPE("cpe:2.3:a:busybox:busybox:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:busybox:busybox:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "util-linux-binary", @@ -180,7 +184,7 @@ func DefaultClassifiers() []Classifier { `\x00util-linux\s(?P[0-9]+\.[0-9]+\.[0-9]+)\x00`), Package: "util-linux", PURL: mustPURL("pkg:generic/util-linux@version"), - CPEs: singleCPE("cpe:2.3:a:kernel:util-linux:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:kernel:util-linux:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "haproxy-binary", @@ -191,7 +195,7 @@ func DefaultClassifiers() []Classifier { ), Package: "haproxy", PURL: mustPURL("pkg:generic/haproxy@version"), - CPEs: singleCPE("cpe:2.3:a:haproxy:haproxy:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:haproxy:haproxy:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "perl-binary", @@ -200,7 +204,7 @@ func DefaultClassifiers() []Classifier { `(?m)\/usr\/local\/lib\/perl\d\/(?P[0-9]+\.[0-9]+\.[0-9]+)`), Package: "perl", PURL: mustPURL("pkg:generic/perl@version"), - CPEs: singleCPE("cpe:2.3:a:perl:perl:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:perl:perl:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "php-cli-binary", @@ -210,7 +214,7 @@ func DefaultClassifiers() []Classifier { `(?m)X-Powered-By: PHP\/(?P[0-9]+\.[0-9]+\.[0-9]+(beta[0-9]+|alpha[0-9]+|RC[0-9]+)?)`), Package: "php-cli", PURL: mustPURL("pkg:generic/php-cli@version"), - CPEs: singleCPE("cpe:2.3:a:php:php:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:php:php:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "php-fpm-binary", @@ -219,7 +223,7 @@ func DefaultClassifiers() []Classifier { `(?m)X-Powered-By: PHP\/(?P[0-9]+\.[0-9]+\.[0-9]+(beta[0-9]+|alpha[0-9]+|RC[0-9]+)?)`), Package: "php-fpm", PURL: mustPURL("pkg:generic/php-fpm@version"), - CPEs: singleCPE("cpe:2.3:a:php:php:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:php:php:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "php-apache-binary", @@ -228,7 +232,7 @@ func DefaultClassifiers() []Classifier { `(?m)X-Powered-By: PHP\/(?P[0-9]+\.[0-9]+\.[0-9]+(beta[0-9]+|alpha[0-9]+|RC[0-9]+)?)`), Package: "libphp", PURL: mustPURL("pkg:generic/php@version"), - CPEs: singleCPE("cpe:2.3:a:php:php:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:php:php:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "php-composer-binary", @@ -237,7 +241,7 @@ func DefaultClassifiers() []Classifier { `(?m)'pretty_version'\s*=>\s*'(?P[0-9]+\.[0-9]+\.[0-9]+(beta[0-9]+|alpha[0-9]+|RC[0-9]+)?)'`), Package: "composer", PURL: mustPURL("pkg:generic/composer@version"), - CPEs: singleCPE("cpe:2.3:a:getcomposer:composer:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:getcomposer:composer:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "httpd-binary", @@ -246,7 +250,7 @@ func DefaultClassifiers() []Classifier { `(?m)Apache\/(?P[0-9]+\.[0-9]+\.[0-9]+)`), Package: "httpd", PURL: mustPURL("pkg:generic/httpd@version"), - CPEs: singleCPE("cpe:2.3:a:apache:http_server:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:apache:http_server:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "memcached-binary", @@ -255,7 +259,7 @@ func DefaultClassifiers() []Classifier { `(?m)memcached\s(?P[0-9]+\.[0-9]+\.[0-9]+)`), Package: "memcached", PURL: mustPURL("pkg:generic/memcached@version"), - CPEs: singleCPE("cpe:2.3:a:memcached:memcached:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:memcached:memcached:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "traefik-binary", @@ -267,7 +271,7 @@ func DefaultClassifiers() []Classifier { `(?m)(\x00|\x{FFFD})?v?(?P[0-9]+\.[0-9]+\.[0-9]+(-alpha[0-9]|-beta[0-9]|-rc[0-9])?)\x00`), Package: "traefik", PURL: mustPURL("pkg:generic/traefik@version"), - CPEs: singleCPE("cpe:2.3:a:traefik:traefik:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:traefik:traefik:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "arangodb-binary", @@ -276,7 +280,7 @@ func DefaultClassifiers() []Classifier { `(?m)\x00*(?P[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?)\s\[linux\]`), Package: "arangodb", PURL: mustPURL("pkg:generic/arangodb@version"), - CPEs: singleCPE("cpe:2.3:a:arangodb:arangodb:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:arangodb:arangodb:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "postgresql-binary", @@ -289,7 +293,7 @@ func DefaultClassifiers() []Classifier { `(?m)(\x00|\?)PostgreSQL (?P[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)`), Package: "postgresql", PURL: mustPURL("pkg:generic/postgresql@version"), - CPEs: singleCPE("cpe:2.3:a:postgresql:postgresql:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:postgresql:postgresql:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "mysql-binary", @@ -302,7 +306,7 @@ func DefaultClassifiers() []Classifier { ), Package: "mysql", PURL: mustPURL("pkg:generic/mysql@version"), - CPEs: singleCPE("cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "mysql-binary", @@ -312,8 +316,8 @@ func DefaultClassifiers() []Classifier { Package: "percona-server", PURL: mustPURL("pkg:generic/percona-server@version"), CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*", cpe.GeneratedSource), - cpe.Must("cpe:2.3:a:percona:percona_server:*:*:*:*:*:*:*:*", cpe.GeneratedSource), + cpe.Must("cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + cpe.Must("cpe:2.3:a:percona:percona_server:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, }, { @@ -324,9 +328,9 @@ func DefaultClassifiers() []Classifier { Package: "percona-xtradb-cluster", PURL: mustPURL("pkg:generic/percona-xtradb-cluster@version"), CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*", cpe.GeneratedSource), - cpe.Must("cpe:2.3:a:percona:percona_server:*:*:*:*:*:*:*:*", cpe.GeneratedSource), - cpe.Must("cpe:2.3:a:percona:xtradb_cluster:*:*:*:*:*:*:*:*", cpe.GeneratedSource), + cpe.Must("cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + cpe.Must("cpe:2.3:a:percona:percona_server:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + cpe.Must("cpe:2.3:a:percona:xtradb_cluster:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, }, { @@ -336,7 +340,7 @@ func DefaultClassifiers() []Classifier { `(?m).*/percona-xtrabackup-(?P[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)`), Package: "percona-xtrabackup", PURL: mustPURL("pkg:generic/percona-xtrabackup@version"), - CPEs: singleCPE("cpe:2.3:a:percona:xtrabackup:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:percona:xtrabackup:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "mariadb-binary", @@ -346,6 +350,7 @@ func DefaultClassifiers() []Classifier { `(?m)(?P[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)-MariaDB`), Package: "mariadb", PURL: mustPURL("pkg:generic/mariadb@version"), + CPEs: singleCPE("cpe:2.3:a:mariadb:mariadb:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "rust-standard-library-linux", @@ -355,7 +360,7 @@ func DefaultClassifiers() []Classifier { `(?m)(\x00)clang LLVM \(rustc version (?P[0-9]+(\.[0-9]+)?(\.[0-9]+)) \(\w+ \d{4}\-\d{2}\-\d{2}\)`), Package: "rust", PURL: mustPURL("pkg:generic/rust@version"), - CPEs: singleCPE("cpe:2.3:a:rust-lang:rust:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:rust-lang:rust:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "rust-standard-library-macos", @@ -365,7 +370,7 @@ func DefaultClassifiers() []Classifier { `(?m)c (?P[0-9]+(\.[0-9]+)?(\.[0-9]+)) \(\w+ \d{4}\-\d{2}\-\d{2}\)`), Package: "rust", PURL: mustPURL("pkg:generic/rust@version"), - CPEs: singleCPE("cpe:2.3:a:rust-lang:rust:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:rust-lang:rust:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "ruby-binary", @@ -379,7 +384,7 @@ func DefaultClassifiers() []Classifier { ), Package: "ruby", PURL: mustPURL("pkg:generic/ruby@version"), - CPEs: singleCPE("cpe:2.3:a:ruby-lang:ruby:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:ruby-lang:ruby:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "erlang-binary", @@ -396,7 +401,7 @@ func DefaultClassifiers() []Classifier { ), Package: "erlang", PURL: mustPURL("pkg:generic/erlang@version"), - CPEs: singleCPE("cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "erlang-alpine-binary", @@ -413,7 +418,7 @@ func DefaultClassifiers() []Classifier { ), Package: "erlang", PURL: mustPURL("pkg:generic/erlang@version"), - CPEs: singleCPE("cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "erlang-library", @@ -430,7 +435,7 @@ func DefaultClassifiers() []Classifier { ), Package: "erlang", PURL: mustPURL("pkg:generic/erlang@version"), - CPEs: singleCPE("cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "swipl-binary", @@ -440,7 +445,7 @@ func DefaultClassifiers() []Classifier { ), Package: "swipl", PURL: mustPURL("pkg:generic/swipl@version"), - CPEs: singleCPE("cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "consul-binary", @@ -451,7 +456,7 @@ func DefaultClassifiers() []Classifier { ), Package: "consul", PURL: mustPURL("pkg:golang/github.com/hashicorp/consul@version"), - CPEs: singleCPE("cpe:2.3:a:hashicorp:consul:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:hashicorp:consul:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "nginx-binary", @@ -464,8 +469,8 @@ func DefaultClassifiers() []Classifier { Package: "nginx", PURL: mustPURL("pkg:generic/nginx@version"), CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:f5:nginx:*:*:*:*:*:*:*:*", cpe.GeneratedSource), - cpe.Must("cpe:2.3:a:nginx:nginx:*:*:*:*:*:*:*:*", cpe.GeneratedSource), + cpe.Must("cpe:2.3:a:f5:nginx:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + cpe.Must("cpe:2.3:a:nginx:nginx:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, }, { @@ -480,7 +485,7 @@ func DefaultClassifiers() []Classifier { ), Package: "bash", PURL: mustPURL("pkg:generic/bash@version"), - CPEs: singleCPE("cpe:2.3:a:gnu:bash:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:gnu:bash:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "openssl-binary", @@ -492,7 +497,7 @@ func DefaultClassifiers() []Classifier { ), Package: "openssl", PURL: mustPURL("pkg:generic/openssl@version"), - CPEs: singleCPE("cpe:2.3:a:openssl:openssl:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:openssl:openssl:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "gcc-binary", @@ -503,7 +508,7 @@ func DefaultClassifiers() []Classifier { ), Package: "gcc", PURL: mustPURL("pkg:generic/gcc@version"), - CPEs: singleCPE("cpe:2.3:a:gnu:gcc:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:gnu:gcc:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "fluent-bit-binary", @@ -516,7 +521,7 @@ func DefaultClassifiers() []Classifier { ), Package: "fluent-bit", PURL: mustPURL("pkg:github/fluent/fluent-bit@version"), - CPEs: singleCPE("cpe:2.3:a:treasuredata:fluent_bit:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:treasuredata:fluent_bit:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "wordpress-cli-binary", @@ -527,7 +532,7 @@ func DefaultClassifiers() []Classifier { ), Package: "wp-cli", PURL: mustPURL("pkg:generic/wp-cli@version"), - CPEs: singleCPE("cpe:2.3:a:wp-cli:wp-cli:*:*:*:*:*:*:*:*"), + CPEs: singleCPE("cpe:2.3:a:wp-cli:wp-cli:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, { Class: "curl-binary", From 04e3371cce248fb221bd79641754898c6db01030 Mon Sep 17 00:00:00 2001 From: GGMU <49076226+tomersein@users.noreply.github.com> Date: Wed, 28 Aug 2024 18:04:26 +0300 Subject: [PATCH 171/284] fix: add log time of task (#3105) Signed-off-by: tomersein --- internal/task/executor.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/task/executor.go b/internal/task/executor.go index 5ba48b58a..2935f61b1 100644 --- a/internal/task/executor.go +++ b/internal/task/executor.go @@ -5,7 +5,9 @@ import ( "fmt" "runtime/debug" "sync" + "time" + "github.com/anchore/syft/internal/log" "github.com/hashicorp/go-multierror" "github.com/anchore/syft/internal/sbomsync" @@ -68,5 +70,8 @@ func runTaskSafely(ctx context.Context, t Task, resolver file.Resolver, s sbomsy } }() - return t.Execute(ctx, resolver, s) + start := time.Now() + res := t.Execute(ctx, resolver, s) + log.WithFields("task", t.Name(), "elapsed", time.Since(start)).Info("task completed") + return res } From 2c25f81b6822eb5035d5bc8d081ec02d618c5694 Mon Sep 17 00:00:00 2001 From: Weston Steimel Date: Wed, 28 Aug 2024 16:46:35 +0100 Subject: [PATCH 172/284] fix: improve generated cpes for binaries with existing classifiers (#3169) The existing syft binary classifiers already specify any known CPEs for the defined binary; however, sometimes these end up getting suppressed (such as when there are ELF notes extracted) and the CPE generator ends up being used instead. This adds enough detail to at least ensure the correct ones get appended to the generation list for the currently covered classifiers. Signed-off-by: Weston Steimel --- .../cpegenerate/candidate_by_package_type.go | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/syft/pkg/cataloger/internal/cpegenerate/candidate_by_package_type.go b/syft/pkg/cataloger/internal/cpegenerate/candidate_by_package_type.go index 5fca14c51..39b62342a 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/candidate_by_package_type.go +++ b/syft/pkg/cataloger/internal/cpegenerate/candidate_by_package_type.go @@ -21,6 +21,137 @@ type candidateRemovalComposite struct { // select package information is discovered var defaultCandidateAdditions = buildCandidateLookup( []candidateComposite{ + // Binary packages + { + pkg.BinaryPkg, + candidateKey{PkgName: "curl"}, + candidateAddition{AdditionalVendors: []string{"haxx"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "go"}, + candidateAddition{AdditionalVendors: []string{"golang"}}, + }, + // Not including the various java ones for now since the raised + // binary package classifier name is the same but there are different CPEs + // for different distributions of OpenJDK. Also, it is unlikely this name will collide + // with whatever might be raised by an ELF notes section, so these are unlikely to + // be of much use here anyways + { + pkg.BinaryPkg, + candidateKey{PkgName: "julia"}, + candidateAddition{AdditionalVendors: []string{"julialang"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "python"}, + candidateAddition{AdditionalVendors: []string{"python_software_foundation"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "redis"}, + candidateAddition{AdditionalVendors: []string{"redislabs"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "node"}, + candidateAddition{AdditionalProducts: []string{"node.js"}, AdditionalVendors: []string{"nodejs"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "util-linux"}, + candidateAddition{AdditionalVendors: []string{"kernel"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "composer"}, + candidateAddition{AdditionalVendors: []string{"getcomposer"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "httpd"}, + candidateAddition{AdditionalProducts: []string{"http_server"}, AdditionalVendors: []string{"apache"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "mysql"}, + candidateAddition{AdditionalVendors: []string{"oracle"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "php-cli"}, + candidateAddition{AdditionalProducts: []string{"php"}, AdditionalVendors: []string{"php"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "php-fpm"}, + candidateAddition{AdditionalProducts: []string{"php"}, AdditionalVendors: []string{"php"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "libphp"}, + candidateAddition{AdditionalProducts: []string{"php"}, AdditionalVendors: []string{"php"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "percona-server"}, + candidateAddition{AdditionalProducts: []string{"percona_server", "mysql"}, AdditionalVendors: []string{"oracle", "percona"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "percona-xtradb-cluster"}, + candidateAddition{AdditionalProducts: []string{"percona_server", "mysql", "xtradb_cluster"}, AdditionalVendors: []string{"oracle", "percona"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "percona-xtrabackup"}, + candidateAddition{AdditionalProducts: []string{"xtrabackup"}, AdditionalVendors: []string{"percona"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "rust"}, + candidateAddition{AdditionalVendors: []string{"rust-lang"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "ruby"}, + candidateAddition{AdditionalVendors: []string{"ruby-lang"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "erlang"}, + candidateAddition{AdditionalProducts: []string{"erlang/otp"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "swipl"}, + candidateAddition{AdditionalProducts: []string{"erlang/otp"}, AdditionalVendors: []string{"erlang"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "consule"}, + candidateAddition{AdditionalVendors: []string{"hashicorp"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "nginx"}, + candidateAddition{AdditionalVendors: []string{"f5"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "bash"}, + candidateAddition{AdditionalVendors: []string{"gnu"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "gcc"}, + candidateAddition{AdditionalVendors: []string{"gnu"}}, + }, + { + pkg.BinaryPkg, + candidateKey{PkgName: "fluent-bit"}, + candidateAddition{AdditionalProducts: []string{"fluent_bit"}, AdditionalVendors: []string{"treasuredata"}}, + }, // Java packages { pkg.JavaPkg, From 11d77b4a9489604c5148bba7a6ca84bd31786691 Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Wed, 28 Aug 2024 15:12:13 -0400 Subject: [PATCH 173/284] fix: cycles resolving relative path parent poms with parent-defined variables (#3170) Signed-off-by: Keith Zantow --- syft/pkg/cataloger/java/archive_parser.go | 4 +- syft/pkg/cataloger/java/maven_resolver.go | 99 ++++++++++++------- .../pkg/cataloger/java/maven_resolver_test.go | 80 +++++++++++---- syft/pkg/cataloger/java/parse_pom_xml.go | 6 +- .../test-fixtures/pom/local/child-2/pom.xml | 15 +++ .../test-fixtures/pom/local/child-3/pom.xml | 15 +++ .../test-fixtures/pom/local/parent-3/pom.xml | 14 +++ 7 files changed, 170 insertions(+), 63 deletions(-) create mode 100644 syft/pkg/cataloger/java/test-fixtures/pom/local/child-2/pom.xml create mode 100644 syft/pkg/cataloger/java/test-fixtures/pom/local/child-3/pom.xml create mode 100644 syft/pkg/cataloger/java/test-fixtures/pom/local/parent-3/pom.xml diff --git a/syft/pkg/cataloger/java/archive_parser.go b/syft/pkg/cataloger/java/archive_parser.go index d2e16898c..740ad0071 100644 --- a/syft/pkg/cataloger/java/archive_parser.go +++ b/syft/pkg/cataloger/java/archive_parser.go @@ -283,7 +283,7 @@ func (j *archiveParser) findLicenseFromJavaMetadata(ctx context.Context, groupID if parsedPom != nil { pomLicenses, err = j.maven.resolveLicenses(ctx, parsedPom.project) if err != nil { - log.WithFields("error", err, "mavenID", j.maven.resolveMavenID(ctx, parsedPom.project)).Debug("error attempting to resolve pom licenses") + log.WithFields("error", err, "mavenID", j.maven.getMavenID(ctx, parsedPom.project)).Debug("error attempting to resolve pom licenses") } } @@ -352,7 +352,7 @@ func (j *archiveParser) discoverMainPackageFromPomInfo(ctx context.Context) (gro version = pomProperties.Version if parsedPom != nil && parsedPom.project != nil { - id := j.maven.resolveMavenID(ctx, parsedPom.project) + id := j.maven.getMavenID(ctx, parsedPom.project) if group == "" { group = id.GroupID } diff --git a/syft/pkg/cataloger/java/maven_resolver.go b/syft/pkg/cataloger/java/maven_resolver.go index e7e73b0be..f9d375b8e 100644 --- a/syft/pkg/cataloger/java/maven_resolver.go +++ b/syft/pkg/cataloger/java/maven_resolver.go @@ -67,10 +67,17 @@ func newMavenResolver(fileResolver file.Resolver, cfg ArchiveCatalogerConfig) *m // as well as supporting the project expressions like ${project.parent.groupId}. // Properties which are not resolved result in empty string "" func (r *mavenResolver) getPropertyValue(ctx context.Context, propertyValue *string, resolutionContext ...*gopom.Project) string { + return r.resolvePropertyValue(ctx, propertyValue, nil, resolutionContext...) +} + +// resolvePropertyValue resolves property values by emulating maven property resolution logic, looking in the project's variables +// as well as supporting the project expressions like ${project.parent.groupId}. +// Properties which are not resolved result in empty string "" +func (r *mavenResolver) resolvePropertyValue(ctx context.Context, propertyValue *string, resolvingProperties []string, resolutionContext ...*gopom.Project) string { if propertyValue == nil { return "" } - resolved, err := r.resolveExpression(ctx, resolutionContext, *propertyValue, nil) + resolved, err := r.resolveExpression(ctx, resolutionContext, *propertyValue, resolvingProperties) if err != nil { log.WithFields("error", err, "propertyValue", *propertyValue).Debug("error resolving maven property") return "" @@ -79,32 +86,35 @@ func (r *mavenResolver) getPropertyValue(ctx context.Context, propertyValue *str } // resolveExpression resolves an expression, which may be a plain string or a string with ${ property.references } -func (r *mavenResolver) resolveExpression(ctx context.Context, resolutionContext []*gopom.Project, expression string, resolving []string) (string, error) { - var err error +func (r *mavenResolver) resolveExpression(ctx context.Context, resolutionContext []*gopom.Project, expression string, resolvingProperties []string) (string, error) { + log.Tracef("resolving expression: '%v' in context: %v", expression, resolutionContext) + + var errs error return expressionMatcher.ReplaceAllStringFunc(expression, func(match string) string { + log.Tracef("resolving property: '%v' in context: %v", expression, resolutionContext) propertyExpression := strings.TrimSpace(match[2 : len(match)-1]) // remove leading ${ and trailing } - resolved, e := r.resolveProperty(ctx, resolutionContext, propertyExpression, resolving) - if e != nil { - err = errors.Join(err, e) + resolved, err := r.resolveProperty(ctx, resolutionContext, propertyExpression, resolvingProperties) + if err != nil { + errs = errors.Join(errs, err) return "" } return resolved - }), err + }), errs } // resolveProperty resolves properties recursively from the root project -func (r *mavenResolver) resolveProperty(ctx context.Context, resolutionContext []*gopom.Project, propertyExpression string, resolving []string) (string, error) { +func (r *mavenResolver) resolveProperty(ctx context.Context, resolutionContext []*gopom.Project, propertyExpression string, resolvingProperties []string) (string, error) { // prevent cycles - if slices.Contains(resolving, propertyExpression) { + if slices.Contains(resolvingProperties, propertyExpression) { return "", fmt.Errorf("cycle detected resolving: %s", propertyExpression) } if len(resolutionContext) == 0 { return "", fmt.Errorf("no project variable resolution context provided for expression: '%s'", propertyExpression) } - resolving = append(resolving, propertyExpression) + resolvingProperties = append(resolvingProperties, propertyExpression) // only resolve project. properties in the context of the current project pom - value, err := r.resolveProjectProperty(ctx, resolutionContext, resolutionContext[len(resolutionContext)-1], propertyExpression, resolving) + value, err := r.resolveProjectProperty(ctx, resolutionContext, resolutionContext[len(resolutionContext)-1], propertyExpression, resolvingProperties) if err != nil { return value, err } @@ -120,10 +130,10 @@ func (r *mavenResolver) resolveProperty(ctx context.Context, resolutionContext [ } if current.Properties != nil && current.Properties.Entries != nil { if value, ok := current.Properties.Entries[propertyExpression]; ok { - return r.resolveExpression(ctx, resolutionContext, value, resolving) // property values can contain expressions + return r.resolveExpression(ctx, resolutionContext, value, resolvingProperties) // property values can contain expressions } } - current, err = r.resolveParent(ctx, current) + current, err = r.resolveParent(ctx, current, resolvingProperties...) if err != nil { return "", err } @@ -200,23 +210,33 @@ func (r *mavenResolver) resolveProjectProperty(ctx context.Context, resolutionCo return "", nil } +// getMavenID creates a new mavenID from a pom, resolving parent information as necessary +func (r *mavenResolver) getMavenID(ctx context.Context, resolutionContext ...*gopom.Project) mavenID { + return r.resolveMavenID(ctx, nil, resolutionContext...) +} + // resolveMavenID creates a new mavenID from a pom, resolving parent information as necessary -func (r *mavenResolver) resolveMavenID(ctx context.Context, pom *gopom.Project) mavenID { +func (r *mavenResolver) resolveMavenID(ctx context.Context, resolvingProperties []string, resolutionContext ...*gopom.Project) mavenID { + if len(resolutionContext) == 0 || resolutionContext[0] == nil { + return mavenID{} + } + pom := resolutionContext[len(resolutionContext)-1] // get topmost pom if pom == nil { return mavenID{} } - groupID := r.getPropertyValue(ctx, pom.GroupID, pom) - artifactID := r.getPropertyValue(ctx, pom.ArtifactID, pom) - version := r.getPropertyValue(ctx, pom.Version, pom) + + groupID := r.resolvePropertyValue(ctx, pom.GroupID, resolvingProperties, resolutionContext...) + artifactID := r.resolvePropertyValue(ctx, pom.ArtifactID, resolvingProperties, resolutionContext...) + version := r.resolvePropertyValue(ctx, pom.Version, resolvingProperties, resolutionContext...) if pom.Parent != nil { if groupID == "" { - groupID = r.getPropertyValue(ctx, pom.Parent.GroupID, pom) + groupID = r.resolvePropertyValue(ctx, pom.Parent.GroupID, resolvingProperties, resolutionContext...) } if artifactID == "" { - artifactID = r.getPropertyValue(ctx, pom.Parent.ArtifactID, pom) + artifactID = r.resolvePropertyValue(ctx, pom.Parent.ArtifactID, resolvingProperties, resolutionContext...) } if version == "" { - version = r.getPropertyValue(ctx, pom.Parent.Version, pom) + version = r.resolvePropertyValue(ctx, pom.Parent.Version, resolvingProperties, resolutionContext...) } } return mavenID{groupID, artifactID, version} @@ -240,7 +260,7 @@ func (r *mavenResolver) resolveDependencyID(ctx context.Context, pom *gopom.Proj depID := mavenID{groupID, artifactID, version} if err != nil { - log.WithFields("error", err, "mavenID", r.resolveMavenID(ctx, pom), "dependencyID", depID) + log.WithFields("error", err, "mavenID", r.getMavenID(ctx, pom), "dependencyID", depID) } return depID @@ -390,16 +410,16 @@ func (r *mavenResolver) cacheResolveReader(key string, resolve func() (io.ReadCl } // resolveParent attempts to resolve the parent for the given pom -func (r *mavenResolver) resolveParent(ctx context.Context, pom *gopom.Project) (*gopom.Project, error) { +func (r *mavenResolver) resolveParent(ctx context.Context, pom *gopom.Project, resolvingProperties ...string) (*gopom.Project, error) { if pom == nil || pom.Parent == nil { return nil, nil } parent := pom.Parent pomWithoutParent := *pom pomWithoutParent.Parent = nil - groupID := r.getPropertyValue(ctx, parent.GroupID, &pomWithoutParent) - artifactID := r.getPropertyValue(ctx, parent.ArtifactID, &pomWithoutParent) - version := r.getPropertyValue(ctx, parent.Version, &pomWithoutParent) + groupID := r.resolvePropertyValue(ctx, parent.GroupID, resolvingProperties, &pomWithoutParent) + artifactID := r.resolvePropertyValue(ctx, parent.ArtifactID, resolvingProperties, &pomWithoutParent) + version := r.resolvePropertyValue(ctx, parent.Version, resolvingProperties, &pomWithoutParent) // check cache before resolving parentID := mavenID{groupID, artifactID, version} @@ -408,7 +428,7 @@ func (r *mavenResolver) resolveParent(ctx context.Context, pom *gopom.Project) ( } // check if the pom exists in the fileResolver - parentPom := r.findParentPomByRelativePath(ctx, pom, parentID) + parentPom := r.findParentPomByRelativePath(ctx, pom, parentID, resolvingProperties) if parentPom != nil { return parentPom, nil } @@ -425,10 +445,10 @@ func (r *mavenResolver) findInheritedVersion(ctx context.Context, pom *gopom.Pro return "", fmt.Errorf("nil pom provided to findInheritedVersion") } if r.cfg.MaxParentRecursiveDepth > 0 && len(resolutionContext) > r.cfg.MaxParentRecursiveDepth { - return "", fmt.Errorf("maximum depth reached attempting to resolve version for: %s:%s at: %v", groupID, artifactID, r.resolveMavenID(ctx, pom)) + return "", fmt.Errorf("maximum depth reached attempting to resolve version for: %s:%s at: %v", groupID, artifactID, r.getMavenID(ctx, pom)) } if slices.Contains(resolutionContext, pom) { - return "", fmt.Errorf("cycle detected attempting to resolve version for: %s:%s at: %v", groupID, artifactID, r.resolveMavenID(ctx, pom)) + return "", fmt.Errorf("cycle detected attempting to resolve version for: %s:%s at: %v", groupID, artifactID, r.getMavenID(ctx, pom)) } resolutionContext = append(resolutionContext, pom) @@ -452,13 +472,13 @@ func (r *mavenResolver) findInheritedVersion(ctx context.Context, pom *gopom.Pro depPom, err := r.findPom(ctx, depGroupID, depArtifactID, depVersion) if err != nil || depPom == nil { - log.WithFields("error", err, "mavenID", r.resolveMavenID(ctx, pom), "dependencyID", mavenID{depGroupID, depArtifactID, depVersion}). + log.WithFields("error", err, "mavenID", r.getMavenID(ctx, pom), "dependencyID", mavenID{depGroupID, depArtifactID, depVersion}). Debug("unable to find imported pom looking for managed dependencies") continue } version, err = r.findInheritedVersion(ctx, depPom, groupID, artifactID, resolutionContext...) if err != nil { - log.WithFields("error", err, "mavenID", r.resolveMavenID(ctx, pom), "dependencyID", mavenID{depGroupID, depArtifactID, depVersion}). + log.WithFields("error", err, "mavenID", r.getMavenID(ctx, pom), "dependencyID", mavenID{depGroupID, depArtifactID, depVersion}). Debug("error during findInheritedVersion") } if version != "" { @@ -508,7 +528,7 @@ func (r *mavenResolver) findLicenses(ctx context.Context, groupID, artifactID, v // resolveLicenses searches the pom for license, traversing parent poms if needed func (r *mavenResolver) resolveLicenses(ctx context.Context, pom *gopom.Project, processing ...mavenID) ([]gopom.License, error) { - id := r.resolveMavenID(ctx, pom) + id := r.getMavenID(ctx, pom) if slices.Contains(processing, id) { return nil, fmt.Errorf("cycle detected resolving licenses for: %v", id) } @@ -545,7 +565,7 @@ func (r *mavenResolver) pomLicenses(ctx context.Context, pom *gopom.Project) []g return out } -func (r *mavenResolver) findParentPomByRelativePath(ctx context.Context, pom *gopom.Project, parentID mavenID) *gopom.Project { +func (r *mavenResolver) findParentPomByRelativePath(ctx context.Context, pom *gopom.Project, parentID mavenID, resolvingProperties []string) *gopom.Project { // don't resolve if no resolver if r.fileResolver == nil { return nil @@ -555,7 +575,7 @@ func (r *mavenResolver) findParentPomByRelativePath(ctx context.Context, pom *go if !hasPomLocation || pom == nil || pom.Parent == nil { return nil } - relativePath := r.getPropertyValue(ctx, pom.Parent.RelativePath, pom) + relativePath := r.resolvePropertyValue(ctx, pom.Parent.RelativePath, resolvingProperties, pom) if relativePath == "" { return nil } @@ -563,9 +583,12 @@ func (r *mavenResolver) findParentPomByRelativePath(ctx context.Context, pom *go p = path.Dir(p) p = path.Join(p, relativePath) p = path.Clean(p) + if !strings.HasSuffix(p, ".xml") { + p = path.Join(p, "pom.xml") + } parentLocations, err := r.fileResolver.FilesByPath(p) if err != nil || len(parentLocations) == 0 { - log.WithFields("error", err, "mavenID", r.resolveMavenID(ctx, pom), "parentID", parentID, "relativePath", relativePath). + log.WithFields("error", err, "mavenID", r.resolveMavenID(ctx, resolvingProperties, pom), "parentID", parentID, "relativePath", relativePath). Trace("parent pom not found by relative path") return nil } @@ -573,21 +596,21 @@ func (r *mavenResolver) findParentPomByRelativePath(ctx context.Context, pom *go parentContents, err := r.fileResolver.FileContentsByLocation(parentLocation) if err != nil || parentContents == nil { - log.WithFields("error", err, "mavenID", r.resolveMavenID(ctx, pom), "parentID", parentID, "parentLocation", parentLocation). + log.WithFields("error", err, "mavenID", r.resolveMavenID(ctx, resolvingProperties, pom), "parentID", parentID, "parentLocation", parentLocation). Debug("unable to get contents of parent pom by relative path") return nil } defer internal.CloseAndLogError(parentContents, parentLocation.RealPath) parentPom, err := decodePomXML(parentContents) if err != nil || parentPom == nil { - log.WithFields("error", err, "mavenID", r.resolveMavenID(ctx, pom), "parentID", parentID, "parentLocation", parentLocation). + log.WithFields("error", err, "mavenID", r.resolveMavenID(ctx, resolvingProperties, pom), "parentID", parentID, "parentLocation", parentLocation). Debug("unable to parse parent pom") return nil } // ensure parent matches - newParentID := r.resolveMavenID(ctx, parentPom) + newParentID := r.resolveMavenID(ctx, resolvingProperties, parentPom) if newParentID.ArtifactID != parentID.ArtifactID { - log.WithFields("newParentID", newParentID, "mavenID", r.resolveMavenID(ctx, pom), "parentID", parentID, "parentLocation", parentLocation). + log.WithFields("newParentID", newParentID, "mavenID", r.resolveMavenID(ctx, resolvingProperties, pom), "parentID", parentID, "parentLocation", parentLocation). Debug("parent IDs do not match resolving parent by relative path") return nil } diff --git a/syft/pkg/cataloger/java/maven_resolver_test.go b/syft/pkg/cataloger/java/maven_resolver_test.go index d778efb69..bec9b6691 100644 --- a/syft/pkg/cataloger/java/maven_resolver_test.go +++ b/syft/pkg/cataloger/java/maven_resolver_test.go @@ -273,32 +273,72 @@ func Test_relativePathParent(t *testing.T) { resolver, err := fileresolver.NewFromDirectory("test-fixtures/pom/local", "") require.NoError(t, err) - r := newMavenResolver(resolver, DefaultArchiveCatalogerConfig()) - locs, err := resolver.FilesByPath("child-1/pom.xml") - require.NoError(t, err) - require.Len(t, locs, 1) + ctx := context.Background() - loc := locs[0] - contents, err := resolver.FileContentsByLocation(loc) - require.NoError(t, err) - defer internal.CloseAndLogError(contents, loc.RealPath) + tests := []struct { + name string + pom string + validate func(t *testing.T, r *mavenResolver, pom *gopom.Project) + }{ + { + name: "basic", + pom: "child-1/pom.xml", + validate: func(t *testing.T, r *mavenResolver, pom *gopom.Project) { + parent, err := r.resolveParent(ctx, pom) + require.NoError(t, err) + require.Contains(t, r.pomLocations, parent) - pom, err := decodePomXML(contents) - require.NoError(t, err) + parent, err = r.resolveParent(ctx, parent) + require.NoError(t, err) + require.Contains(t, r.pomLocations, parent) - r.pomLocations[pom] = loc + got := r.getPropertyValue(ctx, ptr("${commons-exec_subversion}"), pom) + require.Equal(t, "3", got) - ctx := context.Background() - parent, err := r.resolveParent(ctx, pom) - require.NoError(t, err) - require.Contains(t, r.pomLocations, parent) + }, + }, + { + name: "parent property", + pom: "child-2/pom.xml", + validate: func(t *testing.T, r *mavenResolver, pom *gopom.Project) { + id := r.getMavenID(ctx, pom) + // child.parent.version = ${revision} + // parent.revision = 3.3.3 + require.Equal(t, id.Version, "3.3.3") + }, + }, + { + name: "invalid parent", + pom: "child-3/pom.xml", + validate: func(t *testing.T, r *mavenResolver, pom *gopom.Project) { + require.NotNil(t, pom) + id := r.getMavenID(ctx, pom) + // version should not be resolved to anything + require.Equal(t, "", id.Version) + }, + }, + } - parent, err = r.resolveParent(ctx, parent) - require.NoError(t, err) - require.Contains(t, r.pomLocations, parent) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + r := newMavenResolver(resolver, DefaultArchiveCatalogerConfig()) + locs, err := resolver.FilesByPath(test.pom) + require.NoError(t, err) + require.Len(t, locs, 1) + + loc := locs[0] + contents, err := resolver.FileContentsByLocation(loc) + require.NoError(t, err) + defer internal.CloseAndLogError(contents, loc.RealPath) + + pom, err := decodePomXML(contents) + require.NoError(t, err) - got := r.getPropertyValue(ctx, ptr("${commons-exec_subversion}"), pom) - require.Equal(t, "3", got) + r.pomLocations[pom] = loc + + test.validate(t, r, pom) + }) + } } // mockMavenRepo starts a remote maven repo serving all the pom files found in test-fixtures/pom/maven-repo diff --git a/syft/pkg/cataloger/java/parse_pom_xml.go b/syft/pkg/cataloger/java/parse_pom_xml.go index d9fe4b2c2..370ebc2c8 100644 --- a/syft/pkg/cataloger/java/parse_pom_xml.go +++ b/syft/pkg/cataloger/java/parse_pom_xml.go @@ -53,7 +53,7 @@ func (p pomXMLCataloger) Catalog(ctx context.Context, fileResolver file.Resolver // store information about this pom for future lookups r.pomLocations[pom] = pomLocation - r.resolved[r.resolveMavenID(ctx, pom)] = pom + r.resolved[r.getMavenID(ctx, pom)] = pom } var pkgs []pkg.Package @@ -75,7 +75,7 @@ func readPomFromLocation(fileResolver file.Resolver, pomLocation file.Location) func processPomXML(ctx context.Context, r *mavenResolver, pom *gopom.Project, loc file.Location) []pkg.Package { var pkgs []pkg.Package - pomID := r.resolveMavenID(ctx, pom) + pomID := r.getMavenID(ctx, pom) for _, dep := range pomDependencies(pom) { depID := r.resolveDependencyID(ctx, pom, dep) log.WithFields("pomLocation", loc, "mavenID", pomID, "dependencyID", depID).Trace("adding maven pom dependency") @@ -100,7 +100,7 @@ func processPomXML(ctx context.Context, r *mavenResolver, pom *gopom.Project, lo } func newPomProject(ctx context.Context, r *mavenResolver, path string, pom *gopom.Project) *pkg.JavaPomProject { - id := r.resolveMavenID(ctx, pom) + id := r.getMavenID(ctx, pom) name := r.getPropertyValue(ctx, pom.Name, pom) projectURL := r.getPropertyValue(ctx, pom.URL, pom) diff --git a/syft/pkg/cataloger/java/test-fixtures/pom/local/child-2/pom.xml b/syft/pkg/cataloger/java/test-fixtures/pom/local/child-2/pom.xml new file mode 100644 index 000000000..057233ae3 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/pom/local/child-2/pom.xml @@ -0,0 +1,15 @@ + + + 4.0.0 + + + my.org + parent-three + ${revision} + ../parent-3 + + + child-two + jar + diff --git a/syft/pkg/cataloger/java/test-fixtures/pom/local/child-3/pom.xml b/syft/pkg/cataloger/java/test-fixtures/pom/local/child-3/pom.xml new file mode 100644 index 000000000..741ab4c07 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/pom/local/child-3/pom.xml @@ -0,0 +1,15 @@ + + + 4.0.0 + + + my.org + parent-three + ${revision} + ../invalid + + + child-three + jar + diff --git a/syft/pkg/cataloger/java/test-fixtures/pom/local/parent-3/pom.xml b/syft/pkg/cataloger/java/test-fixtures/pom/local/parent-3/pom.xml new file mode 100644 index 000000000..eac8785b6 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/pom/local/parent-3/pom.xml @@ -0,0 +1,14 @@ + + + 4.0.0 + + my.org + parent-three + ${revision} + pom + + + 3.3.3 + + From 19d2735affb0dcb7274d9b9711c67d67a02473d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Aug 2024 14:16:34 +0000 Subject: [PATCH 174/284] chore(deps): bump github/codeql-action from 3.26.5 to 3.26.6 (#3173) --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 768415473..65d23b352 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 #v3.26.5 + uses: github/codeql-action/init@4dd16135b69a43b6c8efb853346f8437d92d3c93 #v3.26.6 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 #v3.26.5 + uses: github/codeql-action/autobuild@4dd16135b69a43b6c8efb853346f8437d92d3c93 #v3.26.6 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 #v3.26.5 + uses: github/codeql-action/analyze@4dd16135b69a43b6c8efb853346f8437d92d3c93 #v3.26.6 From 3499d92c6d57cffebf8d665e2b8c2b7b625f8b7f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Aug 2024 14:16:43 +0000 Subject: [PATCH 175/284] chore(deps): bump github.com/charmbracelet/bubbletea (#3171) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f6d03ab6c..552fbaf30 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 github.com/bmatcuk/doublestar/v4 v4.6.1 github.com/charmbracelet/bubbles v0.19.0 - github.com/charmbracelet/bubbletea v0.27.0 + github.com/charmbracelet/bubbletea v1.0.0 github.com/charmbracelet/lipgloss v0.13.0 github.com/dave/jennifer v1.7.0 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da diff --git a/go.sum b/go.sum index a9c8256cf..2d16cd1a5 100644 --- a/go.sum +++ b/go.sum @@ -157,8 +157,8 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charmbracelet/bubbles v0.19.0 h1:gKZkKXPP6GlDk6EcfujDK19PCQqRjaJZQ7QRERx1UF0= github.com/charmbracelet/bubbles v0.19.0/go.mod h1:WILteEqZ+krG5c3ntGEMeG99nCupcuIk7V0/zOP0tOA= -github.com/charmbracelet/bubbletea v0.27.0 h1:Mznj+vvYuYagD9Pn2mY7fuelGvP0HAXtZYGgRBCbHvU= -github.com/charmbracelet/bubbletea v0.27.0/go.mod h1:5MdP9XH6MbQkgGhnlxUqCNmBXf9I74KRQ8HIidRxV1Y= +github.com/charmbracelet/bubbletea v1.0.0 h1:BlNvkVed3DADQlV+W79eioNUOrnMUY25EEVdFUoDoGA= +github.com/charmbracelet/bubbletea v1.0.0/go.mod h1:xc4gm5yv+7tbniEvQ0naiG9P3fzYhk16cTgDZQQW6YE= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= From 731fc776412df87010c8e745d4ef24a1857161ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Aug 2024 14:16:50 +0000 Subject: [PATCH 176/284] chore(deps): bump github.com/docker/docker (#3168) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 552fbaf30..4075c9be9 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/dave/jennifer v1.7.0 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da github.com/distribution/reference v0.6.0 - github.com/docker/docker v27.1.2+incompatible + github.com/docker/docker v27.2.0+incompatible github.com/dustin/go-humanize v1.0.1 github.com/elliotchance/phpserialize v1.4.0 github.com/facebookincubator/nvdtools v0.1.5 diff --git a/go.sum b/go.sum index 2d16cd1a5..c01d9b3c2 100644 --- a/go.sum +++ b/go.sum @@ -231,8 +231,8 @@ github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2 github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.1.2+incompatible h1:AhGzR1xaQIy53qCkxARaFluI00WPGtXn0AJuoQsVYTY= -github.com/docker/docker v27.1.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.2.0+incompatible h1:Rk9nIVdfH3+Vz4cyI/uhbINhEZ/oLmc+CBXmH6fbNk4= +github.com/docker/docker v27.2.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= From f2caf4569532619b43d298f1d4b6b264bcf3208e Mon Sep 17 00:00:00 2001 From: Mikail <6186720+NyanKiyoshi@users.noreply.github.com> Date: Thu, 29 Aug 2024 17:05:43 +0200 Subject: [PATCH 177/284] fix: properly decode SPDX license expressions in CycloneDX format (#3175) Signed-off-by: Mikail Kocak --- syft/format/internal/cyclonedxutil/helpers/licenses.go | 9 +++------ .../internal/cyclonedxutil/helpers/licenses_test.go | 4 ++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/syft/format/internal/cyclonedxutil/helpers/licenses.go b/syft/format/internal/cyclonedxutil/helpers/licenses.go index a092d3abd..24c5d6ffb 100644 --- a/syft/format/internal/cyclonedxutil/helpers/licenses.go +++ b/syft/format/internal/cyclonedxutil/helpers/licenses.go @@ -54,17 +54,14 @@ func decodeLicenses(c *cyclonedx.Component) []pkg.License { } for _, l := range *c.Licenses { - if l.License == nil { - continue - } // these fields are mutually exclusive in the spec switch { - case l.License.ID != "": + case l.License != nil && l.License.ID != "": licenses = append(licenses, pkg.NewLicenseFromURLs(l.License.ID, l.License.URL)) - case l.License.Name != "": + case l.License != nil && l.License.Name != "": licenses = append(licenses, pkg.NewLicenseFromURLs(l.License.Name, l.License.URL)) case l.Expression != "": - licenses = append(licenses, pkg.NewLicenseFromURLs(l.Expression, l.License.URL)) + licenses = append(licenses, pkg.NewLicense(l.Expression)) default: } } diff --git a/syft/format/internal/cyclonedxutil/helpers/licenses_test.go b/syft/format/internal/cyclonedxutil/helpers/licenses_test.go index e2532f607..373a09377 100644 --- a/syft/format/internal/cyclonedxutil/helpers/licenses_test.go +++ b/syft/format/internal/cyclonedxutil/helpers/licenses_test.go @@ -254,7 +254,8 @@ func TestDecodeLicenses(t *testing.T) { input: &cyclonedx.Component{ Licenses: &cyclonedx.Licenses{ { - License: &cyclonedx.License{}, + // CycloneDX specification doesn't allow to provide License if Expression is provided + License: nil, Expression: "MIT AND GPL-3.0-only WITH Classpath-exception-2.0", }, }, @@ -264,7 +265,6 @@ func TestDecodeLicenses(t *testing.T) { Value: "MIT AND GPL-3.0-only WITH Classpath-exception-2.0", SPDXExpression: "MIT AND GPL-3.0-only WITH Classpath-exception-2.0", Type: license.Declared, - URLs: []string{}, }, }, }, From e299a9512045728c91ce979c52d417266f2f2416 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 12:22:07 -0400 Subject: [PATCH 178/284] chore(deps): bump peter-evans/create-pull-request from 6.1.0 to 7.0.0 (#3187) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 6.1.0 to 7.0.0. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/c5a7806660adbe173f04e3e038b0ccdcd758773c...4320041ed380b20e97d388d56a7fb4f9b8c20e79) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-bootstrap-tools.yml | 2 +- .github/workflows/update-cpe-dictionary-index.yml | 2 +- .github/workflows/update-stereoscope-release.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/update-bootstrap-tools.yml b/.github/workflows/update-bootstrap-tools.yml index 9518a233f..488a2cf5b 100644 --- a/.github/workflows/update-bootstrap-tools.yml +++ b/.github/workflows/update-bootstrap-tools.yml @@ -50,7 +50,7 @@ jobs: app_id: ${{ secrets.TOKEN_APP_ID }} private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c #v6.1.0 + - uses: peter-evans/create-pull-request@4320041ed380b20e97d388d56a7fb4f9b8c20e79 #v7.0.0 with: signoff: true delete-branch: true diff --git a/.github/workflows/update-cpe-dictionary-index.yml b/.github/workflows/update-cpe-dictionary-index.yml index 18d3e2d14..879298e06 100644 --- a/.github/workflows/update-cpe-dictionary-index.yml +++ b/.github/workflows/update-cpe-dictionary-index.yml @@ -33,7 +33,7 @@ jobs: app_id: ${{ secrets.TOKEN_APP_ID }} private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c #v6.1.0 + - uses: peter-evans/create-pull-request@4320041ed380b20e97d388d56a7fb4f9b8c20e79 #v7.0.0 with: signoff: true delete-branch: true diff --git a/.github/workflows/update-stereoscope-release.yml b/.github/workflows/update-stereoscope-release.yml index 94ea0ee1b..411422611 100644 --- a/.github/workflows/update-stereoscope-release.yml +++ b/.github/workflows/update-stereoscope-release.yml @@ -44,7 +44,7 @@ jobs: app_id: ${{ secrets.TOKEN_APP_ID }} private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c #v6.1.0 + - uses: peter-evans/create-pull-request@4320041ed380b20e97d388d56a7fb4f9b8c20e79 #v7.0.0 with: signoff: true delete-branch: true From 8ade3916585d76b330dc06647fc110af5aa0c342 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 12:22:16 -0400 Subject: [PATCH 179/284] chore(deps): bump actions/upload-artifact from 4.3.6 to 4.4.0 (#3184) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.6 to 4.4.0. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/834a144ee995460fba8ed112a2fc961b36a5ec5a...50769540e7f4bd5e21e526ee35c689e35e0d6874) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/benchmark-testing.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/benchmark-testing.yaml b/.github/workflows/benchmark-testing.yaml index 8284d8264..9fff8c76a 100644 --- a/.github/workflows/benchmark-testing.yaml +++ b/.github/workflows/benchmark-testing.yaml @@ -39,7 +39,7 @@ jobs: OUTPUT="${OUTPUT//$'\r'/'%0D'}" # URL encode all '\r' characters echo "result=$OUTPUT" >> $GITHUB_OUTPUT - - uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 + - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 with: name: benchmark-test-results path: test/results/**/* From 8c690d000d6e5d6b423541d6b427954f27619b2a Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 12:22:30 -0400 Subject: [PATCH 180/284] chore(deps): update CPE dictionary index (#3183) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: wagoodman <590471+wagoodman@users.noreply.github.com> --- .../dictionary/data/cpe-index.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index 20dee5938..abd3b6ca8 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -6705,6 +6705,9 @@ "multiqueue2": [ "cpe:2.3:a:multiqueue2_project:multiqueue2:*:*:*:*:*:rust:*:*" ], + "naga": [ + "cpe:2.3:a:gfx-rs:naga:*:*:*:*:*:rust:*:*" + ], "nalgebra": [ "cpe:2.3:a:dimforge:nalgebra:*:*:*:*:*:rust:*:*" ], @@ -8081,6 +8084,9 @@ "block-specific-plugin-updates": [ "cpe:2.3:a:dineshkarki:block_plugin_update:*:*:*:*:*:wordpress:*:*" ], + "blockart-blocks": [ + "cpe:2.3:a:wpblockart:blockart_blocks:*:*:*:*:*:wordpress:*:*" + ], "blockonomics-bitcoin-payments": [ "cpe:2.3:a:blockonomics:blockonomics:*:*:*:*:*:wordpress:*:*" ], @@ -8218,6 +8224,9 @@ "bp-social-connect": [ "cpe:2.3:a:vibethemes:bp_social_connect:*:*:*:*:*:wordpress:*:*" ], + "bradmax-player": [ + "cpe:2.3:a:bradmax:bradmax_player:*:*:*:*:*:wordpress:*:*" + ], "brave-popup-builder": [ "cpe:2.3:a:getbrave:brave:*:*:*:*:*:wordpress:*:*" ], @@ -12482,6 +12491,7 @@ "cpe:2.3:a:mediavine:create:*:*:*:*:*:wordpress:*:*" ], "meeting-scheduler-by-vcita": [ + "cpe:2.3:a:vcita:online_booking_\\\u0026_scheduling_calendar:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:vcita:online_booking_\\\u0026_scheduling_calendar_for_wordpress:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:vcita:online_booking_\\\u0026_scheduling_calendar_for_wordpress_by_vcita:*:*:*:*:*:wordpress:*:*" ], @@ -13468,6 +13478,9 @@ "photo-gallery": [ "cpe:2.3:a:10web:photo_gallery:*:*:*:*:*:wordpress:*:*" ], + "photo-video-gallery-master": [ + "cpe:2.3:a:webhuntinfotech:photo_video_gallery_master:*:*:*:*:*:wordpress:*:*" + ], "photoblocks-grid-gallery": [ "cpe:2.3:a:greentreelabs:gallery_photoblocks:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:wpchill:gallery_photoblocks:*:*:*:*:*:wordpress:*:*" @@ -14351,6 +14364,9 @@ "review-schema": [ "cpe:2.3:a:radiustheme:review_schema:*:*:*:*:*:wordpress:*:*" ], + "reviews-feed": [ + "cpe:2.3:a:smashballoon:reviews_feed:*:*:*:*:*:wordpress:*:*" + ], "reviews-plus": [ "cpe:2.3:a:implecode:reviews_plus:*:*:*:*:*:wordpress:*:*" ], @@ -16077,6 +16093,9 @@ "ultimate-blocks": [ "cpe:2.3:a:dotcamp:ultimate_blocks:*:*:*:*:*:wordpress:*:*" ], + "ultimate-bootstrap-elements-for-elementor": [ + "cpe:2.3:a:g5plus:ultimate_bootstrap_elements_for_elementor:*:*:*:*:*:wordpress:*:*" + ], "ultimate-carousel-for-elementor": [ "cpe:2.3:a:topdigitaltrends:ultimate_carousel_for_elementor:*:*:*:*:*:wordpress:*:*" ], From 7c96a10cbea82e94c843112c8394abac7672b0dc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 12:22:43 -0400 Subject: [PATCH 181/284] chore(deps): bump github.com/Masterminds/sprig/v3 from 3.2.3 to 3.3.0 (#3177) Bumps [github.com/Masterminds/sprig/v3](https://github.com/Masterminds/sprig) from 3.2.3 to 3.3.0. - [Release notes](https://github.com/Masterminds/sprig/releases) - [Changelog](https://github.com/Masterminds/sprig/blob/master/CHANGELOG.md) - [Commits](https://github.com/Masterminds/sprig/compare/v3.2.3...v3.3.0) --- updated-dependencies: - dependency-name: github.com/Masterminds/sprig/v3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 13 ++++++------- go.sum | 33 ++++++++++++--------------------- 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/go.mod b/go.mod index 4075c9be9..8e6a7ea63 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.22.0 require ( github.com/CycloneDX/cyclonedx-go v0.9.0 github.com/Masterminds/semver v1.5.0 - github.com/Masterminds/sprig/v3 v3.2.3 + github.com/Masterminds/sprig/v3 v3.3.0 github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/acobaugh/osrelease v0.1.0 github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9 @@ -94,12 +94,12 @@ require ( ) require ( - dario.cat/mergo v1.0.0 // indirect + dario.cat/mergo v1.0.1 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect github.com/DataDog/zstd v1.5.5 // indirect github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.2.0 // indirect + github.com/Masterminds/semver/v3 v3.3.0 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect github.com/ProtonMail/go-crypto v1.0.0 // indirect @@ -153,9 +153,8 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/huandu/xstrings v1.3.3 // indirect + github.com/huandu/xstrings v1.5.0 // indirect github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect - github.com/imdario/mergo v0.3.15 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect @@ -200,11 +199,11 @@ require ( github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sahilm/fuzzy v0.1.1 // indirect github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d // indirect - github.com/shopspring/decimal v1.2.0 // indirect + github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/skeema/knownhosts v1.2.2 // indirect github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/cast v1.7.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.18.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect diff --git a/go.sum b/go.sum index c01d9b3c2..0cc5381b2 100644 --- a/go.sum +++ b/go.sum @@ -45,8 +45,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= @@ -69,10 +69,10 @@ github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJ github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= -github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= -github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= +github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= +github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= +github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= @@ -411,7 +411,6 @@ github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8I github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo= github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -463,8 +462,8 @@ github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOn github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= -github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= -github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= +github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 h1:i462o439ZjprVSFSZLZxcsoAe592sZB1rci2Z8j4wdk= github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= @@ -473,9 +472,6 @@ github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= -github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= -github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= @@ -563,7 +559,6 @@ github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= -github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -576,7 +571,6 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= @@ -707,8 +701,8 @@ github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNX github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -729,10 +723,9 @@ github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY52 github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= -github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= +github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= @@ -871,7 +864,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= @@ -1340,7 +1332,6 @@ gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From a3438256856d372d94a8f13c651dded916e5c56d Mon Sep 17 00:00:00 2001 From: witchcraze <67056980+witchcraze@users.noreply.github.com> Date: Fri, 6 Sep 2024 03:52:19 +0900 Subject: [PATCH 182/284] fix: haproxy classifier for versions with -dev suffix (#3180) Signed-off-by: witchcraze --- .../cataloger/binary/classifier_cataloger_test.go | 12 +++++++++++- syft/pkg/cataloger/binary/classifiers.go | 4 ++-- .../snippets/haproxy/3.1-dev0/linux-amd64/haproxy | Bin 0 -> 351 bytes .../cataloger/binary/test-fixtures/config.yaml | 7 +++++++ 4 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/haproxy/3.1-dev0/linux-amd64/haproxy diff --git a/syft/pkg/cataloger/binary/classifier_cataloger_test.go b/syft/pkg/cataloger/binary/classifier_cataloger_test.go index 721ee9ee0..4e283a56a 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger_test.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger_test.go @@ -359,7 +359,17 @@ func Test_Cataloger_PositiveCases(t *testing.T) { Metadata: metadata("haproxy-binary"), }, }, - + { + logicalFixture: "haproxy/3.1-dev0/linux-amd64", + expected: pkg.Package{ + Name: "haproxy", + Version: "3.1-dev0", + Type: "binary", + PURL: "pkg:generic/haproxy@3.1-dev0", + Locations: locations("haproxy"), + Metadata: metadata("haproxy-binary"), + }, + }, { logicalFixture: "helm/3.11.1/linux-amd64", expected: pkg.Package{ diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index 24c514c7e..46afa87f5 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -190,8 +190,8 @@ func DefaultClassifiers() []Classifier { Class: "haproxy-binary", FileGlob: "**/haproxy", EvidenceMatcher: evidenceMatchers( - FileContentsVersionMatcher(`(?m)HA-Proxy version (?P[0-9]+\.[0-9]+\.[0-9]+)`), - FileContentsVersionMatcher(`(?m)(?P[0-9]+\.[0-9]+\.[0-9]+)-[0-9a-zA-Z]{7}.+HAProxy version`), + FileContentsVersionMatcher(`(?m)HA-Proxy version (?P[0-9]+\.[0-9]+(\.|-dev)[0-9]+)`), + FileContentsVersionMatcher(`(?m)(?P[0-9]+\.[0-9]+(\.|-dev)[0-9]+)-[0-9a-zA-Z]{7}.+HAProxy version`), ), Package: "haproxy", PURL: mustPURL("pkg:generic/haproxy@version"), diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/haproxy/3.1-dev0/linux-amd64/haproxy b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/haproxy/3.1-dev0/linux-amd64/haproxy new file mode 100644 index 0000000000000000000000000000000000000000..94a91b1ad84b87e6746984d2de620782f99345f9 GIT binary patch literal 351 zcmYLFF>b>!49u*lPY~cajYL_pk{mJu6iv*js$YUSERIq;50;z)4x zXKH!pr%V32v7FLOOUspZt~QnpG`=rg%OwalkNq^!^459Krbt@YfDxQ87_88goYXGX zg^CE|Qez@wsDnl!Aw^Q?h>R5x!AM}KAL!2vl~dLhKZ8od;G0Hj>71g7$|q$!MQ<>g z;whV;oDK%d=0=7HR?C{Ps;W5N7UKJve91iJVaT7nv>3R<0R+@1p-(GcLp{o4q^mee qLXiMA^*_HnzphW=SGvr79(TL>aQ~=(hrV~bKj^LAk)OBzQ^6mkZdh&r literal 0 HcmV?d00001 diff --git a/syft/pkg/cataloger/binary/test-fixtures/config.yaml b/syft/pkg/cataloger/binary/test-fixtures/config.yaml index 15273d33d..78d8ba4b8 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/config.yaml +++ b/syft/pkg/cataloger/binary/test-fixtures/config.yaml @@ -106,6 +106,13 @@ from-images: paths: - /usr/local/sbin/haproxy + - version: 3.1-dev0 + images: + - ref: haproxy:3.1-dev0@sha256:eba1aac9aa6ea84869bd2ecae79792a934563fd731eddf724eb3b12ef6a9b93f + platform: linux/amd64 + paths: + - /usr/local/sbin/haproxy + - version: 2.4.54 images: - ref: httpd:2.4.54@sha256:c13feaef62bdb03e65e645f47d9780adea5a080c78eb9e4b3c32e861327262b4 From ff0bae67bdaf052b4ac318ba23932651f98709f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:05:15 -0400 Subject: [PATCH 183/284] chore(deps): bump golang.org/x/mod from 0.20.0 to 0.21.0 (#3197) Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.20.0 to 0.21.0. - [Commits](https://github.com/golang/mod/compare/v0.20.0...v0.21.0) --- updated-dependencies: - dependency-name: golang.org/x/mod dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8e6a7ea63..7cb63cf53 100644 --- a/go.mod +++ b/go.mod @@ -78,7 +78,7 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1 go.uber.org/goleak v1.3.0 - golang.org/x/mod v0.20.0 + golang.org/x/mod v0.21.0 golang.org/x/net v0.28.0 gopkg.in/yaml.v3 v3.0.1 modernc.org/sqlite v1.32.0 diff --git a/go.sum b/go.sum index 0cc5381b2..d3dc4b7d9 100644 --- a/go.sum +++ b/go.sum @@ -908,8 +908,8 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= -golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= From deabd4115a091e6d411e31b910e45e2309562b09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:06:23 -0400 Subject: [PATCH 184/284] chore(deps): bump peter-evans/create-pull-request from 7.0.0 to 7.0.1 (#3196) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.0 to 7.0.1. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/4320041ed380b20e97d388d56a7fb4f9b8c20e79...8867c4aba1b742c39f8d0ba35429c2dfa4b6cb20) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-bootstrap-tools.yml | 2 +- .github/workflows/update-cpe-dictionary-index.yml | 2 +- .github/workflows/update-stereoscope-release.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/update-bootstrap-tools.yml b/.github/workflows/update-bootstrap-tools.yml index 488a2cf5b..b07ad4580 100644 --- a/.github/workflows/update-bootstrap-tools.yml +++ b/.github/workflows/update-bootstrap-tools.yml @@ -50,7 +50,7 @@ jobs: app_id: ${{ secrets.TOKEN_APP_ID }} private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@4320041ed380b20e97d388d56a7fb4f9b8c20e79 #v7.0.0 + - uses: peter-evans/create-pull-request@8867c4aba1b742c39f8d0ba35429c2dfa4b6cb20 #v7.0.1 with: signoff: true delete-branch: true diff --git a/.github/workflows/update-cpe-dictionary-index.yml b/.github/workflows/update-cpe-dictionary-index.yml index 879298e06..cec2d9399 100644 --- a/.github/workflows/update-cpe-dictionary-index.yml +++ b/.github/workflows/update-cpe-dictionary-index.yml @@ -33,7 +33,7 @@ jobs: app_id: ${{ secrets.TOKEN_APP_ID }} private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@4320041ed380b20e97d388d56a7fb4f9b8c20e79 #v7.0.0 + - uses: peter-evans/create-pull-request@8867c4aba1b742c39f8d0ba35429c2dfa4b6cb20 #v7.0.1 with: signoff: true delete-branch: true diff --git a/.github/workflows/update-stereoscope-release.yml b/.github/workflows/update-stereoscope-release.yml index 411422611..1a3e22623 100644 --- a/.github/workflows/update-stereoscope-release.yml +++ b/.github/workflows/update-stereoscope-release.yml @@ -44,7 +44,7 @@ jobs: app_id: ${{ secrets.TOKEN_APP_ID }} private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@4320041ed380b20e97d388d56a7fb4f9b8c20e79 #v7.0.0 + - uses: peter-evans/create-pull-request@8867c4aba1b742c39f8d0ba35429c2dfa4b6cb20 #v7.0.1 with: signoff: true delete-branch: true From 0a3f513f923932d990bb9567339d9a0e142b0d36 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Mon, 9 Sep 2024 11:15:13 -0400 Subject: [PATCH 185/284] Slim down docker cache size (#3190) * slim down docker cache size Signed-off-by: Alex Goodman * remove old centos images Signed-off-by: Alex Goodman * troubleshoot test failure Signed-off-by: Alex Goodman * fix wget version ref Signed-off-by: Alex Goodman * refactor caching mechanisms Signed-off-by: Alex Goodman * add cache cleanup steps Signed-off-by: Alex Goodman * simplify deleting cache Signed-off-by: Alex Goodman * fix first clone issue Signed-off-by: Alex Goodman * add tool dep Signed-off-by: Alex Goodman --------- Signed-off-by: Alex Goodman --- .binny.yaml | 16 + .github/actions/bootstrap/action.yaml | 23 +- .github/scripts/ci-check.sh | 11 - .github/scripts/find_cache_paths.py | 135 +++++++++ .../scripts/fingerprint_docker_fixtures.py | 70 +++++ .github/scripts/labeler.py | 2 + .github/scripts/labeler_test.py | 2 + .github/workflows/release-version-file.yaml | 2 +- .../workflows/test-fixture-cache-publish.yaml | 39 +++ .github/workflows/update-bootstrap-tools.yml | 1 - .github/workflows/validations.yaml | 93 ++---- Makefile | 4 +- Taskfile.yaml | 280 ++++++++++++++---- cmd/syft/internal/test/integration/.gitignore | 1 + .../all_layers_squashed_comparison_test.go | 2 +- .../integration/encode_decode_cycle_test.go | 62 ++-- .../integration/go_compiler_detection_test.go | 4 +- .../test/integration/java_purl_test.go | 13 +- .../integration/package_deduplication_test.go | 76 +++-- .../test/integration/test-fixtures/Makefile | 25 +- .../image-golang-compiler/Dockerfile | 7 +- .../image-java-no-main-package/Dockerfile | 8 +- .../Dockerfile | 10 +- .../extract.py | 69 +++++ .../image-large-apk-data/Dockerfile | 7 +- .../image-mariner-distroless/Dockerfile | 9 +- .../image-owning-package/Dockerfile | 7 +- .../image-photon-all-layers/Dockerfile | 6 +- .../image-sqlite-rpmdb/Dockerfile | 7 +- .../image-suse-all-layers/Dockerfile | 11 +- .../image-test-java-purls/Dockerfile | 19 +- .../image-test-java-purls/extract.py | 69 +++++ .../image-vertical-package-dups/Dockerfile | 29 +- go.mod | 1 + go.sum | 2 + internal/task/executor.go | 2 +- .../executable/test-fixtures/Makefile | 15 + .../executable/test-fixtures/elf/Makefile | 25 +- .../test-fixtures/shared-info/Makefile | 28 +- .../test-fixtures/image-simple/Dockerfile | 4 - .../test-fixtures/image-simple/file-1.txt | 1 - .../test-fixtures/image-simple/file-2.txt | 1 - .../snapshot/TestTextImageEncoder.golden | 4 +- .../cataloger/binary/test-fixtures/.gitignore | 1 - .../cataloger/binary/test-fixtures/Makefile | 31 +- .../traefik/3.0.4/linux-riscv64/traefik | Bin 0 -> 352 bytes .../binary/test-fixtures/config.yaml | 1 + .../elf-test-fixtures/Dockerfile | 19 +- .../image-fedora-32bit/Dockerfile | 2 +- .../image-fedora-64bit/Dockerfile | 2 +- .../internal/config/binary_from_image.go | 8 +- .../internal/config/binary_from_image_test.go | 6 +- .../manager/internal/download_from_image.go | 48 ++- .../internal/download_from_image_test.go | 30 +- .../manager/internal/list_entries.go | 2 +- syft/pkg/cataloger/gentoo/cataloger_test.go | 2 +- .../pkg/app-containers/skopeo-1.5.1/CONTENTS | 0 .../pkg/app-containers/skopeo-1.5.1/LICENSE | 0 .../db/pkg/app-containers/skopeo-1.5.1/SIZE | 0 .../cataloger/golang/test-fixtures/Makefile | 15 + .../golang/test-fixtures/archs/Makefile | 32 +- .../golang/test-fixtures/archs/src/build.sh | 5 +- .../pkg/cataloger/java/test-fixtures/Makefile | 15 + .../java/test-fixtures/jar-metadata/Makefile | 50 +++- .../java/test-fixtures/java-builds/Makefile | 29 +- .../cataloger/kernel/test-fixtures/Makefile | 26 +- .../image-multi-site-package/Dockerfile | 19 +- .../cataloger/redhat/test-fixtures/Makefile | 39 ++- .../test-fixtures/image-minimal/Dockerfile | 6 +- test/cli/.gitignore | 1 + test/cli/cyclonedx_valid_test.go | 2 +- test/cli/scan_cmd_test.go | 50 +++- test/cli/test-fixtures/Makefile | 26 +- .../image-hidden-packages/Dockerfile | 8 +- test/install/Makefile | 13 +- 75 files changed, 1305 insertions(+), 385 deletions(-) delete mode 100755 .github/scripts/ci-check.sh create mode 100755 .github/scripts/find_cache_paths.py create mode 100755 .github/scripts/fingerprint_docker_fixtures.py mode change 100644 => 100755 .github/scripts/labeler.py mode change 100644 => 100755 .github/scripts/labeler_test.py create mode 100644 .github/workflows/test-fixture-cache-publish.yaml create mode 100644 cmd/syft/internal/test/integration/.gitignore create mode 100644 cmd/syft/internal/test/integration/test-fixtures/image-java-virtualpath-regression/extract.py create mode 100644 cmd/syft/internal/test/integration/test-fixtures/image-test-java-purls/extract.py create mode 100644 syft/file/cataloger/executable/test-fixtures/Makefile delete mode 100644 syft/format/text/test-fixtures/image-simple/Dockerfile delete mode 100644 syft/format/text/test-fixtures/image-simple/file-1.txt delete mode 100644 syft/format/text/test-fixtures/image-simple/file-2.txt create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/traefik/3.0.4/linux-riscv64/traefik rename syft/pkg/cataloger/gentoo/test-fixtures/{image-portage => layout}/var/db/pkg/app-containers/skopeo-1.5.1/CONTENTS (100%) rename syft/pkg/cataloger/gentoo/test-fixtures/{image-portage => layout}/var/db/pkg/app-containers/skopeo-1.5.1/LICENSE (100%) rename syft/pkg/cataloger/gentoo/test-fixtures/{image-portage => layout}/var/db/pkg/app-containers/skopeo-1.5.1/SIZE (100%) create mode 100644 syft/pkg/cataloger/golang/test-fixtures/Makefile create mode 100644 syft/pkg/cataloger/java/test-fixtures/Makefile create mode 100644 test/cli/.gitignore diff --git a/.binny.yaml b/.binny.yaml index a9a374393..cab909d29 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -115,3 +115,19 @@ tools: method: github-release with: repo: cli/cli + + # used to upload test fixture cache + - name: oras + version: + want: v1.2.0 + method: github-release + with: + repo: oras-project/oras + + # used to upload test fixture cache + - name: yq + version: + want: v4.44.3 + method: github-release + with: + repo: mikefarah/yq \ No newline at end of file diff --git a/.github/actions/bootstrap/action.yaml b/.github/actions/bootstrap/action.yaml index bc771d3b5..6150113ae 100644 --- a/.github/actions/bootstrap/action.yaml +++ b/.github/actions/bootstrap/action.yaml @@ -13,16 +13,15 @@ inputs: cache-key-prefix: description: "Prefix all cache keys with this value" required: true - default: "1ac8281053" - compute-fingerprints: - description: "Compute test fixture fingerprints" + default: "181053ac82" + download-test-fixture-cache: + description: "Download test fixture cache from OCI and github actions" required: true - default: "true" + default: "false" bootstrap-apt-packages: description: "Space delimited list of tools to install via apt" default: "libxml2-utils" - runs: using: "composite" steps: @@ -54,8 +53,14 @@ runs: run: | DEBIAN_FRONTEND=noninteractive sudo apt update && sudo -E apt install -y ${{ inputs.bootstrap-apt-packages }} - - name: Create all cache fingerprints - if: inputs.compute-fingerprints == 'true' - shell: bash - run: make fingerprints + - name: Restore ORAS cache from github actions + if: inputs.download-test-fixture-cache == 'true' + uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + with: + path: ${{ github.workspace }}/.tmp/oras-cache + key: ${{ inputs.cache-key-prefix }}-oras-cache + - name: Download test fixture cache + if: inputs.download-test-fixture-cache == 'true' + shell: bash + run: make download-test-fixture-cache diff --git a/.github/scripts/ci-check.sh b/.github/scripts/ci-check.sh deleted file mode 100755 index 0ab83a318..000000000 --- a/.github/scripts/ci-check.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -red=$(tput setaf 1) -bold=$(tput bold) -normal=$(tput sgr0) - -# assert we are running in CI (or die!) -if [[ -z "$CI" ]]; then - echo "${bold}${red}This step should ONLY be run in CI. Exiting...${normal}" - exit 1 -fi diff --git a/.github/scripts/find_cache_paths.py b/.github/scripts/find_cache_paths.py new file mode 100755 index 000000000..cc2e4081a --- /dev/null +++ b/.github/scripts/find_cache_paths.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import os +import glob +import sys +import json +import hashlib + + +IGNORED_PREFIXES = [] + + +def find_fingerprints_and_check_dirs(base_dir): + all_fingerprints = set(glob.glob(os.path.join(base_dir, '**', 'test*', '**', '*.fingerprint'), recursive=True)) + + all_fingerprints = {os.path.relpath(fp) for fp in all_fingerprints + if not any(fp.startswith(prefix) for prefix in IGNORED_PREFIXES)} + + if not all_fingerprints: + show("No .fingerprint files or cache directories found.") + exit(1) + + missing_content = [] + valid_paths = set() + fingerprint_contents = [] + + for fingerprint in all_fingerprints: + path = fingerprint.replace('.fingerprint', '') + + if not os.path.exists(path): + missing_content.append(path) + continue + + if not os.path.isdir(path): + valid_paths.add(path) + continue + + if os.listdir(path): + valid_paths.add(path) + else: + missing_content.append(path) + + with open(fingerprint, 'r') as f: + content = f.read().strip() + fingerprint_contents.append((fingerprint, content)) + + return sorted(valid_paths), missing_content, fingerprint_contents + + +def parse_fingerprint_contents(fingerprint_content): + input_map = {} + for line in fingerprint_content.splitlines(): + digest, path = line.split() + input_map[path] = digest + return input_map + + +def calculate_sha256(fingerprint_contents): + sorted_fingerprint_contents = sorted(fingerprint_contents, key=lambda x: x[0]) + + concatenated_contents = ''.join(content for _, content in sorted_fingerprint_contents) + + sha256_hash = hashlib.sha256(concatenated_contents.encode()).hexdigest() + + return sha256_hash + + +def calculate_file_sha256(file_path): + sha256_hash = hashlib.sha256() + with open(file_path, 'rb') as f: + for byte_block in iter(lambda: f.read(4096), b""): + sha256_hash.update(byte_block) + return sha256_hash.hexdigest() + + +def show(*s: str): + print(*s, file=sys.stderr) + + +def main(file_path: str | None): + base_dir = '.' + valid_paths, missing_content, fingerprint_contents = find_fingerprints_and_check_dirs(base_dir) + + if missing_content: + show("The following paths are missing or have no content, but have corresponding .fingerprint files:") + for path in sorted(missing_content): + show(f"- {path}") + show("Please ensure these paths exist and have content if they are directories.") + exit(1) + + sha256_hash = calculate_sha256(fingerprint_contents) + + paths_with_digests = [] + for path in sorted(valid_paths): + fingerprint_file = f"{path}.fingerprint" + try: + if os.path.exists(fingerprint_file): + file_digest = calculate_file_sha256(fingerprint_file) + + # Parse the fingerprint file to get the digest/path tuples + with open(fingerprint_file, 'r') as f: + fingerprint_content = f.read().strip() + input_map = parse_fingerprint_contents(fingerprint_content) + + paths_with_digests.append({ + "path": path, + "digest": file_digest, + "input": input_map + }) + + except Exception as e: + show(f"Error processing {fingerprint_file}: {e}") + raise e + + + output = { + "digest": sha256_hash, + "paths": paths_with_digests + } + + content = json.dumps(output, indent=2, sort_keys=True) + + if file_path: + with open(file_path, 'w') as f: + f.write(content) + + print(content) + + +if __name__ == "__main__": + file_path = None + if len(sys.argv) > 1: + file_path = sys.argv[1] + main(file_path) diff --git a/.github/scripts/fingerprint_docker_fixtures.py b/.github/scripts/fingerprint_docker_fixtures.py new file mode 100755 index 000000000..4a74420e0 --- /dev/null +++ b/.github/scripts/fingerprint_docker_fixtures.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 + +import os +import subprocess +import hashlib + +BOLD = '\033[1m' +YELLOW = '\033[0;33m' +RESET = '\033[0m' + + +def print_message(message): + print(f"{YELLOW}{message}{RESET}") + + +def sha256sum(filepath): + h = hashlib.sha256() + with open(filepath, 'rb') as f: + for chunk in iter(lambda: f.read(4096), b""): + h.update(chunk) + return h.hexdigest() + + +def is_git_tracked_or_untracked(directory): + """Returns a sorted list of files in the directory that are tracked or not ignored by Git.""" + result = subprocess.run( + ["git", "ls-files", "--cached", "--others", "--exclude-standard"], + cwd=directory, + stdout=subprocess.PIPE, + text=True + ) + return sorted(result.stdout.strip().splitlines()) + + +def find_test_fixture_dirs_with_images(base_dir): + """Find directories that contain 'test-fixtures' and at least one 'image-*' directory.""" + for root, dirs, files in os.walk(base_dir): + if 'test-fixtures' in root: + image_dirs = [d for d in dirs if d.startswith('image-')] + if image_dirs: + yield os.path.realpath(root) + + +def generate_fingerprints(): + print_message("creating fingerprint files for docker fixtures...") + + for test_fixture_dir in find_test_fixture_dirs_with_images('.'): + cache_fingerprint_path = os.path.join(test_fixture_dir, 'cache.fingerprint') + + with open(cache_fingerprint_path, 'w') as fingerprint_file: + for image_dir in find_image_dirs(test_fixture_dir): + for file in is_git_tracked_or_untracked(image_dir): + file_path = os.path.join(image_dir, file) + checksum = sha256sum(file_path) + path_from_fixture_dir = os.path.relpath(file_path, test_fixture_dir) + fingerprint_file.write(f"{checksum} {path_from_fixture_dir}\n") + + +def find_image_dirs(test_fixture_dir): + """Find all 'image-*' directories inside a given test-fixture directory.""" + result = [] + for root, dirs, files in os.walk(test_fixture_dir): + for dir_name in dirs: + if dir_name.startswith('image-'): + result.append(os.path.join(root, dir_name)) + return sorted(result) + + +if __name__ == "__main__": + generate_fingerprints() diff --git a/.github/scripts/labeler.py b/.github/scripts/labeler.py old mode 100644 new mode 100755 index b33dd6df0..2efd33206 --- a/.github/scripts/labeler.py +++ b/.github/scripts/labeler.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + from __future__ import annotations import sys diff --git a/.github/scripts/labeler_test.py b/.github/scripts/labeler_test.py old mode 100644 new mode 100755 index 36eebd18c..d792929f1 --- a/.github/scripts/labeler_test.py +++ b/.github/scripts/labeler_test.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + import unittest from unittest.mock import patch import subprocess diff --git a/.github/workflows/release-version-file.yaml b/.github/workflows/release-version-file.yaml index cd41a0c8e..6635a053f 100644 --- a/.github/workflows/release-version-file.yaml +++ b/.github/workflows/release-version-file.yaml @@ -1,4 +1,4 @@ -name: "Release" +name: "Release: version file" on: diff --git a/.github/workflows/test-fixture-cache-publish.yaml b/.github/workflows/test-fixture-cache-publish.yaml new file mode 100644 index 000000000..3144a0b6b --- /dev/null +++ b/.github/workflows/test-fixture-cache-publish.yaml @@ -0,0 +1,39 @@ +name: "Test fixture cache: publish" + +on: + workflow_dispatch: + schedule: + # run nightly at 4AM UTC + - cron: "0 4 * * *" + +permissions: + contents: read + +jobs: + + Publish: + name: "Publish test fixture image cache" + # we use this runner to get enough storage space for docker images and fixture cache + runs-on: ubuntu-22.04-4core-16gb + permissions: + packages: write + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + + - name: Bootstrap environment + uses: ./.github/actions/bootstrap + with: + # we want to rebuild the cache with no previous state + download-test-fixture-cache: false + + - name: Run all tests + run: make test + env: + # we want to rebuild the cache with no previous state + DOWNLOAD_TEST_FIXTURE_CACHE: "false" + + - name: Login to GitHub Container Registry (ORAS) + run: echo "${{ secrets.GITHUB_TOKEN }}" | .tool/oras login ghcr.io -u ${{ github.actor }} --password-stdin + + - name: Publish test fixture cache + run: make upload-test-fixture-cache diff --git a/.github/workflows/update-bootstrap-tools.yml b/.github/workflows/update-bootstrap-tools.yml index b07ad4580..3cdedf52a 100644 --- a/.github/workflows/update-bootstrap-tools.yml +++ b/.github/workflows/update-bootstrap-tools.yml @@ -19,7 +19,6 @@ jobs: uses: ./.github/actions/bootstrap with: bootstrap-apt-packages: "" - compute-fingerprints: "false" go-dependencies: false - name: "Update tool versions" diff --git a/.github/workflows/validations.yaml b/.github/workflows/validations.yaml index 669d8b8c5..0ebca5c82 100644 --- a/.github/workflows/validations.yaml +++ b/.github/workflows/validations.yaml @@ -35,48 +35,8 @@ jobs: - name: Bootstrap environment uses: ./.github/actions/bootstrap - - - name: Restore file executable test-fixture cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2 - with: - path: syft/file/cataloger/executable/test-fixtures/elf/bin - key: ${{ runner.os }}-unit-file-executable-elf-cache-${{ hashFiles( 'syft/file/cataloger/executable/test-fixtures/elf/cache.fingerprint' ) }} - - - name: Restore file executable shared-info test-fixture cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2 - with: - path: syft/file/cataloger/executable/test-fixtures/shared-info/bin - key: ${{ runner.os }}-unit-file-executable-shared-info-cache-${{ hashFiles( 'syft/file/cataloger/executable/test-fixtures/shared-info/cache.fingerprint' ) }} - - - name: Restore Java test-fixture cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2 - with: - path: syft/pkg/cataloger/java/test-fixtures/java-builds/packages - key: ${{ runner.os }}-unit-java-cache-${{ hashFiles( 'syft/pkg/cataloger/java/test-fixtures/java-builds/cache.fingerprint' ) }} - - - name: Restore RPM test-fixture cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2 with: - path: syft/pkg/cataloger/redhat/test-fixtures/rpms - key: ${{ runner.os }}-unit-rpm-cache-${{ hashFiles( 'syft/pkg/cataloger/redhat/test-fixtures/rpms.fingerprint' ) }} - - - name: Restore go binary test-fixture cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2 - with: - path: syft/pkg/cataloger/golang/test-fixtures/archs/binaries - key: ${{ runner.os }}-unit-go-binaries-cache-${{ hashFiles( 'syft/pkg/cataloger/golang/test-fixtures/archs/binaries.fingerprint' ) }} - - - name: Restore binary cataloger test-fixture cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2 - with: - path: syft/pkg/cataloger/binary/test-fixtures/classifiers/bin - key: ${{ runner.os }}-unit-binary-cataloger-cache-${{ hashFiles( 'syft/pkg/cataloger/binary/test-fixtures/cache.fingerprint' ) }} - - - name: Restore Kernel test-fixture cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2 - with: - path: syft/pkg/cataloger/kernel/test-fixtures/cache - key: ${{ runner.os }}-unit-kernel-cache-${{ hashFiles( 'syft/pkg/cataloger/kernel/test-fixtures/cache.fingerprint' ) }} + download-test-fixture-cache: true - name: Run unit tests run: make unit @@ -91,16 +51,12 @@ jobs: - name: Bootstrap environment uses: ./.github/actions/bootstrap + with: + download-test-fixture-cache: true - name: Validate syft output against the CycloneDX schema run: make validate-cyclonedx-schema - - name: Restore integration test cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2 - with: - path: ${{ github.workspace }}/cmd/syft/internal/test/integration/test-fixtures/cache - key: ${{ runner.os }}-integration-test-cache-${{ hashFiles('/cmd/syft/internal/test/integration/test-fixtures/cache.fingerprint') }} - - name: Run integration tests run: make integration @@ -143,6 +99,8 @@ jobs: - name: Bootstrap environment uses: ./.github/actions/bootstrap + with: + download-test-fixture-cache: true - name: Download snapshot build id: snapshot-cache @@ -162,13 +120,6 @@ jobs: - name: Run comparison tests (Linux) run: make compare-linux - - name: Restore install.sh test image cache - id: install-test-image-cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2 - with: - path: ${{ github.workspace }}/test/install/cache - key: ${{ runner.os }}-install-test-image-cache-${{ hashFiles('test/install/cache.fingerprint') }} - - name: Load test image cache if: steps.install-test-image-cache.outputs.cache-hit == 'true' run: make install-test-cache-load @@ -196,8 +147,8 @@ jobs: uses: ./.github/actions/bootstrap with: bootstrap-apt-packages: "" - compute-fingerprints: "false" go-dependencies: false + download-test-fixture-cache: true - name: Download snapshot build id: snapshot-cache @@ -214,13 +165,6 @@ jobs: if: steps.snapshot-cache.outputs.cache-hit != 'true' run: echo "unable to download snapshots from previous job" && false - - name: Restore docker image cache for compare testing - id: mac-compare-testing-cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2 - with: - path: image.tar - key: ${{ runner.os }}-${{ hashFiles('test/compare/mac.sh') }} - - name: Run comparison tests (Mac) run: make compare-mac @@ -238,12 +182,8 @@ jobs: - name: Bootstrap environment uses: ./.github/actions/bootstrap - - - name: Restore CLI test-fixture cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2 with: - path: ${{ github.workspace }}/test/cli/test-fixtures/cache - key: ${{ runner.os }}-cli-test-cache-${{ hashFiles('test/cli/test-fixtures/cache.fingerprint') }} + download-test-fixture-cache: true - name: Download snapshot build id: snapshot-cache @@ -262,3 +202,22 @@ jobs: - name: Run CLI Tests (Linux) run: make cli + + + Cleanup-Cache: + name: "Cleanup snapshot cache" + if: always() + runs-on: ubuntu-20.04 + permissions: + actions: write + needs: + - Acceptance-Linux + - Acceptance-Mac + - Cli-Linux + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + + - name: Delete snapshot cache + run: gh cache delete "snapshot-build-${{ github.run_id }}" + env: + GH_TOKEN: ${{ github.token }} diff --git a/Makefile b/Makefile index 9089ee619..2f1ae1f8e 100644 --- a/Makefile +++ b/Makefile @@ -25,8 +25,8 @@ ci-bootstrap-go: # this is a bootstrapping catch-all, where if the target doesn't exist, we'll ensure the tools are installed and then try again %: - make $(TASK) - $(TASK) $@ + @make --silent $(TASK) + @$(TASK) $@ ## Shim targets ################################# diff --git a/Taskfile.yaml b/Taskfile.yaml index c0a8bc334..feb12f636 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -4,9 +4,19 @@ vars: OWNER: anchore PROJECT: syft + CACHE_IMAGE: ghcr.io/{{ .OWNER }}/{{ .PROJECT }}/test-fixture-cache:latest + # static file dirs TOOL_DIR: .tool TMP_DIR: .tmp + ORAS_CACHE: "{{ .TMP_DIR }}/oras-cache" + CACHE_PATHS_FILE: "{{ .TMP_DIR }}/cache_paths.json" + LAST_CACHE_PULL_FILE: "{{ .TMP_DIR }}/last_cache_paths.json" + + # TOOLS + ORAS: "{{ .TOOL_DIR }}/oras" + YQ: "{{ .TOOL_DIR }}/yq" + TASK: "{{ .TOOL_DIR }}/task" # used for changelog generation CHANGELOG: CHANGELOG.md @@ -33,6 +43,9 @@ vars: COMPARE_DIR: ./test/compare COMPARE_TEST_IMAGE: centos:8.2.2004 +env: + GNUMAKEFLAGS: '--no-print-directory' + tasks: ## High-level tasks ################################# @@ -65,6 +78,7 @@ tasks: - task: benchmark - task: test-utils - task: cli + - task: check-docker-cache ## Bootstrap tasks ################################# @@ -212,10 +226,6 @@ tasks: # that the cache being restored with the correct binary will be rebuilt since the timestamps # and local checksums will not line up. deps: [tools, snapshot] - sources: - - "{{ .SNAPSHOT_BIN }}" - - ./test/cli/** - - ./**/*.go cmds: - cmd: "echo 'testing binary: {{ .SNAPSHOT_BIN }}'" silent: true @@ -229,18 +239,14 @@ tasks: test-utils: desc: Run tests for pipeline utils - sources: - - .github/scripts/labeler*.py cmds: - - cmd: python .github/scripts/labeler_test.py + - cmd: .github/scripts/labeler_test.py ## Benchmark test targets ################################# benchmark: deps: [tmpdir] - sources: - - ./**/*.go generates: - "{{ .TMP_DIR }}/benchmark-main.txt" cmds: @@ -253,8 +259,6 @@ tasks: show-benchstat: deps: [benchmark, tmpdir] - sources: - - "{{ .TMP_DIR }}/benchstat.txt" cmds: - cmd: "cat {{ .TMP_DIR }}/benchstat.txt" silent: true @@ -263,56 +267,188 @@ tasks: ## Test-fixture-related targets ################################# fingerprints: - desc: Generate test fixture fingerprints + desc: Generate fingerprints for all non-docker test fixture + silent: true + # this will look for `test-fixtures/Makefile` and invoke the `fingerprint` target to calculate all cache input fingerprint files generates: - - cmd/syft/internal/test/integration/test-fixtures/cache.fingerprint - - syft/file/cataloger/executable/test-fixtures/elf/cache.fingerprint - - syft/file/cataloger/executable/test-fixtures/shared-info/cache.fingerprint - - syft/pkg/cataloger/binary/test-fixtures/cache.fingerprint - - syft/pkg/cataloger/java/test-fixtures/java-builds/cache.fingerprint - - syft/pkg/cataloger/golang/test-fixtures/archs/binaries.fingerprint - - syft/pkg/cataloger/redhat/test-fixtures/rpms.fingerprint - - syft/pkg/cataloger/kernel/test-fixtures/cache.fingerprint + - '**/test-fixtures/**/*.fingerprint' - test/install/cache.fingerprint - - test/cli/test-fixtures/cache.fingerprint - cmds: - # for EXECUTABLE unit test fixtures - - "cd syft/file/cataloger/executable/test-fixtures/elf && make cache.fingerprint" - - "cd syft/file/cataloger/executable/test-fixtures/shared-info && make cache.fingerprint" - # for IMAGE integration test fixtures - - "cd cmd/syft/internal/test/integration/test-fixtures && make cache.fingerprint" - # for BINARY unit test fixtures - - "cd syft/pkg/cataloger/binary/test-fixtures && make cache.fingerprint" - # for JAVA BUILD unit test fixtures - - "cd syft/pkg/cataloger/java/test-fixtures/java-builds && make cache.fingerprint" - # for GO BINARY unit test fixtures - - "cd syft/pkg/cataloger/golang/test-fixtures/archs && make binaries.fingerprint" - # for RPM unit test fixtures - - "cd syft/pkg/cataloger/redhat/test-fixtures && make rpms.fingerprint" - # for Kernel unit test fixtures - - "cd syft/pkg/cataloger/kernel/test-fixtures && make cache.fingerprint" - # for INSTALL test fixtures - - "cd test/install && make cache.fingerprint" - # for CLI test fixtures - - "cd test/cli/test-fixtures && make cache.fingerprint" - - fixtures: - desc: Generate test fixtures - cmds: - - "cd syft/file/cataloger/executable/test-fixtures/elf && make" - - "cd syft/file/cataloger/executable/test-fixtures/shared-info && make" - - "cd syft/pkg/cataloger/java/test-fixtures/java-builds && make" - - "cd syft/pkg/cataloger/redhat/test-fixtures && make" - - "cd syft/pkg/cataloger/binary/test-fixtures && make" + cmds: + - | + BOLD='\033[1m' + YELLOW='\033[0;33m' + RESET='\033[0m' + + echo -e "${YELLOW}creating fingerprint files for non-docker fixtures...${RESET}" + for dir in $(find . -type d -name 'test-fixtures'); do + if [ -f "$dir/Makefile" ]; then + # for debugging... + #echo -e "${YELLOW}â€ĸ calculating fingerprints in $dir... ${RESET}" + + (make -C "$dir" fingerprint) + fi + done + + # for debugging... + # echo -e "generated all fixture fingerprints" + + - .github/scripts/fingerprint_docker_fixtures.py + - | + # if DOWNLOAD_TEST_FIXTURE_CACHE is set to 'false', then we don't need to calculate the fingerprint for the cache + if [ "$DOWNLOAD_TEST_FIXTURE_CACHE" = "false" ]; then + exit 0 + fi + .github/scripts/find_cache_paths.py {{ .CACHE_PATHS_FILE }} > /dev/null + + + refresh-fixtures: + desc: Clear and fetch all test fixture cache + aliases: + - fixtures + silent: true + deps: + - tools + cmds: + - | + BOLD='\033[1m' + PURPLE='\033[0;35m' + RESET='\033[0m' + + # if DOWNLOAD_TEST_FIXTURE_CACHE is set to 'false', then skip the cache download and always build + if [ "$DOWNLOAD_TEST_FIXTURE_CACHE" = "false" ]; then + echo -e "${BOLD}${PURPLE}skipping cache download, rebuilding cache...${RESET}" + {{ .TASK }} build-fixtures + exit 0 + fi + + LATEST_FINGERPRINT=$(docker manifest inspect {{ .CACHE_IMAGE }} | {{ .YQ }} -r '.annotations.fingerprint') + + echo "latest cache: $LATEST_FINGERPRINT" + + if [ -f {{ .LAST_CACHE_PULL_FILE }} ]; then + LAST_PULL_FINGERPRINT=$(cat {{ .LAST_CACHE_PULL_FILE }} | {{ .YQ }} -r '.digest') + else + echo -e "${BOLD}${PURPLE}empty cache, downloading cache...${RESET}" + {{ .TASK }} download-test-fixture-cache + exit 0 + fi + + {{ .TASK }} fingerprints + + WANT_FINGERPRINT=$(cat {{ .CACHE_PATHS_FILE }} | {{ .YQ }} -r '.digest') + + echo "desired cache: $WANT_FINGERPRINT" + echo "last pulled cache: $LAST_PULL_FINGERPRINT" + + # if we already have the latest cache, skip the refresh + if [ "$LAST_PULL_FINGERPRINT" = "$WANT_FINGERPRINT" ]; then + echo -e "${BOLD}${PURPLE}already have the latest cache (skipping cache download)${RESET}" + exit 0 + fi + + # at this point we only refresh the cache if we want the same cache that is currently available. + # we don't by default refresh the cache if the cache if it is simply different from what we have, + # because we may be working on a code change that doesn't require a cache refresh (but could trigger one, + # which would be annoying to deal with in a development workflow). + + if [ "$LATEST_FINGERPRINT" = "$WANT_FINGERPRINT" ]; then + echo -e "${BOLD}${PURPLE}found newer cache! downloading cache...${RESET}" + {{ .TASK }} download-test-fixture-cache + else + echo -e "${BOLD}${PURPLE}found different cache, but isn't clear if it's newer (skipping cache download and manually building)${RESET}" + + {{ .YQ }} eval '.paths[] | "\(.digest) \(.path)"' {{ .LAST_CACHE_PULL_FILE }} > .tmp/last_cache_lines + {{ .YQ }} eval '.paths[] | "\(.digest) \(.path)"' {{ .CACHE_PATHS_FILE }} > .tmp/cache_lines + diff .tmp/last_cache_lines .tmp/cache_lines || true + + echo -e "${BOLD}${PURPLE}diff with more context...${RESET}" + + diff -U10000 {{ .LAST_CACHE_PULL_FILE }} {{ .CACHE_PATHS_FILE }} || true + + echo -e "${BOLD}${PURPLE}detected changes to input material, manually building fixtures...${RESET}" + + {{ .TASK }} build-fixtures + fi + + build-fixtures: + desc: Generate all non-docker test fixtures + silent: true + # this will look for `test-fixtures/Makefile` and invoke the `fixtures` target to generate any and all test fixtures + cmds: + - | + BOLD='\033[1m' + YELLOW='\033[0;33m' + RESET='\033[0m' + + # Use a for loop with command substitution to avoid subshell issues + for dir in $(find . -type d -name 'test-fixtures'); do + if [ -f "$dir/Makefile" ]; then + echo -e "${YELLOW}${BOLD}generating fixtures in $dir${RESET}" + (make -C "$dir" fixtures) + fi + done + echo -e "${BOLD}generated all fixtures${RESET}" + + download-test-fixture-cache: + desc: Download test fixture cache from ghcr.io + deps: [tools, clean-cache] + vars: + CACHE_DIGEST: + sh: docker manifest inspect {{ .CACHE_IMAGE }} | {{ .YQ }} -r '.annotations.fingerprint' + cmds: + - silent: true + cmd: | + # if oras cache is > 4 GB, delete it + if [ -d {{ .ORAS_CACHE }} ]; then + total_size=$(du -c {{ .ORAS_CACHE }} | grep total | awk '{print $1}') + if [ "$total_size" -gt 4194304 ]; then + echo 'deleting oras cache' + rm -rf {{ .ORAS_CACHE }} + fi + fi + - "ORAS_CACHE={{ .ORAS_CACHE }} {{ .ORAS }} pull {{ .CACHE_IMAGE }}" + - "cp {{ .CACHE_PATHS_FILE }} {{ .LAST_CACHE_PULL_FILE }}" + + upload-test-fixture-cache: + desc: Upload the test fixture cache to ghcr.io + deps: [tools, fingerprints] + silent: true + cmd: | + set -eu + oras_command="{{ .ORAS }} push {{ .CACHE_IMAGE }}" + + paths=$(cat {{ .CACHE_PATHS_FILE }} | {{ .YQ }} -r '.paths[].path') + for path in $paths; do + oras_command+=" $path" + done + oras_command+=" {{ .CACHE_PATHS_FILE }}" + + oras_command+=" --annotation org.opencontainers.image.source=https://github.com/{{ .OWNER }}/{{ .PROJECT }}" + oras_command+=" --annotation fingerprint=$(cat {{ .CACHE_PATHS_FILE }} | {{ .YQ }} -r '.digest')" + + echo "Executing: $oras_command" + eval $oras_command show-test-image-cache: silent: true cmds: - - "echo '\nDocker daemon cache:'" + - "echo 'Docker daemon cache:'" - "docker images --format '{{`{{.ID}}`}} {{`{{.Repository}}`}}:{{`{{.Tag}}`}}' | grep stereoscope-fixture- | sort" - "echo '\nTar cache:'" - - 'find . -type f -wholename "**/test-fixtures/snapshot/*" | sort' + - 'find . -type f -wholename "**/test-fixtures/cache/stereoscope-fixture-*.tar" | sort' + check-docker-cache: + desc: Ensure docker caches aren't using too much disk space + silent: true + cmd: | + total_size=$(find . | grep cache | grep tar | xargs du -c | grep total | awk '{print $1}') + find . | grep cache | grep tar | xargs du + echo "total $total_size KB" + + if [ "$total_size" -gt 1048576 ]; then + echo 'docker cache is larger than 1GB' + exit 1 + fi ## install.sh testing targets ################################# @@ -457,7 +593,16 @@ tasks: ci-check: # desc: "[CI only] Are you in CI?" cmds: - - cmd: .github/scripts/ci-check.sh + - cmd: | + red=$(tput setaf 1) + bold=$(tput bold) + normal=$(tput sgr0) + + # assert we are running in CI (or die!) + if [[ -z "$CI" ]]; then + echo "${bold}${red}This step should ONLY be run in CI. Exiting...${normal}" + exit 1 + fi silent: true ci-release: @@ -489,8 +634,31 @@ tasks: - "rm -rf {{ .SNAPSHOT_DIR }}" - "rm -rf {{ .TMP_DIR }}/goreleaser.yaml" + clean-docker-cache: + desc: Remove all docker cache tars and images from the daemon + cmds: + - find . -type d -wholename "**/test-fixtures/cache" | xargs rm -rf + - docker images --format '{{`{{.ID}}`}} {{`{{.Repository}}`}}' | grep stereoscope-fixture- | awk '{print $1}' | uniq | xargs -r docker rmi --force + + clean-oras-cache: + desc: Remove all cache for oras commands + cmd: rm -rf {{ .ORAS_CACHE }} + clean-cache: - desc: Remove all docker cache and local image tar cache + desc: Remove all image docker tar cache, images from the docker daemon, and ephemeral test fixtures cmds: - - 'find . -type f -wholename "**/test-fixtures/cache/stereoscope-fixture-*.tar" -delete' - - "docker images --format '{{`{{.ID}}`}} {{`{{.Repository}}`}}' | grep stereoscope-fixture- | awk '{print $$1}' | uniq | xargs -r docker rmi --force" + - task: clean-docker-cache + - | + BOLD='\033[1m' + YELLOW='\033[0;33m' + RESET='\033[0m' + + # Use a for loop with command substitution to avoid subshell issues + for dir in $(find . -type d -name 'test-fixtures'); do + if [ -f "$dir/Makefile" ]; then + echo -e "${YELLOW}${BOLD}deleting ephemeral test fixtures in $dir${RESET}" + (make -C "$dir" clean) + fi + done + echo -e "${BOLD}Deleted all ephemeral test fixtures${RESET}" + - rm -f {{ .LAST_CACHE_PULL_FILE }} {{ .CACHE_PATHS_FILE }} diff --git a/cmd/syft/internal/test/integration/.gitignore b/cmd/syft/internal/test/integration/.gitignore new file mode 100644 index 000000000..872aa273a --- /dev/null +++ b/cmd/syft/internal/test/integration/.gitignore @@ -0,0 +1 @@ +results \ No newline at end of file diff --git a/cmd/syft/internal/test/integration/all_layers_squashed_comparison_test.go b/cmd/syft/internal/test/integration/all_layers_squashed_comparison_test.go index 4dedd9ef4..41f8e3502 100644 --- a/cmd/syft/internal/test/integration/all_layers_squashed_comparison_test.go +++ b/cmd/syft/internal/test/integration/all_layers_squashed_comparison_test.go @@ -7,7 +7,7 @@ import ( ) func Test_AllLayersIncludesSquashed(t *testing.T) { - // This is a verification test for issue #894 (https://github.com/anchore/syft/issues/894) + // This is a verification test for issue grype/#894 (https://github.com/anchore/grype/issues/894) allLayers, _ := catalogFixtureImage(t, "image-suse-all-layers", source.AllLayersScope) squashed, _ := catalogFixtureImage(t, "image-suse-all-layers", source.SquashedScope) diff --git a/cmd/syft/internal/test/integration/encode_decode_cycle_test.go b/cmd/syft/internal/test/integration/encode_decode_cycle_test.go index 56bd7b772..dd3a99a85 100644 --- a/cmd/syft/internal/test/integration/encode_decode_cycle_test.go +++ b/cmd/syft/internal/test/integration/encode_decode_cycle_test.go @@ -2,7 +2,9 @@ package integration import ( "bytes" - "regexp" + "os" + "path/filepath" + "strings" "testing" "github.com/google/go-cmp/cmp" @@ -12,8 +14,6 @@ import ( "github.com/anchore/syft/cmd/syft/internal/options" "github.com/anchore/syft/syft/format" - "github.com/anchore/syft/syft/format/cyclonedxjson" - "github.com/anchore/syft/syft/format/cyclonedxxml" "github.com/anchore/syft/syft/format/syftjson" "github.com/anchore/syft/syft/source" ) @@ -43,26 +43,27 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) { }, json: true, }, - { - name: cyclonedxjson.ID.String(), - redactor: func(in []byte) []byte { - // unstable values - in = regexp.MustCompile(`"(timestamp|serialNumber|bom-ref|ref)":\s*"(\n|[^"])+"`).ReplaceAll(in, []byte(`"$1": "redacted"`)) - in = regexp.MustCompile(`"(dependsOn)":\s*\[(?:\s|[^]])+]`).ReplaceAll(in, []byte(`"$1": []`)) - return in - }, - json: true, - }, - { - name: cyclonedxxml.ID.String(), - redactor: func(in []byte) []byte { - // unstable values - in = regexp.MustCompile(`(serialNumber|bom-ref|ref)="[^"]+"`).ReplaceAll(in, []byte{}) - in = regexp.MustCompile(`[^<]+`).ReplaceAll(in, []byte{}) - - return in - }, - }, + // TODO: ignoring the `ref` field though does create stable results to compare, but the SBOM is fundamentally gutted and not worth comparing (find a better redaction or compare method) + //{ + // name: cyclonedxjson.ID.String(), + // redactor: func(in []byte) []byte { + // // unstable values + // in = regexp.MustCompile(`"(timestamp|serialNumber|bom-ref|ref)":\s*"(\n|[^"])+"`).ReplaceAll(in, []byte(`"$1": "redacted"`)) + // in = regexp.MustCompile(`"(dependsOn)":\s*\[(?:\s|[^]])+]`).ReplaceAll(in, []byte(`"$1": []`)) + // return in + // }, + // json: true, + //}, + //{ + // name: cyclonedxxml.ID.String(), + // redactor: func(in []byte) []byte { + // // unstable values + // in = regexp.MustCompile(`(serialNumber|bom-ref|ref)="[^"]+"`).ReplaceAll(in, []byte{}) + // in = regexp.MustCompile(`[^<]+`).ReplaceAll(in, []byte{}) + // + // return in + // }, + //}, } opts := options.DefaultOutput() @@ -112,6 +113,21 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) { diffs := dmp.DiffMain(string(by1), string(by2), true) t.Errorf("diff: %s", dmp.DiffPrettyText(diffs)) } + + // write raw IMAGE@NAME-start and IMAGE@NAME-finish to files within the results dir + // ... this is helpful for debugging + require.NoError(t, os.MkdirAll("results", 0700)) + + suffix := "sbom" + switch { + case strings.Contains(test.name, "json"): + suffix = "json" + case strings.Contains(test.name, "xml"): + suffix = "xml" + } + + require.NoError(t, os.WriteFile(filepath.Join("results", image+"@"+test.name+"-start."+suffix), by1, 0600)) + require.NoError(t, os.WriteFile(filepath.Join("results", image+"@"+test.name+"-finish."+suffix), by2, 0600)) } }) } diff --git a/cmd/syft/internal/test/integration/go_compiler_detection_test.go b/cmd/syft/internal/test/integration/go_compiler_detection_test.go index 8c440a030..e6a0d5888 100644 --- a/cmd/syft/internal/test/integration/go_compiler_detection_test.go +++ b/cmd/syft/internal/test/integration/go_compiler_detection_test.go @@ -35,8 +35,8 @@ func TestGolangCompilerDetection(t *testing.T) { for _, pkg := range packages { foundCompilerVersions[pkg.Version] = struct{}{} foundPURL[pkg.PURL] = struct{}{} - for _, cpe := range pkg.CPEs { - foundCPE[cpe] = struct{}{} + for _, c := range pkg.CPEs { + foundCPE[c] = struct{}{} } } diff --git a/cmd/syft/internal/test/integration/java_purl_test.go b/cmd/syft/internal/test/integration/java_purl_test.go index 5dab545d6..5de8875ca 100644 --- a/cmd/syft/internal/test/integration/java_purl_test.go +++ b/cmd/syft/internal/test/integration/java_purl_test.go @@ -1,10 +1,9 @@ package integration import ( - "fmt" "testing" - "github.com/stretchr/testify/assert" + "github.com/google/go-cmp/cmp" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/source" @@ -26,13 +25,9 @@ func TestJavaPURLs(t *testing.T) { found[metadata.VirtualPath] = p.PURL } } - for key, expectedPURL := range expectedPURLs { - purl := found[key] - assert.Equal(t, expectedPURL, purl, fmt.Sprintf("found wrong or missing PURL for %s want %s, got %s", key, expectedPURL, purl)) - } - for key, foundPURL := range found { - expectedPURL := expectedPURLs[key] - assert.Equal(t, expectedPURL, foundPURL, fmt.Sprintf("found extra purl for %s want %s, got %s", key, expectedPURL, foundPURL)) + + if d := cmp.Diff(expectedPURLs, found); d != "" { + t.Errorf("unexpected purl values:\n%s", d) } } diff --git a/cmd/syft/internal/test/integration/package_deduplication_test.go b/cmd/syft/internal/test/integration/package_deduplication_test.go index 12fa9dcf2..ab8e580f8 100644 --- a/cmd/syft/internal/test/integration/package_deduplication_test.go +++ b/cmd/syft/internal/test/integration/package_deduplication_test.go @@ -1,5 +1,3 @@ -//go:build !arm64 - package integration import ( @@ -7,7 +5,6 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/source" @@ -22,41 +19,39 @@ func TestPackageDeduplication(t *testing.T) { }{ { scope: source.AllLayersScope, - packageCount: 172, // without deduplication this would be 618 + packageCount: 178, // without deduplication this would be ~600 instanceCount: map[string]int{ - "basesystem": 1, - "wget": 1, - "curl": 2, // upgraded in the image - "vsftpd": 1, - "httpd": 1, // rpm, - we exclude binary + "basesystem": 1, + "wget": 1, + "curl-minimal": 2, // upgraded in the image + "vsftpd": 1, + "httpd": 1, // rpm, - we exclude binary }, locationCount: map[string]int{ - "basesystem-10.0-7.el7.centos": 4, - "curl-7.29.0-59.el7": 1, // from base image - "curl-7.29.0-59.el7_9.1": 3, // upgrade - "wget-1.14-18.el7_6.1": 3, - "vsftpd-3.0.2-29.el7_9": 2, - "httpd-2.4.6-97.el7.centos.5": 1, - // "httpd-2.4.6": 1, // binary + "basesystem-11-13.el9": 5, // in all layers + "curl-minimal-7.76.1-26.el9_3.2.0.1": 2, // base + wget layer + "curl-minimal-7.76.1-29.el9_4.1": 3, // curl upgrade layer + all above layers + "wget-1.21.1-8.el9_4": 4, // wget + all above layers + "vsftpd-3.0.5-5.el9": 2, // vsftpd + all above layers + "httpd-2.4.57-11.el9_4.1": 1, // last layer }, }, { scope: source.SquashedScope, - packageCount: 170, + packageCount: 172, instanceCount: map[string]int{ - "basesystem": 1, - "wget": 1, - "curl": 1, // upgraded, but the most recent - "vsftpd": 1, - "httpd": 1, // rpm, binary is now excluded by overlap + "basesystem": 1, + "wget": 1, + "curl-minimal": 1, // upgraded, but the most recent + "vsftpd": 1, + "httpd": 1, // rpm, binary is now excluded by overlap }, locationCount: map[string]int{ - "basesystem-10.0-7.el7.centos": 1, - "curl-7.29.0-59.el7_9.1": 1, // upgrade - "wget-1.14-18.el7_6.1": 1, - "vsftpd-3.0.2-29.el7_9": 1, - "httpd-2.4.6-97.el7.centos.5": 1, - // "httpd-2.4.6": 1, // binary (excluded) + "basesystem-11-13.el9": 1, + "curl-minimal-7.76.1-29.el9_4.1": 1, // upgrade + "wget-1.21.1-8.el9_4": 1, + "vsftpd-3.0.5-5.el9": 1, + "httpd-2.4.57-11.el9_4.1": 1, }, }, } @@ -75,20 +70,21 @@ func TestPackageDeduplication(t *testing.T) { pkgs := sbom.Artifacts.Packages.PackagesByName(name) // with multiple packages with the same name, something is wrong (or this is the wrong fixture) - require.Len(t, pkgs, expectedInstanceCount) - - for _, p := range pkgs { - nameVersion := fmt.Sprintf("%s-%s", name, p.Version) - expectedLocationCount, ok := tt.locationCount[nameVersion] - if !ok { - t.Fatalf("missing name-version: %s", nameVersion) - } + if assert.Len(t, pkgs, expectedInstanceCount, "unexpected package count for %s", name) { + for _, p := range pkgs { + nameVersion := fmt.Sprintf("%s-%s", name, p.Version) + expectedLocationCount, ok := tt.locationCount[nameVersion] + if !ok { + t.Errorf("missing name-version: %s", nameVersion) + continue + } - // we should see merged locations (assumption, there was 1 location for each package) - assert.Len(t, p.Locations.ToSlice(), expectedLocationCount) + // we should see merged locations (assumption, there was 1 location for each package) + assert.Len(t, p.Locations.ToSlice(), expectedLocationCount, "unexpected location count for %s", nameVersion) - // all paths should match - assert.Len(t, p.Locations.CoordinateSet().Paths(), 1) + // all paths should match + assert.Len(t, p.Locations.CoordinateSet().Paths(), 1, "unexpected location count for %s", nameVersion) + } } } diff --git a/cmd/syft/internal/test/integration/test-fixtures/Makefile b/cmd/syft/internal/test/integration/test-fixtures/Makefile index 2a75aa436..7cce0b0d8 100644 --- a/cmd/syft/internal/test/integration/test-fixtures/Makefile +++ b/cmd/syft/internal/test/integration/test-fixtures/Makefile @@ -1,6 +1,21 @@ -# change these if you want CI to not use previous stored cache -INTEGRATION_CACHE_BUSTER := "894d8ca" +FINGERPRINT_FILE := cache.fingerprint -.PHONY: cache.fingerprint -cache.fingerprint: - find image-* -type f -exec md5sum {} + | awk '{print $1}' | sort | tee /dev/stderr | md5sum | tee cache.fingerprint && echo "$(INTEGRATION_CACHE_BUSTER)" >> cache.fingerprint +.DEFAULT_GOAL := fixtures + +# requirement 1: 'fixtures' goal to generate any and all test fixtures +fixtures: + @echo "nothing to do" + +# requirement 2: 'fingerprint' goal to determine if the fixture input that indicates any existing cache should be busted +fingerprint: $(FINGERPRINT_FILE) + +# requirement 3: we always need to recalculate the fingerprint based on source regardless of any existing fingerprint +.PHONY: $(FINGERPRINT_FILE) +$(FINGERPRINT_FILE): + @find image-* -type f -exec sha256sum {} \; | sort -k2 > $(FINGERPRINT_FILE) + @#cat $(FINGERPRINT_FILE) | sha256sum | awk '{print $$1}' + +# requirement 4: 'clean' goal to remove all generated test fixtures +.PHONY: clean +clean: + rm -f $(FINGERPRINT_FILE) diff --git a/cmd/syft/internal/test/integration/test-fixtures/image-golang-compiler/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-golang-compiler/Dockerfile index 2d8e6bbdc..e73f169b2 100644 --- a/cmd/syft/internal/test/integration/test-fixtures/image-golang-compiler/Dockerfile +++ b/cmd/syft/internal/test/integration/test-fixtures/image-golang-compiler/Dockerfile @@ -1 +1,6 @@ -FROM golang:1.18.10-alpine \ No newline at end of file +FROM --platform=linux/amd64 golang:1.18.10-alpine + +FROM scratch + +# we don't need the entire golang toolchain, just a single binary with the stdlib baked in +COPY --from=0 /usr/local/go/bin/gofmt bin/gofmt diff --git a/cmd/syft/internal/test/integration/test-fixtures/image-java-no-main-package/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-java-no-main-package/Dockerfile index dce8deba3..3271f14cf 100644 --- a/cmd/syft/internal/test/integration/test-fixtures/image-java-no-main-package/Dockerfile +++ b/cmd/syft/internal/test/integration/test-fixtures/image-java-no-main-package/Dockerfile @@ -1,4 +1,4 @@ -FROM jenkins/jenkins:2.346.3-slim-jdk17@sha256:028fbbd9112c60ed086f5197fcba71992317864d27644e5949cf9c52ff4b65f0 +FROM jenkins/jenkins:2.346.3-slim-jdk17@sha256:028fbbd9112c60ed086f5197fcba71992317864d27644e5949cf9c52ff4b65f0 AS base USER root @@ -12,7 +12,7 @@ RUN apt-get update 2>&1 > /dev/null && apt-get install -y less zip 2>&1 > /dev/n RUN unzip ../jenkins.war 2>&1 > /dev/null -RUN rm -f ./META-INF/MANIFEST.MF +RUN rm -rf ./META-INF/MANIFEST.MF ./WEB-INF ./jsbundles ./scripts ./css WORKDIR /usr/share/jenkins @@ -21,3 +21,7 @@ RUN rm -rf jenkins.war RUN cd ./tmp && zip -r ../jenkins.war . && cd .. RUN rm -rf ./tmp + +FROM scratch + +COPY --from=base /usr/share/jenkins/jenkins.war /jenkins.war diff --git a/cmd/syft/internal/test/integration/test-fixtures/image-java-virtualpath-regression/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-java-virtualpath-regression/Dockerfile index 63fc6c92a..b7990d9d1 100644 --- a/cmd/syft/internal/test/integration/test-fixtures/image-java-virtualpath-regression/Dockerfile +++ b/cmd/syft/internal/test/integration/test-fixtures/image-java-virtualpath-regression/Dockerfile @@ -1,7 +1,15 @@ -FROM alpine:3.18.3@sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a +FROM alpine:3.18.3@sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a AS base RUN wget https://repo1.maven.org/maven2/org/jvnet/hudson/main/hudson-war/2.2.1/hudson-war-2.2.1.war RUN mv hudson-war-2.2.1.war hudson.war +# let's make this image a little smaller as to not take up so much disk space +# we'll only keep the jar metadata files (pom data + manifest) and throw away the rest +RUN apk add --no-cache python3 py3-pip +COPY extract.py /extract.py +RUN python extract.py +FROM scratch + +COPY --from=base /slim / diff --git a/cmd/syft/internal/test/integration/test-fixtures/image-java-virtualpath-regression/extract.py b/cmd/syft/internal/test/integration/test-fixtures/image-java-virtualpath-regression/extract.py new file mode 100644 index 000000000..e0f005b4c --- /dev/null +++ b/cmd/syft/internal/test/integration/test-fixtures/image-java-virtualpath-regression/extract.py @@ -0,0 +1,69 @@ +import os +import zipfile +import io + +ARCHIVE_EXTENSIONS = ('.jar', '.war', '.ear', '.hpi', '.war', '.sar', '.nar', '.par') +METADATA_FILES = ('pom.xml', 'pom.properties', 'MANIFEST.MF') + + +def slim_archive(archive, output_dir, base_path="", archive_name=""): + """ + extracts metadata files from the archive and creates a slim JAR file + containing only these files. handles nested JARs by preserving them. + """ + slim_buffer = io.BytesIO() + with zipfile.ZipFile(archive, 'r') as zip_file: + with zipfile.ZipFile(slim_buffer, 'w', zipfile.ZIP_DEFLATED) as slim_zip: + for file_name in zip_file.namelist(): + # check for metadata files or nested JARs + if file_name.endswith(METADATA_FILES): + # add metadata files directly to the slimmed archive + file_data = zip_file.read(file_name) + slim_zip.writestr(file_name, file_data) + elif file_name.endswith(ARCHIVE_EXTENSIONS): + # if it's a nested archive, recursively slim it + nested_archive = io.BytesIO(zip_file.read(file_name)) + nested_slim_buffer = io.BytesIO() + slim_archive( + nested_archive, + nested_slim_buffer, + base_path=os.path.join(base_path, os.path.dirname(file_name)), + archive_name=os.path.basename(file_name) + ) + # add the slimmed nested archive back to the parent archive + nested_slim_buffer.seek(0) + slim_zip.writestr(file_name, nested_slim_buffer.read()) + + # write out the slimmed JAR to the output directory if output_dir is a directory + if isinstance(output_dir, str): + output_path = os.path.join(output_dir, base_path, archive_name) + os.makedirs(os.path.dirname(output_path), exist_ok=True) + with open(output_path, 'wb') as f: + slim_buffer.seek(0) + f.write(slim_buffer.read()) + else: + # if output_dir is a BytesIO buffer (for nested archives), just write to it + output_dir.seek(0) + output_dir.write(slim_buffer.getvalue()) + + +def walk_directory_and_slim_jars(base_dir, output_dir): + """ + recursively walks through a directory tree looking for .jar, .war, .ear, + .hpi files and slims them down by keeping only metadata files. + """ + for dirpath, _, filenames in os.walk(base_dir): + for filename in filenames: + if filename.endswith(ARCHIVE_EXTENSIONS): + archive_path = os.path.join(dirpath, filename) + print(f"Processing {archive_path}") + slim_archive(archive_path, output_dir, os.path.relpath(dirpath, base_dir), filename) + + +# a helper script for slimming down JAR files by keeping only metadata files but still keeping the jar packaging, +# including nested JARs! Useful for testing purposes. +if __name__ == "__main__": + BASE_DIR = "." + OUTPUT_DIR = "./slim" + os.makedirs(OUTPUT_DIR, exist_ok=True) + walk_directory_and_slim_jars(BASE_DIR, OUTPUT_DIR) diff --git a/cmd/syft/internal/test/integration/test-fixtures/image-large-apk-data/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-large-apk-data/Dockerfile index 8187870a8..a8eaca236 100644 --- a/cmd/syft/internal/test/integration/test-fixtures/image-large-apk-data/Dockerfile +++ b/cmd/syft/internal/test/integration/test-fixtures/image-large-apk-data/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine@sha256:d9a7354e3845ea8466bb00b22224d9116b183e594527fb5b6c3d30bc01a20378 +FROM alpine@sha256:d9a7354e3845ea8466bb00b22224d9116b183e594527fb5b6c3d30bc01a20378 AS base # we keep these unpinned so that if alpine # changes our integration tests can adapt @@ -6,3 +6,8 @@ RUN apk add --no-cache \ tzdata \ vim \ alpine-sdk + +# we don't need the installed bins for this test, only the APK installed metadata +FROM scratch + +COPY --from=base /lib/apk/db/installed /lib/apk/db/installed diff --git a/cmd/syft/internal/test/integration/test-fixtures/image-mariner-distroless/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-mariner-distroless/Dockerfile index 6a6e08f61..12e7a416d 100644 --- a/cmd/syft/internal/test/integration/test-fixtures/image-mariner-distroless/Dockerfile +++ b/cmd/syft/internal/test/integration/test-fixtures/image-mariner-distroless/Dockerfile @@ -1 +1,8 @@ -FROM mcr.microsoft.com/cbl-mariner/distroless/base:2.0.202205275@sha256:f550c5428df17b145851ad75983aca6d613ad4b51ca7983b2a83e67d0ac91a5d +FROM mcr.microsoft.com/cbl-mariner/distroless/base:2.0.202205275@sha256:f550c5428df17b145851ad75983aca6d613ad4b51ca7983b2a83e67d0ac91a5d AS base + +# let's shoot for smaller test fixtures +FROM scratch + +COPY --from=base /var/lib/rpmmanifest/container-manifest-2 /var/lib/rpmmanifest/container-manifest-2 +COPY --from=base /usr/bin/gencat /usr/bin/gencat +COPY --from=base /usr/bin/openssl /usr/bin/openssl diff --git a/cmd/syft/internal/test/integration/test-fixtures/image-owning-package/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-owning-package/Dockerfile index 192998626..931547acd 100644 --- a/cmd/syft/internal/test/integration/test-fixtures/image-owning-package/Dockerfile +++ b/cmd/syft/internal/test/integration/test-fixtures/image-owning-package/Dockerfile @@ -1,3 +1,8 @@ -FROM ubuntu:20.04@sha256:33a5cc25d22c45900796a1aca487ad7a7cb09f09ea00b779e3b2026b4fc2faba +FROM ubuntu:20.04@sha256:33a5cc25d22c45900796a1aca487ad7a7cb09f09ea00b779e3b2026b4fc2faba AS base # this covers rpm-python RUN apt-get update && apt-get install -y python-pil=6.2.1-3 + +# let's save some space... +FROM scratch + +COPY --from=base /var/lib/dpkg/status /var/lib/dpkg/status diff --git a/cmd/syft/internal/test/integration/test-fixtures/image-photon-all-layers/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-photon-all-layers/Dockerfile index 17bb3691b..491064736 100644 --- a/cmd/syft/internal/test/integration/test-fixtures/image-photon-all-layers/Dockerfile +++ b/cmd/syft/internal/test/integration/test-fixtures/image-photon-all-layers/Dockerfile @@ -1 +1,5 @@ -FROM photon:5.0-20230729@sha256:4cf2a1ce0a3f4625f13a0becb6b9bccfdb014c565be6e9a2ec4c4aad1ff8a5d9 +FROM photon:5.0-20230729@sha256:4cf2a1ce0a3f4625f13a0becb6b9bccfdb014c565be6e9a2ec4c4aad1ff8a5d9 AS base + +FROM scratch + +COPY --from=base /usr/lib/sysimage/rpm /usr/lib/sysimage/rpm diff --git a/cmd/syft/internal/test/integration/test-fixtures/image-sqlite-rpmdb/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-sqlite-rpmdb/Dockerfile index 938b431d5..1bda58960 100644 --- a/cmd/syft/internal/test/integration/test-fixtures/image-sqlite-rpmdb/Dockerfile +++ b/cmd/syft/internal/test/integration/test-fixtures/image-sqlite-rpmdb/Dockerfile @@ -1 +1,6 @@ -FROM fedora:35@sha256:36af84ba69e21c9ef86a0424a090674c433b2b80c2462e57503886f1d823abe8 +FROM fedora:35@sha256:36af84ba69e21c9ef86a0424a090674c433b2b80c2462e57503886f1d823abe8 AS base + +# lets save some space +FROM scratch + +COPY --from=base /var/lib/rpm /var/lib/rpm diff --git a/cmd/syft/internal/test/integration/test-fixtures/image-suse-all-layers/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-suse-all-layers/Dockerfile index 339983d88..0c4f11656 100644 --- a/cmd/syft/internal/test/integration/test-fixtures/image-suse-all-layers/Dockerfile +++ b/cmd/syft/internal/test/integration/test-fixtures/image-suse-all-layers/Dockerfile @@ -1,2 +1,11 @@ -FROM registry.suse.com/suse/sle15:15.3.17.20.20@sha256:fd657ecbab5ca564d6933e887f6ae8542a9398e6a4b399f352ce10c3a24afc64 +FROM registry.suse.com/suse/sle15:15.3.17.20.20@sha256:fd657ecbab5ca564d6933e887f6ae8542a9398e6a4b399f352ce10c3a24afc64 AS base RUN zypper in -y wget + +# let's save some space... we really just need an image that has an RPM DB that is linked across layers +FROM --platform=linux/amd64 busybox:1.36.1 + +# setup a link /var/lib/rpm -> ../../usr/lib/sysimage/rpm +RUN mkdir -p /var/lib && ln -s ../../usr/lib/sysimage/rpm /var/lib/rpm + +# copy the RPM DB from the SUSE image +COPY --from=base /usr/lib/sysimage/rpm/Packages.db /usr/lib/sysimage/rpm/Packages.db diff --git a/cmd/syft/internal/test/integration/test-fixtures/image-test-java-purls/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-test-java-purls/Dockerfile index 16f074b36..4e4cb1388 100644 --- a/cmd/syft/internal/test/integration/test-fixtures/image-test-java-purls/Dockerfile +++ b/cmd/syft/internal/test/integration/test-fixtures/image-test-java-purls/Dockerfile @@ -1,3 +1,18 @@ -FROM docker.io/anchore/test_images:java-88948cc@sha256:dea0e6c24636937f53bdc997d9960c2a18966d1e38bcd8ebd0c395d4e169b806 +FROM docker.io/anchore/test_images:java-88948cc@sha256:dea0e6c24636937f53bdc997d9960c2a18966d1e38bcd8ebd0c395d4e169b806 AS base -RUN rm /packages/gradle-7.1.1-bin.zip \ No newline at end of file +# not covered in testing... +RUN rm /packages/gradle-7.1.1-bin.zip + +RUN apk add --no-cache python3 py3-pip + +COPY extract.py /extract.py + +WORKDIR / + +# let's make this image a little smaller as to not take up so much disk space +# we'll only keep the jar metadata files (pom data + manifest) and throw away the rest +RUN python extract.py + +FROM scratch + +COPY --from=base /slim/packages /packages diff --git a/cmd/syft/internal/test/integration/test-fixtures/image-test-java-purls/extract.py b/cmd/syft/internal/test/integration/test-fixtures/image-test-java-purls/extract.py new file mode 100644 index 000000000..e0f005b4c --- /dev/null +++ b/cmd/syft/internal/test/integration/test-fixtures/image-test-java-purls/extract.py @@ -0,0 +1,69 @@ +import os +import zipfile +import io + +ARCHIVE_EXTENSIONS = ('.jar', '.war', '.ear', '.hpi', '.war', '.sar', '.nar', '.par') +METADATA_FILES = ('pom.xml', 'pom.properties', 'MANIFEST.MF') + + +def slim_archive(archive, output_dir, base_path="", archive_name=""): + """ + extracts metadata files from the archive and creates a slim JAR file + containing only these files. handles nested JARs by preserving them. + """ + slim_buffer = io.BytesIO() + with zipfile.ZipFile(archive, 'r') as zip_file: + with zipfile.ZipFile(slim_buffer, 'w', zipfile.ZIP_DEFLATED) as slim_zip: + for file_name in zip_file.namelist(): + # check for metadata files or nested JARs + if file_name.endswith(METADATA_FILES): + # add metadata files directly to the slimmed archive + file_data = zip_file.read(file_name) + slim_zip.writestr(file_name, file_data) + elif file_name.endswith(ARCHIVE_EXTENSIONS): + # if it's a nested archive, recursively slim it + nested_archive = io.BytesIO(zip_file.read(file_name)) + nested_slim_buffer = io.BytesIO() + slim_archive( + nested_archive, + nested_slim_buffer, + base_path=os.path.join(base_path, os.path.dirname(file_name)), + archive_name=os.path.basename(file_name) + ) + # add the slimmed nested archive back to the parent archive + nested_slim_buffer.seek(0) + slim_zip.writestr(file_name, nested_slim_buffer.read()) + + # write out the slimmed JAR to the output directory if output_dir is a directory + if isinstance(output_dir, str): + output_path = os.path.join(output_dir, base_path, archive_name) + os.makedirs(os.path.dirname(output_path), exist_ok=True) + with open(output_path, 'wb') as f: + slim_buffer.seek(0) + f.write(slim_buffer.read()) + else: + # if output_dir is a BytesIO buffer (for nested archives), just write to it + output_dir.seek(0) + output_dir.write(slim_buffer.getvalue()) + + +def walk_directory_and_slim_jars(base_dir, output_dir): + """ + recursively walks through a directory tree looking for .jar, .war, .ear, + .hpi files and slims them down by keeping only metadata files. + """ + for dirpath, _, filenames in os.walk(base_dir): + for filename in filenames: + if filename.endswith(ARCHIVE_EXTENSIONS): + archive_path = os.path.join(dirpath, filename) + print(f"Processing {archive_path}") + slim_archive(archive_path, output_dir, os.path.relpath(dirpath, base_dir), filename) + + +# a helper script for slimming down JAR files by keeping only metadata files but still keeping the jar packaging, +# including nested JARs! Useful for testing purposes. +if __name__ == "__main__": + BASE_DIR = "." + OUTPUT_DIR = "./slim" + os.makedirs(OUTPUT_DIR, exist_ok=True) + walk_directory_and_slim_jars(BASE_DIR, OUTPUT_DIR) diff --git a/cmd/syft/internal/test/integration/test-fixtures/image-vertical-package-dups/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-vertical-package-dups/Dockerfile index cd0e69b5d..28f95ba59 100644 --- a/cmd/syft/internal/test/integration/test-fixtures/image-vertical-package-dups/Dockerfile +++ b/cmd/syft/internal/test/integration/test-fixtures/image-vertical-package-dups/Dockerfile @@ -1,6 +1,27 @@ -FROM centos:7.9.2009@sha256:be65f488b7764ad3638f236b7b515b3678369a5124c47b8d32916d6487418ea4 +FROM --platform=linux/amd64 rockylinux:9.3.20231119@sha256:d644d203142cd5b54ad2a83a203e1dee68af2229f8fe32f52a30c6e1d3c3a9e0 AS base + # modifying the RPM DB multiple times will result in duplicate packages when using all-layers (if there was no de-dup logic) # curl is tricky, it already exists in the image and is being upgraded -RUN yum install -y wget-1.14-18.el7_6.1 curl-7.29.0-59.el7_9.1 -RUN yum install -y vsftpd-3.0.2-29.el7_9 -RUN yum install -y httpd-2.4.6-97.el7.centos.5 + +# but... we want to make the test image as small as possible, so we are making the changes in stages and then +# copying the RPM DB from each stage to a final stage in separate layers. This will result in a much smaller image. + +FROM base AS stage1 +RUN dnf install -y wget + +FROM stage1 AS stage2 +RUN dnf update -y curl-minimal + +FROM stage2 AS stage3 +RUN dnf install -y vsftpd + +FROM stage3 AS stage4 +RUN dnf install -y httpd + +FROM scratch + +COPY --from=base /var/lib/rpm /var/lib/rpm +COPY --from=stage1 /var/lib/rpm /var/lib/rpm +COPY --from=stage2 /var/lib/rpm /var/lib/rpm +COPY --from=stage3 /var/lib/rpm /var/lib/rpm +COPY --from=stage4 /var/lib/rpm /var/lib/rpm diff --git a/go.mod b/go.mod index 7cb63cf53..f6fc52411 100644 --- a/go.mod +++ b/go.mod @@ -88,6 +88,7 @@ require google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirec require ( github.com/BurntSushi/toml v1.4.0 + github.com/OneOfOne/xxhash v1.2.8 github.com/adrg/xdg v0.5.0 github.com/magiconair/properties v1.8.7 golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 diff --git a/go.sum b/go.sum index d3dc4b7d9..61e20d6dd 100644 --- a/go.sum +++ b/go.sum @@ -79,6 +79,8 @@ github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5 github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= +github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= diff --git a/internal/task/executor.go b/internal/task/executor.go index 2935f61b1..899796424 100644 --- a/internal/task/executor.go +++ b/internal/task/executor.go @@ -7,9 +7,9 @@ import ( "sync" "time" - "github.com/anchore/syft/internal/log" "github.com/hashicorp/go-multierror" + "github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/sbomsync" "github.com/anchore/syft/syft/event/monitor" "github.com/anchore/syft/syft/file" diff --git a/syft/file/cataloger/executable/test-fixtures/Makefile b/syft/file/cataloger/executable/test-fixtures/Makefile new file mode 100644 index 000000000..da3e730e1 --- /dev/null +++ b/syft/file/cataloger/executable/test-fixtures/Makefile @@ -0,0 +1,15 @@ +.DEFAULT_GOAL := default + +default: + @for dir in $(shell find . -mindepth 1 -maxdepth 1 -type d); do \ + if [ -f "$$dir/Makefile" ]; then \ + $(MAKE) -C $$dir; \ + fi; \ + done + +%: + @for dir in $(shell find . -mindepth 1 -maxdepth 1 -type d); do \ + if [ -f "$$dir/Makefile" ]; then \ + $(MAKE) -C $$dir $@; \ + fi; \ + done diff --git a/syft/file/cataloger/executable/test-fixtures/elf/Makefile b/syft/file/cataloger/executable/test-fixtures/elf/Makefile index 1cff6183e..5130c8fac 100644 --- a/syft/file/cataloger/executable/test-fixtures/elf/Makefile +++ b/syft/file/cataloger/executable/test-fixtures/elf/Makefile @@ -1,8 +1,19 @@ BIN=./bin TOOL_IMAGE=localhost/syft-bin-build-tools:latest VERIFY_FILE=actual_verify +FINGERPRINT_FILE=$(BIN).fingerprint -all: build verify +ifndef BIN + $(error BIN is not set) +endif + +.DEFAULT_GOAL := fixtures + +# requirement 1: 'fixtures' goal to generate any and all test fixtures +fixtures: build verify + +# requirement 2: 'fingerprint' goal to determine if the fixture input that indicates any existing cache should be busted +fingerprint: $(FINGERPRINT_FILE) tools-check: @sha256sum -c Dockerfile.sha256 || (echo "Tools Dockerfile has changed" && exit 1) @@ -25,10 +36,14 @@ verify: tools debug: docker run -i --rm -v $(shell pwd):/mount -w /mount/project $(TOOL_IMAGE) bash -cache.fingerprint: - @find project Dockerfile Makefile -type f -exec md5sum {} + | awk '{print $1}' | sort | tee cache.fingerprint +# requirement 3: we always need to recalculate the fingerprint based on source regardless of any existing fingerprint +.PHONY: $(FINGERPRINT_FILE) +$(FINGERPRINT_FILE): + @find project Dockerfile Makefile -type f -exec sha256sum {} \; | sort -k2 > $(FINGERPRINT_FILE) + @#cat $(FINGERPRINT_FILE) | sha256sum | awk '{print $$1}' +# requirement 4: 'clean' goal to remove all generated test fixtures clean: - rm -f $(BIN)/* + rm -rf $(BIN) Dockerfile.sha256 $(VERIFY_FILE) $(FINGERPRINT_FILE) -.PHONY: build verify debug build-image build-bins clean dockerfile-check cache.fingerprint +.PHONY: tools tools-check build verify debug clean \ No newline at end of file diff --git a/syft/file/cataloger/executable/test-fixtures/shared-info/Makefile b/syft/file/cataloger/executable/test-fixtures/shared-info/Makefile index a3d5959c3..8321e0ae0 100644 --- a/syft/file/cataloger/executable/test-fixtures/shared-info/Makefile +++ b/syft/file/cataloger/executable/test-fixtures/shared-info/Makefile @@ -1,8 +1,20 @@ BIN=./bin TOOL_IMAGE=localhost/syft-shared-info-build-tools:latest VERIFY_FILE=actual_verify +FINGERPRINT_FILE=$(BIN).fingerprint + +ifndef BIN + $(error BIN is not set) +endif + +.DEFAULT_GOAL := fixtures + +# requirement 1: 'fixtures' goal to generate any and all test fixtures +fixtures: build + +# requirement 2: 'fingerprint' goal to determine if the fixture input that indicates any existing cache should be busted +fingerprint: $(FINGERPRINT_FILE) -all: build tools-check: @sha256sum -c Dockerfile.sha256 || (echo "Tools Dockerfile has changed" && exit 1) @@ -10,16 +22,20 @@ tools: @(docker inspect $(TOOL_IMAGE) > /dev/null && make tools-check) || (docker build -t $(TOOL_IMAGE) . && sha256sum Dockerfile > Dockerfile.sha256) build: tools - mkdir -p $(BIN) + @mkdir -p $(BIN) docker run --platform linux/amd64 -i -v $(shell pwd):/mount -w /mount/project $(TOOL_IMAGE) make debug: docker run --platform linux/amd64 -i --rm -v $(shell pwd):/mount -w /mount/project $(TOOL_IMAGE) bash -cache.fingerprint: - @find project Dockerfile Makefile -type f -exec md5sum {} + | awk '{print $1}' | sort | tee cache.fingerprint +# requirement 3: we always need to recalculate the fingerprint based on source regardless of any existing fingerprint +.PHONY: $(FINGERPRINT_FILE) +$(FINGERPRINT_FILE): + @find project Dockerfile Makefile -type f -exec sha256sum {} \; | sort -k2 > $(FINGERPRINT_FILE) + @#cat $(FINGERPRINT_FILE) | sha256sum | awk '{print $$1}' +# requirement 4: 'clean' goal to remove all generated test fixtures clean: - rm -f $(BIN)/* + rm -rf $(BIN) Dockerfile.sha256 $(VERIFY_FILE) $(FINGERPRINT_FILE) -.PHONY: build verify debug build-image build-bins clean dockerfile-check cache.fingerprint +.PHONY: tools tools-check build debug clean diff --git a/syft/format/text/test-fixtures/image-simple/Dockerfile b/syft/format/text/test-fixtures/image-simple/Dockerfile deleted file mode 100644 index 79cfa759e..000000000 --- a/syft/format/text/test-fixtures/image-simple/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -# Note: changes to this file will result in updating several test values. Consider making a new image fixture instead of editing this one. -FROM scratch -ADD file-1.txt /somefile-1.txt -ADD file-2.txt /somefile-2.txt diff --git a/syft/format/text/test-fixtures/image-simple/file-1.txt b/syft/format/text/test-fixtures/image-simple/file-1.txt deleted file mode 100644 index 985d3408e..000000000 --- a/syft/format/text/test-fixtures/image-simple/file-1.txt +++ /dev/null @@ -1 +0,0 @@ -this file has contents \ No newline at end of file diff --git a/syft/format/text/test-fixtures/image-simple/file-2.txt b/syft/format/text/test-fixtures/image-simple/file-2.txt deleted file mode 100644 index 396d08bbc..000000000 --- a/syft/format/text/test-fixtures/image-simple/file-2.txt +++ /dev/null @@ -1 +0,0 @@ -file-2 contents! \ No newline at end of file diff --git a/syft/format/text/test-fixtures/snapshot/TestTextImageEncoder.golden b/syft/format/text/test-fixtures/snapshot/TestTextImageEncoder.golden index 4ab3a446e..0c49cecc0 100644 --- a/syft/format/text/test-fixtures/snapshot/TestTextImageEncoder.golden +++ b/syft/format/text/test-fixtures/snapshot/TestTextImageEncoder.golden @@ -1,11 +1,11 @@ [Image] Layer: 0 - Digest: sha256:fb6beecb75b39f4bb813dbf177e501edd5ddb3e69bb45cedeb78c676ee1b7a59 + Digest: sha256:100d5a55f9032faead28b7427fa3e650e4f0158f86ea89d06e1489df00cb8c6f Size: 22 MediaType: application/vnd.docker.image.rootfs.diff.tar.gzip Layer: 1 - Digest: sha256:319b588ce64253a87b533c8ed01cf0025e0eac98e7b516e12532957e1244fdec + Digest: sha256:000fb9200890d3a19138478b20023023c0dce1c54352007c2863716780f049eb Size: 16 MediaType: application/vnd.docker.image.rootfs.diff.tar.gzip diff --git a/syft/pkg/cataloger/binary/test-fixtures/.gitignore b/syft/pkg/cataloger/binary/test-fixtures/.gitignore index e1d59c126..4d4d11ec9 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/.gitignore +++ b/syft/pkg/cataloger/binary/test-fixtures/.gitignore @@ -1,6 +1,5 @@ classifiers/dynamic classifiers/bin -cache.fingerprint # allow for lb patterns (rust, pytho, php and more) !lib*.so diff --git a/syft/pkg/cataloger/binary/test-fixtures/Makefile b/syft/pkg/cataloger/binary/test-fixtures/Makefile index 3e8efed94..fa37d43c1 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/Makefile +++ b/syft/pkg/cataloger/binary/test-fixtures/Makefile @@ -1,8 +1,14 @@ -.PHONY: default list download download-all cache.fingerprint +BIN=classifiers/bin +FINGERPRINT_FILE=$(BIN).fingerprint -.DEFAULT_GOAL := default -default: download +.DEFAULT_GOAL := fixtures + +# requirement 1: 'fixtures' goal to generate any and all test fixtures +fixtures: download + +# requirement 2: 'fingerprint' goal to determine if the fixture input that indicates any existing cache should be busted +fingerprint: clean-fingerprint $(FINGERPRINT_FILE) list: ## list all managed binaries and snippets go run ./manager list @@ -16,14 +22,23 @@ download-all: ## download all managed binaries add-snippet: ## add a new snippet from an existing binary go run ./manager add-snippet -cache.fingerprint: ## prints the sha256sum of the any input to the download command (to determine if there is a cache miss) - @cat ./config.yaml | sha256sum | awk '{print $$1}' | tee cache.fingerprint +# requirement 3: we always need to recalculate the fingerprint based on source regardless of any existing fingerprint +.PHONY: $(FINGERPRINT_FILE) +$(FINGERPRINT_FILE): ## prints the sha256sum of the any input to the download command (to determine if there is a cache miss) + @sha256sum ./config.yaml > $(FINGERPRINT_FILE) + +# requirement 4: 'clean' goal to remove all generated test fixtures +clean: ## clean up all downloaded binaries + rm -rf $(BIN) + +clean-fingerprint: ## clean up all legacy fingerprint files + @find $(BIN) -name '*.fingerprint' -delete -clean: ## clean up all downloaded binaries - rm -rf ./classifiers/bin ## Halp! ################################# .PHONY: help help: - @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "$(BOLD)$(CYAN)%-25s$(RESET)%s\n", $$1, $$2}' \ No newline at end of file + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "$(BOLD)$(CYAN)%-25s$(RESET)%s\n", $$1, $$2}' + +.PHONY: default list download download-all clean clean-fingerprint add-snippet fingerprint \ No newline at end of file diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/traefik/3.0.4/linux-riscv64/traefik b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/traefik/3.0.4/linux-riscv64/traefik new file mode 100644 index 0000000000000000000000000000000000000000..f361c692988ec8d3246272fd8a69b029bd6509c4 GIT binary patch literal 352 zcmY+8txf|$5P%zSYY-3=Vv{qdvVXU;Q$t8_NS6+l64t;$jEY4)Am?MXhB85 z5Yd}}62X>9IY)^sWKCd{%Sj_BnJ{__mL#FZU`lDUVyq|%9_~Bh!<)Qod2Z{vz2kk0 zjYh}MzpGKt;`HF<@o2vfJr-lLE)DDq-rE+=e|FdD;_dsNR~sH)m+v1J@O1X|x#48k JI~>e={{f-rVJ-jw literal 0 HcmV?d00001 diff --git a/syft/pkg/cataloger/binary/test-fixtures/config.yaml b/syft/pkg/cataloger/binary/test-fixtures/config.yaml index 78d8ba4b8..ac433555c 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/config.yaml +++ b/syft/pkg/cataloger/binary/test-fixtures/config.yaml @@ -85,6 +85,7 @@ from-images: paths: - /usr/local/go/bin/go + # TODO: this is no longer available from dockerhub! (the snippet is vital) - version: 1.5.14 images: - ref: haproxy:1.5.14@sha256:3d57e3921cc84e860f764e863ce729dd0765e3d28d444775127bc42d68f98e10 diff --git a/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/Dockerfile b/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/Dockerfile index a5efa56eb..42a74837c 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/Dockerfile +++ b/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/Dockerfile @@ -1,14 +1,31 @@ -FROM rockylinux:8 +FROM rockylinux:8 AS base + RUN dnf update -y; \ dnf install make automake gcc gcc-c++ kernel-devel -y; \ dnf clean all RUN mkdir -p /usr/local/bin/elftests/elfbinwithnestedlib RUN mkdir -p /usr/local/bin/elftests/elfbinwithsisterlib + COPY ./elfbinwithnestedlib /usr/local/bin/elftests/elfbinwithnestedlib COPY ./elfbinwithsisterlib /usr/local/bin/elftests/elfbinwithsisterlib + ENV LD_LIBRARY_PATH=/usr/local/bin/elftests/elfbinwithnestedlib/bin/lib + WORKDIR /usr/local/bin/elftests/elfbinwithnestedlib/ RUN make + WORKDIR /usr/local/bin/elftests/elfbinwithsisterlib RUN make +# let's make the test image smaller, since we only require the built binaries and supporting libraries +FROM busybox:1.36.1-musl + +COPY --from=base /usr/local/bin/elftests /usr/local/bin/elftests +COPY --from=base /var/lib/rpm /var/lib/rpm +COPY --from=base '/usr/lib64/libstdc++.so.6.0.25' '/usr/lib64/libstdc++.so.6.0.25' +COPY --from=base '/usr/lib64/libstdc++.so.6' '/usr/lib64/libstdc++.so.6' +COPY --from=base '/usr/lib64/libc.so.6' '/usr/lib64/libc.so.6' +COPY --from=base '/usr/lib64/libc.so' '/usr/lib64/libc.so' + +# prove we can operate over symlinks (/lib64 -> usr/lib64) +RUN ln -s /usr/lib64 /lib64 diff --git a/syft/pkg/cataloger/binary/test-fixtures/image-fedora-32bit/Dockerfile b/syft/pkg/cataloger/binary/test-fixtures/image-fedora-32bit/Dockerfile index e89c76124..0df726644 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/image-fedora-32bit/Dockerfile +++ b/syft/pkg/cataloger/binary/test-fixtures/image-fedora-32bit/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=linux/arm arm32v7/fedora:36 as build +FROM --platform=linux/arm arm32v7/fedora:36 AS build FROM scratch COPY --from=build /bin/sha256sum /sha256sum diff --git a/syft/pkg/cataloger/binary/test-fixtures/image-fedora-64bit/Dockerfile b/syft/pkg/cataloger/binary/test-fixtures/image-fedora-64bit/Dockerfile index 0d65e7341..bd9694091 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/image-fedora-64bit/Dockerfile +++ b/syft/pkg/cataloger/binary/test-fixtures/image-fedora-64bit/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=linux/amd64 fedora:41@sha256:c05bf79137835bf5c521c58f8252d6031780ae865a0379ab57f412e0ac6b42aa as build +FROM --platform=linux/amd64 fedora:41@sha256:c05bf79137835bf5c521c58f8252d6031780ae865a0379ab57f412e0ac6b42aa AS build FROM scratch diff --git a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/config/binary_from_image.go b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/config/binary_from_image.go index f26ac3ae4..dc5582501 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/config/binary_from_image.go +++ b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/config/binary_from_image.go @@ -1,11 +1,11 @@ package config import ( - "crypto/sha256" "fmt" "path/filepath" "strings" + "github.com/OneOfOne/xxhash" "gopkg.in/yaml.v3" ) @@ -68,13 +68,13 @@ func PlatformAsValue(platform string) string { return strings.ReplaceAll(platform, "/", "-") } -func (c BinaryFromImage) Fingerprint() string { +func (c BinaryFromImage) Digest() string { by, err := yaml.Marshal(c) if err != nil { panic(err) } - hasher := sha256.New() - hasher.Write(by) + hasher := xxhash.New64() + _, _ = hasher.Write(by) return fmt.Sprintf("%x", hasher.Sum(nil)) } diff --git a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/config/binary_from_image_test.go b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/config/binary_from_image_test.go index 8d76d5a2b..55bb3ee40 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/config/binary_from_image_test.go +++ b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/config/binary_from_image_test.go @@ -158,7 +158,7 @@ func TestPlatformAsValue(t *testing.T) { } } -func TestFingerprint(t *testing.T) { +func TestDigest(t *testing.T) { tests := []struct { name string binary BinaryFromImage @@ -179,13 +179,13 @@ func TestFingerprint(t *testing.T) { "path/to/test", }, }, - expected: "54ed081c07e4eba031afed4c04315cf96047822196473971be98d0769a0e3645", + expected: "fc25c48e3d2f01e3", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.expected, tt.binary.Fingerprint()) + assert.Equal(t, tt.expected, tt.binary.Digest()) }) } } diff --git a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/download_from_image.go b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/download_from_image.go index 32b9c83d6..1d5a667ea 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/download_from_image.go +++ b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/download_from_image.go @@ -2,6 +2,7 @@ package internal import ( "encoding/json" + "errors" "fmt" "os" "os/exec" @@ -14,6 +15,8 @@ import ( "github.com/anchore/syft/syft/pkg/cataloger/binary/test-fixtures/manager/internal/ui" ) +const digestFileSuffix = ".xxh64" + func DownloadFromImage(dest string, config config.BinaryFromImage) error { t := ui.Title{Name: config.Name(), Version: config.Version} t.Start() @@ -39,22 +42,22 @@ func DownloadFromImage(dest string, config config.BinaryFromImage) error { } func isDownloadStale(config config.BinaryFromImage, binaryPaths []string) bool { - currentFingerprint := config.Fingerprint() + currentDigest := config.Digest() for _, path := range binaryPaths { - fingerprintPath := path + ".fingerprint" - if _, err := os.Stat(fingerprintPath); err != nil { + digestPath := path + digestFileSuffix + if _, err := os.Stat(digestPath); err != nil { // missing a fingerprint file means the download is stale return true } - writtenFingerprint, err := os.ReadFile(fingerprintPath) + writtenDigest, err := os.ReadFile(digestPath) if err != nil { // missing a fingerprint file means the download is stale return true } - if string(writtenFingerprint) != currentFingerprint { + if string(writtenDigest) != currentDigest { // the fingerprint file does not match the current fingerprint, so the download is stale return true } @@ -103,6 +106,12 @@ func pullDockerImage(imageReference, platform string) error { cmd := exec.Command("docker", "pull", "--platform", platform, imageReference) err := cmd.Run() if err != nil { + // attach stderr to output message + var exitErr *exec.ExitError + if errors.As(err, &exitErr) && len(exitErr.Stderr) > 0 { + err = fmt.Errorf("pull failed: %w:\n%s", err, exitErr.Stderr) + } + a.Done(err) return err } @@ -152,6 +161,12 @@ func copyBinariesFromDockerImage(config config.BinaryFromImage, destination stri cmd := exec.Command("docker", "create", "--name", containerName, image.Reference) if err = cmd.Run(); err != nil { + // attach stderr to output message + var exitErr *exec.ExitError + if errors.As(err, &exitErr) && len(exitErr.Stderr) > 0 { + err = fmt.Errorf("%w:\n%s", err, exitErr.Stderr) + } + return err } @@ -162,7 +177,7 @@ func copyBinariesFromDockerImage(config config.BinaryFromImage, destination stri for i, destinationPath := range config.AllStorePathsForImage(image, destination) { path := config.PathsInImage[i] - if err := copyBinaryFromContainer(containerName, path, destinationPath, config.Fingerprint()); err != nil { + if err := copyBinaryFromContainer(containerName, path, destinationPath, config.Digest()); err != nil { return err } } @@ -170,7 +185,7 @@ func copyBinariesFromDockerImage(config config.BinaryFromImage, destination stri return nil } -func copyBinaryFromContainer(containerName, containerPath, destinationPath, fingerprint string) (err error) { +func copyBinaryFromContainer(containerName, containerPath, destinationPath, digest string) (err error) { a := ui.Action{Msg: fmt.Sprintf("extract %s", containerPath)} a.Start() @@ -185,13 +200,24 @@ func copyBinaryFromContainer(containerName, containerPath, destinationPath, fing cmd := exec.Command("docker", "cp", fmt.Sprintf("%s:%s", containerName, containerPath), destinationPath) //nolint:gosec // reason for gosec exception: this is for processing test fixtures only, not used in production if err := cmd.Run(); err != nil { + // attach stderr to output message + var exitErr *exec.ExitError + if errors.As(err, &exitErr) && len(exitErr.Stderr) > 0 { + err = fmt.Errorf("%w:\n%s", err, exitErr.Stderr) + } + return err } - // capture fingerprint file - fingerprintPath := destinationPath + ".fingerprint" - if err := os.WriteFile(fingerprintPath, []byte(fingerprint), 0600); err != nil { - return fmt.Errorf("unable to write fingerprint file: %w", err) + // ensure permissions are 600 for destination + if err := os.Chmod(destinationPath, 0600); err != nil { + return fmt.Errorf("unable to set permissions on file %q: %w", destinationPath, err) + } + + // capture digest file + digestPath := destinationPath + digestFileSuffix + if err := os.WriteFile(digestPath, []byte(digest), 0600); err != nil { + return fmt.Errorf("unable to write digest file: %w", err) } return nil diff --git a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/download_from_image_test.go b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/download_from_image_test.go index ca62ea547..fc097a7db 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/download_from_image_test.go +++ b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/download_from_image_test.go @@ -14,35 +14,35 @@ import ( func TestIsDownloadStale(t *testing.T) { cases := []struct { - name string - fingerprint string - expected bool + name string + digest string + expected bool }{ { - name: "no fingerprint", - fingerprint: "", - expected: true, + name: "no digest", + digest: "", + expected: true, }, { - name: "fingerprint matches", - // this is the fingerprint for config in the loop body - fingerprint: "5177d458eaca031ea16fa707841043df2e31b89be6bae7ea41290aa32f0251a6", - expected: false, + name: "digest matches", + // this is the digest for config in the loop body + digest: "c9c8007f9c55c2f1", + expected: false, }, { - name: "fingerprint does not match", - fingerprint: "fingerprint", - expected: true, + name: "digest does not match", + digest: "bogus", + expected: true, }, } for _, tt := range cases { t.Run(tt.name, func(t *testing.T) { binaryPath := filepath.Join(t.TempDir(), "binary") - fh, err := os.Create(binaryPath + ".fingerprint") + fh, err := os.Create(binaryPath + digestFileSuffix) require.NoError(t, err) - fh.Write([]byte(tt.fingerprint)) + fh.Write([]byte(tt.digest)) require.NoError(t, fh.Close()) cfg := config.BinaryFromImage{ diff --git a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/list_entries.go b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/list_entries.go index 7d6c20630..9ecf25440 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/list_entries.go +++ b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/list_entries.go @@ -170,7 +170,7 @@ func getLogicalKey(managedBinaryPath string) (*LogicalEntryKey, error) { func allFilePaths(root string) ([]string, error) { var paths []string err := filepath.Walk(root, func(path string, info os.FileInfo, _ error) error { - if info != nil && !info.IsDir() && !strings.HasSuffix(path, ".fingerprint") { + if info != nil && !info.IsDir() && !strings.HasSuffix(path, digestFileSuffix) { paths = append(paths, path) } return nil diff --git a/syft/pkg/cataloger/gentoo/cataloger_test.go b/syft/pkg/cataloger/gentoo/cataloger_test.go index f2deeb199..6fb80e780 100644 --- a/syft/pkg/cataloger/gentoo/cataloger_test.go +++ b/syft/pkg/cataloger/gentoo/cataloger_test.go @@ -64,7 +64,7 @@ func TestPortageCataloger(t *testing.T) { var expectedRelationships []artifact.Relationship pkgtest.NewCatalogTester(). - FromDirectory(t, "test-fixtures/image-portage"). + FromDirectory(t, "test-fixtures/layout"). Expects(expectedPkgs, expectedRelationships). TestCataloger(t, NewPortageCataloger()) diff --git a/syft/pkg/cataloger/gentoo/test-fixtures/image-portage/var/db/pkg/app-containers/skopeo-1.5.1/CONTENTS b/syft/pkg/cataloger/gentoo/test-fixtures/layout/var/db/pkg/app-containers/skopeo-1.5.1/CONTENTS similarity index 100% rename from syft/pkg/cataloger/gentoo/test-fixtures/image-portage/var/db/pkg/app-containers/skopeo-1.5.1/CONTENTS rename to syft/pkg/cataloger/gentoo/test-fixtures/layout/var/db/pkg/app-containers/skopeo-1.5.1/CONTENTS diff --git a/syft/pkg/cataloger/gentoo/test-fixtures/image-portage/var/db/pkg/app-containers/skopeo-1.5.1/LICENSE b/syft/pkg/cataloger/gentoo/test-fixtures/layout/var/db/pkg/app-containers/skopeo-1.5.1/LICENSE similarity index 100% rename from syft/pkg/cataloger/gentoo/test-fixtures/image-portage/var/db/pkg/app-containers/skopeo-1.5.1/LICENSE rename to syft/pkg/cataloger/gentoo/test-fixtures/layout/var/db/pkg/app-containers/skopeo-1.5.1/LICENSE diff --git a/syft/pkg/cataloger/gentoo/test-fixtures/image-portage/var/db/pkg/app-containers/skopeo-1.5.1/SIZE b/syft/pkg/cataloger/gentoo/test-fixtures/layout/var/db/pkg/app-containers/skopeo-1.5.1/SIZE similarity index 100% rename from syft/pkg/cataloger/gentoo/test-fixtures/image-portage/var/db/pkg/app-containers/skopeo-1.5.1/SIZE rename to syft/pkg/cataloger/gentoo/test-fixtures/layout/var/db/pkg/app-containers/skopeo-1.5.1/SIZE diff --git a/syft/pkg/cataloger/golang/test-fixtures/Makefile b/syft/pkg/cataloger/golang/test-fixtures/Makefile new file mode 100644 index 000000000..da3e730e1 --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/Makefile @@ -0,0 +1,15 @@ +.DEFAULT_GOAL := default + +default: + @for dir in $(shell find . -mindepth 1 -maxdepth 1 -type d); do \ + if [ -f "$$dir/Makefile" ]; then \ + $(MAKE) -C $$dir; \ + fi; \ + done + +%: + @for dir in $(shell find . -mindepth 1 -maxdepth 1 -type d); do \ + if [ -f "$$dir/Makefile" ]; then \ + $(MAKE) -C $$dir $@; \ + fi; \ + done diff --git a/syft/pkg/cataloger/golang/test-fixtures/archs/Makefile b/syft/pkg/cataloger/golang/test-fixtures/archs/Makefile index 60eee7ff9..872f2be91 100644 --- a/syft/pkg/cataloger/golang/test-fixtures/archs/Makefile +++ b/syft/pkg/cataloger/golang/test-fixtures/archs/Makefile @@ -1,29 +1,39 @@ DESTINATION=binaries +FINGERPRINT_FILE=$(DESTINATION).fingerprint -all: $(DESTINATION)/hello-mach-o-arm64 $(DESTINATION)/hello-linux-arm $(DESTINATION)/hello-linux-ppc64le $(DESTINATION)/hello-win-amd64 +ifndef DESTINATION + $(error DESTINATION is not set) +endif + +.DEFAULT_GOAL := fixtures + +# requirement 1: 'fixtures' goal to generate any and all test fixtures +fixtures: $(DESTINATION) + +# requirement 2: 'fingerprint' goal to determine if the fixture input that indicates any existing cache should be busted +fingerprint: $(DESTINATION).fingerprint + +$(DESTINATION): $(DESTINATION)/hello-mach-o-arm64 $(DESTINATION)/hello-linux-arm $(DESTINATION)/hello-linux-ppc64le $(DESTINATION)/hello-win-amd64 $(DESTINATION)/hello-mach-o-arm64: - mkdir -p $(DESTINATION) GOARCH=arm64 GOOS=darwin ./src/build.sh $(DESTINATION)/hello-mach-o-arm64 $(DESTINATION)/hello-linux-arm: - mkdir -p $(DESTINATION) GOARCH=arm GOOS=linux ./src/build.sh $(DESTINATION)/hello-linux-arm $(DESTINATION)/hello-linux-ppc64le: - mkdir -p $(DESTINATION) GOARCH=ppc64le GOOS=linux ./src/build.sh $(DESTINATION)/hello-linux-ppc64le $(DESTINATION)/hello-win-amd64: - mkdir -p $(DESTINATION) GOARCH=amd64 GOOS=windows ./src/build.sh $(DESTINATION)/hello-win-amd64 -# we need a way to determine if CI should bust the test cache based on the source material -$(DESTINATION).fingerprint: clean - mkdir -p $(DESTINATION) - find src -type f -exec sha256sum {} \; | sort | tee /dev/stderr | tee $(DESTINATION).fingerprint - sha256sum $(DESTINATION).fingerprint +# requirement 3: we always need to recalculate the fingerprint based on source regardless of any existing fingerprint +.PHONY: $(FINGERPRINT_FILE) +$(FINGERPRINT_FILE): + @find src -type f -exec sha256sum {} \; | sort -k2 > $(FINGERPRINT_FILE) + @#cat $(FINGERPRINT_FILE) | sha256sum | awk '{print $$1}' +# requirement 4: 'clean' goal to remove all generated test fixtures .PHONY: clean clean: - rm -f $(DESTINATION)/* + rm -rf $(DESTINATION) diff --git a/syft/pkg/cataloger/golang/test-fixtures/archs/src/build.sh b/syft/pkg/cataloger/golang/test-fixtures/archs/src/build.sh index 8a3919470..a740b7dba 100755 --- a/syft/pkg/cataloger/golang/test-fixtures/archs/src/build.sh +++ b/syft/pkg/cataloger/golang/test-fixtures/archs/src/build.sh @@ -1,10 +1,13 @@ #!/usr/bin/env bash -set -uxe +set -ue # note: this can be easily done in a 1-liner, however circle CI does NOT allow volume mounts from the host in docker executors (since they are on remote hosts, where the host files are inaccessible) # note: gocache override is so we can run docker build not as root in a container without permission issues BINARY=$1 + +mkdir -p "$(dirname "$BINARY")" + CTRID=$(docker create -e GOOS="${GOOS}" -e GOARCH="${GOARCH}" -u "$(id -u):$(id -g)" -e GOCACHE=/tmp -w /src golang:1.17 go build -o main main.go) function cleanup() { diff --git a/syft/pkg/cataloger/java/test-fixtures/Makefile b/syft/pkg/cataloger/java/test-fixtures/Makefile new file mode 100644 index 000000000..da3e730e1 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/Makefile @@ -0,0 +1,15 @@ +.DEFAULT_GOAL := default + +default: + @for dir in $(shell find . -mindepth 1 -maxdepth 1 -type d); do \ + if [ -f "$$dir/Makefile" ]; then \ + $(MAKE) -C $$dir; \ + fi; \ + done + +%: + @for dir in $(shell find . -mindepth 1 -maxdepth 1 -type d); do \ + if [ -f "$$dir/Makefile" ]; then \ + $(MAKE) -C $$dir $@; \ + fi; \ + done diff --git a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/Makefile b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/Makefile index 980839042..cf0d21a86 100644 --- a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/Makefile +++ b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/Makefile @@ -1,5 +1,10 @@ CACHE_DIR = cache CACHE_PATH = $(shell pwd)/cache +FINGERPRINT_FILE=$(CACHE_DIR).fingerprint + +ifndef CACHE_DIR + $(error CACHE_DIR is not set) +endif JACKSON_CORE = jackson-core-2.15.2 SBT_JACKSON_CORE = com.fasterxml.jackson.core.jackson-core-2.15.2 @@ -8,28 +13,53 @@ API_ALL_SOURCES = api-all-2.0.0-sources SPRING_INSTRUMENTATION = spring-instrumentation-4.3.0-1.0 MULTIPLE_MATCHING = multiple-matching-2.11.5 -$(CACHE_DIR): - mkdir -p $(CACHE_DIR) -$(CACHE_DIR)/$(JACKSON_CORE).jar: $(CACHE_DIR) +.DEFAULT_GOAL := fixtures + +# requirement 1: 'fixtures' goal to generate any and all test fixtures +fixtures: $(CACHE_DIR) + +# requirement 2: 'fingerprint' goal to determine if the fixture input that indicates any existing cache should be busted +fingerprint: $(FINGERPRINT_FILE) + +$(CACHE_DIR): $(CACHE_DIR)/$(JACKSON_CORE).jar $(CACHE_DIR)/$(SBT_JACKSON_CORE).jar $(CACHE_DIR)/$(OPENSAML_CORE).jar $(CACHE_DIR)/$(API_ALL_SOURCES).jar $(CACHE_DIR)/$(SPRING_INSTRUMENTATION).jar $(CACHE_DIR)/$(MULTIPLE_MATCHING).jar + +$(CACHE_DIR)/$(JACKSON_CORE).jar: + mkdir -p $(CACHE_DIR) cd $(JACKSON_CORE) && zip -r $(CACHE_PATH)/$(JACKSON_CORE).jar . -$(CACHE_DIR)/$(SBT_JACKSON_CORE).jar: $(CACHE_DIR) +$(CACHE_DIR)/$(SBT_JACKSON_CORE).jar: + mkdir -p $(CACHE_DIR) cd $(SBT_JACKSON_CORE) && zip -r $(CACHE_PATH)/$(SBT_JACKSON_CORE).jar . -$(CACHE_DIR)/$(OPENSAML_CORE).jar: $(CACHE_DIR) +$(CACHE_DIR)/$(OPENSAML_CORE).jar: + mkdir -p $(CACHE_DIR) cd $(OPENSAML_CORE) && zip -r $(CACHE_PATH)/$(OPENSAML_CORE).jar . -$(CACHE_DIR)/$(API_ALL_SOURCES).jar: $(CACHE_DIR) +$(CACHE_DIR)/$(API_ALL_SOURCES).jar: + mkdir -p $(CACHE_DIR) cd $(API_ALL_SOURCES) && zip -r $(CACHE_PATH)/$(API_ALL_SOURCES).jar . -$(CACHE_DIR)/$(SPRING_INSTRUMENTATION).jar: $(CACHE_DIR) +$(CACHE_DIR)/$(SPRING_INSTRUMENTATION).jar: + mkdir -p $(CACHE_DIR) cd $(SPRING_INSTRUMENTATION) && zip -r $(CACHE_PATH)/$(SPRING_INSTRUMENTATION).jar . -$(CACHE_DIR)/$(MULTIPLE_MATCHING).jar: $(CACHE_DIR) +$(CACHE_DIR)/$(MULTIPLE_MATCHING).jar: + mkdir -p $(CACHE_DIR) cd $(MULTIPLE_MATCHING) && zip -r $(CACHE_PATH)/$(MULTIPLE_MATCHING).jar . # Jenkins plugins typically do not have the version included in the archive name, # so it is important to not include it in the generated test fixture -$(CACHE_DIR)/gradle.hpi: $(CACHE_DIR) - cd jenkins-plugins/gradle/2.11 && zip -r $(CACHE_PATH)/gradle.hpi . \ No newline at end of file +$(CACHE_DIR)/gradle.hpi: + mkdir -p $(CACHE_DIR) + cd jenkins-plugins/gradle/2.11 && zip -r $(CACHE_PATH)/gradle.hpi . + +# requirement 3: we always need to recalculate the fingerprint based on source regardless of any existing fingerprint +.PHONY: $(FINGERPRINT_FILE) +$(FINGERPRINT_FILE): + @find . ! -path '*/cache*' -type f -exec sha256sum {} \; | sort -k2 > $(FINGERPRINT_FILE) + @#cat $(FINGERPRINT_FILE) | sha256sum | awk '{print $$1}' + +# requirement 4: 'clean' goal to remove all generated test fixtures +clean: + rm -rf $(CACHE_DIR)/* $(FINGERPRINT_FILE) diff --git a/syft/pkg/cataloger/java/test-fixtures/java-builds/Makefile b/syft/pkg/cataloger/java/test-fixtures/java-builds/Makefile index 1970b42f8..b3aae020a 100644 --- a/syft/pkg/cataloger/java/test-fixtures/java-builds/Makefile +++ b/syft/pkg/cataloger/java/test-fixtures/java-builds/Makefile @@ -1,17 +1,18 @@ PKGSDIR=packages +FINGERPRINT_FILE=$(PKGSDIR).fingerprint ifndef PKGSDIR $(error PKGSDIR is not set) endif -all: jars archives native-image -clean: clean-examples - rm -f $(PKGSDIR)/* +.DEFAULT_GOAL := fixtures -clean-examples: clean-gradle clean-maven clean-jenkins clean-nestedjar +# requirement 1: 'fixtures' goal to generate any and all test fixtures +fixtures: jars archives native-image -.PHONY: maven gradle clean clean-gradle clean-maven clean-jenkins clean-examples clean-nestedjar jars archives +# requirement 2: 'fingerprint' goal to determine if the fixture input that indicates any existing cache should be busted +fingerprint: $(FINGERPRINT_FILE) jars: $(PKGSDIR)/example-java-app-maven-0.1.0.jar $(PKGSDIR)/example-java-app-gradle-0.1.0.jar $(PKGSDIR)/example-jenkins-plugin.hpi $(PKGSDIR)/spring-boot-0.0.1-SNAPSHOT.jar @@ -71,8 +72,16 @@ $(PKGSDIR)/example-java-app: $(PKGSDIR)/example-java-app-maven-0.1.0.jar $(PKGSDIR)/gcc-amd64-darwin-exec-debug: ./build-example-macho-binary.sh $(PKGSDIR) -# we need a way to determine if CI should bust the test cache based on the source material -.PHONY: cache.fingerprint -cache.fingerprint: - find example* build* gradle* Makefile -type f -exec sha256sum {} \; | sort | tee /dev/stderr | tee cache.fingerprint - sha256sum cache.fingerprint +# requirement 3: we always need to recalculate the fingerprint based on source regardless of any existing fingerprint +.PHONY: $(FINGERPRINT_FILE) +$(FINGERPRINT_FILE): + @find example-* build-* Makefile -type f -exec sha256sum {} \; | sort -k2 > $(FINGERPRINT_FILE) + @#cat $(FINGERPRINT_FILE) | sha256sum | awk '{print $$1}' + +# requirement 4: 'clean' goal to remove all generated test fixtures +clean: clean-examples + rm -rf $(PKGSDIR) $(FINGERPRINT_FILE) + +clean-examples: clean-gradle clean-maven clean-jenkins clean-nestedjar + +.PHONY: maven gradle clean clean-gradle clean-maven clean-jenkins clean-examples clean-nestedjar jars archives diff --git a/syft/pkg/cataloger/kernel/test-fixtures/Makefile b/syft/pkg/cataloger/kernel/test-fixtures/Makefile index 4a2849919..a2c19cf9f 100644 --- a/syft/pkg/cataloger/kernel/test-fixtures/Makefile +++ b/syft/pkg/cataloger/kernel/test-fixtures/Makefile @@ -1,7 +1,21 @@ -all: +FINGERPRINT_FILE=cache.fingerprint -# we need a way to determine if CI should bust the test cache based on the source material -.PHONY: cache.fingerprint -cache.fingerprint: - find Makefile **/Dockerfile -type f -exec sha256sum {} \; | sort | tee /dev/stderr | tee cache.fingerprint - sha256sum cache.fingerprint + +.DEFAULT_GOAL := fixtures + +# requirement 1: 'fixtures' goal to generate any and all test fixtures +fixtures: + @echo "nothing to do" + +# requirement 2: 'fingerprint' goal to determine if the fixture input that indicates any existing cache should be busted +fingerprint: $(FINGERPRINT_FILE) + +# requirement 3: we always need to recalculate the fingerprint based on source regardless of any existing fingerprint +.PHONY: $(FINGERPRINT_FILE) +$(FINGERPRINT_FILE): + @find Makefile **/Dockerfile -type f -exec sha256sum {} \; | sort -k2 > $(FINGERPRINT_FILE) + @#cat $(FINGERPRINT_FILE) | sha256sum | awk '{print $$1}' + +# requirement 4: 'clean' goal to remove all generated test fixtures +clean: + rm -f $(FINGERPRINT_FILE) diff --git a/syft/pkg/cataloger/python/test-fixtures/image-multi-site-package/Dockerfile b/syft/pkg/cataloger/python/test-fixtures/image-multi-site-package/Dockerfile index 3895cebbd..7a8b39c98 100644 --- a/syft/pkg/cataloger/python/test-fixtures/image-multi-site-package/Dockerfile +++ b/syft/pkg/cataloger/python/test-fixtures/image-multi-site-package/Dockerfile @@ -1,9 +1,8 @@ # digest is for linux/amd64 -FROM ubuntu:20.04@sha256:cc9cc8169c9517ae035cf293b15f06922cb8c6c864d625a72b7b18667f264b70 +FROM ubuntu:20.04@sha256:cc9cc8169c9517ae035cf293b15f06922cb8c6c864d625a72b7b18667f264b70 AS base # install Python 3.8 and Python 3.9 -ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update && apt-get install -y python3.8 python3.9 python3-pip python3-venv python3.9-venv python3.8-venv +RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y python3.8 python3.9 python3-pip python3-venv python3.9-venv python3.8-venv # install pip and virtualenv for both Python versions RUN python3.8 -m pip install --upgrade pip virtualenv @@ -35,3 +34,17 @@ RUN /app/project2/venv/bin/pip install click==8.0.3 pyyaml==6.0 RUN /app/project2/venv/bin/pip install inquirer==3.2.4 runs==1.2.2 xmod==1.8.1 six==1.16.0 wcwidth==0.2.13 blessed==1.20.0 editor==1.6.6 readchar==4.1.0 WORKDIR /app + +# let's not waste disk space... we only need the above state we've setup, not all of the os-level packages +RUN rm -rf /app/project1/venv/share +RUN rm -rf /app/project2/venv/share +RUN find /app/project1/venv/lib/python3.9/site-packages/* -type d ! -name '*.dist-info' -exec rm -rf {} + +RUN find /app/project2/venv/lib/python3.8/site-packages/* -type d ! -name '*.dist-info' -exec rm -rf {} + +RUN find /usr/local/lib/python3.8/dist-packages/* -type d ! -name '*.dist-info' -exec rm -rf {} + +RUN find /usr/local/lib/python3.9/dist-packages/* -type d ! -name '*.dist-info' -exec rm -rf {} + + +FROM scratch + +COPY --from=base /app/ /app/ +COPY --from=base /usr/local/lib/python3.8/ /usr/local/lib/python3.8/ +COPY --from=base /usr/local/lib/python3.9/ /usr/local/lib/python3.9/ diff --git a/syft/pkg/cataloger/redhat/test-fixtures/Makefile b/syft/pkg/cataloger/redhat/test-fixtures/Makefile index e280d5e60..2495210ab 100644 --- a/syft/pkg/cataloger/redhat/test-fixtures/Makefile +++ b/syft/pkg/cataloger/redhat/test-fixtures/Makefile @@ -1,21 +1,38 @@ RPMSDIR=rpms +FINGERPRINT_FILE=$(RPMSDIR).fingerprint ifndef RPMSDIR $(error RPMSDIR is not set) endif -all: rpms -clean: - rm -rf $(RPMSDIR) +.DEFAULT_GOAL := fixtures + +# requirement 1: 'fixtures' goal to generate any and all test fixtures +fixtures: rpms + +# requirement 2: 'fingerprint' goal to determine if the fixture input that indicates any existing cache should be busted +fingerprint: $(FINGERPRINT_FILE) rpms: mkdir -p $(RPMSDIR) - cd $(RPMSDIR) && curl https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/a/abc-1.01-9.hg20160905.el7.x86_64.rpm -O - cd $(RPMSDIR) && curl https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/z/zork-1.0.3-1.el7.x86_64.rpm -O - -# we need a way to determine if CI should bust the test cache based on the source material -.PHONY: $(RPMSDIR).fingerprint -$(RPMSDIR).fingerprint: - find Makefile -type f -exec sha256sum {} \; | sort | tee /dev/stderr | tee $(RPMSDIR).fingerprint - sha256sum $(RPMSDIR).fingerprint + @# see note from https://dl.fedoraproject.org/pub/epel/7/README + @# ATTENTION + @# ====================================== + @# The contents of this directory have been moved to our archives available at: + @# + @# http://archives.fedoraproject.org/pub/archive/epel/ + + cd $(RPMSDIR) && curl -LO https://archives.fedoraproject.org/pub/archive/epel/7/x86_64/Packages/a/abc-1.01-9.hg20160905.el7.x86_64.rpm + cd $(RPMSDIR) && curl -LO https://archives.fedoraproject.org/pub/archive/epel/7/x86_64/Packages/z/zork-1.0.3-1.el7.x86_64.rpm + +# requirement 3: we always need to recalculate the fingerprint based on source regardless of any existing fingerprint +.PHONY: $(FINGERPRINT_FILE) +$(FINGERPRINT_FILE): + @find Makefile -type f -exec sha256sum {} \; | sort -k2 > $(FINGERPRINT_FILE) + @#cat $(FINGERPRINT_FILE) | sha256sum | awk '{print $$1}' + +# requirement 4: 'clean' goal to remove all generated test fixtures +.PHONY: clean +clean: + rm -rf $(RPMSDIR) $(FINGERPRINT_FILE) diff --git a/syft/pkg/cataloger/redhat/test-fixtures/image-minimal/Dockerfile b/syft/pkg/cataloger/redhat/test-fixtures/image-minimal/Dockerfile index cda80c349..6e01032f3 100644 --- a/syft/pkg/cataloger/redhat/test-fixtures/image-minimal/Dockerfile +++ b/syft/pkg/cataloger/redhat/test-fixtures/image-minimal/Dockerfile @@ -2,4 +2,8 @@ FROM rockylinux:9.3.20231119@sha256:45cc42828cc5ceeffa3a9b4f6363fb582fac3ab91f77bf403daa067f8f049f96 ADD remove.sh /remove.sh -RUN /remove.sh \ No newline at end of file +RUN /remove.sh + +# let's only keep what we need for testing (not the intermediate layers) +FROM scratch +COPY --from=0 / / diff --git a/test/cli/.gitignore b/test/cli/.gitignore new file mode 100644 index 000000000..872aa273a --- /dev/null +++ b/test/cli/.gitignore @@ -0,0 +1 @@ +results \ No newline at end of file diff --git a/test/cli/cyclonedx_valid_test.go b/test/cli/cyclonedx_valid_test.go index 49755f0bc..4f2ce11ed 100644 --- a/test/cli/cyclonedx_valid_test.go +++ b/test/cli/cyclonedx_valid_test.go @@ -33,7 +33,7 @@ func TestValidCycloneDX(t *testing.T) { { name: "validate cyclonedx output", subcommand: "scan", - args: []string{"-o", "cyclonedx-json"}, + args: []string{"-o", "cyclonedx-json", "-o", "cyclonedx-json=results/sbom.cdx.json"}, fixture: imageFixture, assertions: []traitAssertion{ assertSuccessfulReturnCode, diff --git a/test/cli/scan_cmd_test.go b/test/cli/scan_cmd_test.go index 555f0856b..ed84933ff 100644 --- a/test/cli/scan_cmd_test.go +++ b/test/cli/scan_cmd_test.go @@ -143,8 +143,22 @@ func TestPackagesCmdFlags(t *testing.T) { name: "squashed-scope-flag-hidden-packages", args: []string{"scan", "-o", "json", "-s", "squashed", hiddenPackagesImage}, assertions: []traitAssertion{ - assertPackageCount(162), - assertNotInOutput("vsftpd"), // hidden package + assertPackageCount(14), + // package 1: alpine-baselayout-data@3.6.5-r0 (apk) + // package 2: alpine-baselayout@3.6.5-r0 (apk) + // package 3: alpine-keys@2.4-r1 (apk) + // package 4: apk-tools@2.14.4-r0 (apk) + // package 5: busybox-binsh@1.36.1-r29 (apk) + // package 6: busybox@1.36.1-r29 (apk) + // package 7: ca-certificates-bundle@20240705-r0 (apk) + // package 8: libcrypto3@3.3.1-r3 (apk) + // package 9: libssl3@3.3.1-r3 (apk) + // package 10: musl-utils@1.2.5-r0 (apk) + // package 11: musl@1.2.5-r0 (apk) + // package 12: scanelf@1.3.7-r2 (apk) + // package 13: ssl_client@1.36.1-r29 (apk) + // package 14: zlib@1.3.1-r1 (apk) + assertNotInOutput(`"name":"curl"`), // hidden package assertSuccessfulReturnCode, }, }, @@ -152,9 +166,33 @@ func TestPackagesCmdFlags(t *testing.T) { name: "all-layers-scope-flag", args: []string{"scan", "-o", "json", "-s", "all-layers", hiddenPackagesImage}, assertions: []traitAssertion{ - assertPackageCount(163), // packages are now deduplicated for this case + assertPackageCount(24), + // package 1: alpine-baselayout-data@3.6.5-r0 (apk) + // package 2: alpine-baselayout@3.6.5-r0 (apk) + // package 3: alpine-keys@2.4-r1 (apk) + // package 4: apk-tools@2.14.4-r0 (apk) + // package 5: brotli-libs@1.1.0-r2 (apk) + // package 6: busybox-binsh@1.36.1-r29 (apk) + // package 7: busybox@1.36.1-r29 (apk) + // package 8: c-ares@1.28.1-r0 (apk) + // package 9: ca-certificates-bundle@20240705-r0 (apk) + // package 10: ca-certificates@20240705-r0 (apk) + // package 11: curl@8.9.1-r1 (apk) + // package 12: libcrypto3@3.3.1-r3 (apk) + // package 13: libcurl@8.9.1-r1 (apk) + // package 14: libidn2@2.3.7-r0 (apk) + // package 15: libpsl@0.21.5-r1 (apk) + // package 16: libssl3@3.3.1-r3 (apk) + // package 17: libunistring@1.2-r0 (apk) + // package 18: musl-utils@1.2.5-r0 (apk) + // package 19: musl@1.2.5-r0 (apk) + // package 20: nghttp2-libs@1.62.1-r0 (apk) + // package 21: scanelf@1.3.7-r2 (apk) + // package 22: ssl_client@1.36.1-r29 (apk) + // package 23: zlib@1.3.1-r1 (apk) + // package 24: zstd-libs@1.5.6-r0 (apk) assertInOutput("all-layers"), - assertInOutput("vsftpd"), // hidden package + assertInOutput(`"name":"curl"`), // hidden package assertSuccessfulReturnCode, }, }, @@ -165,9 +203,9 @@ func TestPackagesCmdFlags(t *testing.T) { "SYFT_SCOPE": "all-layers", }, assertions: []traitAssertion{ - assertPackageCount(163), // packages are now deduplicated for this case + assertPackageCount(24), // packages are now deduplicated for this case assertInOutput("all-layers"), - assertInOutput("vsftpd"), // hidden package + assertInOutput(`"name":"curl"`), // hidden package assertSuccessfulReturnCode, }, }, diff --git a/test/cli/test-fixtures/Makefile b/test/cli/test-fixtures/Makefile index 5042a5aad..ff1de637e 100644 --- a/test/cli/test-fixtures/Makefile +++ b/test/cli/test-fixtures/Makefile @@ -1,6 +1,22 @@ -# change these if you want CI to not use previous stored cache -CLI_CACHE_BUSTER := "e5cdfd8" +FINGERPRINT_FILE=cache.fingerprint + +.DEFAULT_GOAL := fixtures + +# requirement 1: 'fixtures' goal to generate any and all test fixtures +fixtures: + @echo "nothing to do" + +# requirement 2: 'fingerprint' goal to determine if the fixture input that indicates any existing cache should be busted +fingerprint: $(FINGERPRINT_FILE) + +# requirement 3: we always need to recalculate the fingerprint based on source regardless of any existing fingerprint +.PHONY: $(FINGERPRINT_FILE) +$(FINGERPRINT_FILE): + @find image-* -type f -exec sha256sum {} \; | sort -k2 > $(FINGERPRINT_FILE) + @#cat $(FINGERPRINT_FILE) | sha256sum | awk '{print $$1}' + +# requirement 4: 'clean' goal to remove all generated test fixtures +.PHONY: clean +clean: + rm -f $(FINGERPRINT_FILE) -.PHONY: cache.fingerprint -cache.fingerprint: - find image-* -type f -exec md5sum {} + | awk '{print $1}' | sort | md5sum | tee cache.fingerprint && echo "$(CLI_CACHE_BUSTER)" >> cache.fingerprint diff --git a/test/cli/test-fixtures/image-hidden-packages/Dockerfile b/test/cli/test-fixtures/image-hidden-packages/Dockerfile index 1150209e8..07b7f3275 100644 --- a/test/cli/test-fixtures/image-hidden-packages/Dockerfile +++ b/test/cli/test-fixtures/image-hidden-packages/Dockerfile @@ -1,4 +1,4 @@ -FROM centos:7.9.2009@sha256:dead07b4d8ed7e29e98de0f4504d87e8880d4347859d839686a31da35a3b532f -# all-layers scope should pickup on vsftpd -RUN yum install -y vsftpd -RUN yum remove -y vsftpd +FROM --platform=linux/amd64 alpine:3.20.2@sha256:eddacbc7e24bf8799a4ed3cdcfa50d4b88a323695ad80f317b6629883b2c2a78 + +RUN apk add --no-cache curl +RUN apk del curl diff --git a/test/install/Makefile b/test/install/Makefile index 2a632cd28..9d26ebc63 100644 --- a/test/install/Makefile +++ b/test/install/Makefile @@ -1,5 +1,7 @@ NAME=syft +FINGERPRINT_FILE := cache.fingerprint + # for local testing (not testing within containers) use the binny-managed version of cosign. # this also means that the user does not need to install cosign on their system to run tests. COSIGN_BINARY=../../.tool/cosign @@ -21,8 +23,6 @@ ACCEPTANCE_CMD=sh -c '../../install.sh -v -b /usr/local/bin && syft version && r PREVIOUS_RELEASE=v0.33.0 ACCEPTANCE_PREVIOUS_RELEASE_CMD=sh -c "../../install.sh -b /usr/local/bin $(PREVIOUS_RELEASE) && syft version" -# CI cache busting values; change these if you want CI to not use previous stored cache -INSTALL_TEST_CACHE_BUSTER=894d8ca define title @printf '\n≡≡≡[ $(1) ]≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡\n' @@ -130,7 +130,8 @@ busybox-1.36: ## For CI ######################################################## -.PHONY: cache.fingerprint -cache.fingerprint: - $(call title,Install test fixture fingerprint) - @find ./environments/* -type f -exec md5sum {} + | awk '{print $1}' | sort | tee /dev/stderr | md5sum | tee cache.fingerprint && echo "$(INSTALL_TEST_CACHE_BUSTER)" >> cache.fingerprint +# requirement 3: we always need to recalculate the fingerprint based on source regardless of any existing fingerprint +.PHONY: $(FINGERPRINT_FILE) +$(FINGERPRINT_FILE): + @find ./environments/* -type f -exec sha256sum {} \; | sort -k2 > $(FINGERPRINT_FILE) + @#cat $(FINGERPRINT_FILE) | sha256sum | awk '{print $$1}' From b153b1d5949dda172817289ca8b57c2474c6a5e0 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Mon, 9 Sep 2024 11:27:59 -0400 Subject: [PATCH 186/284] less verbose java logging when non-fatal issues arise (#3208) Signed-off-by: Alex Goodman --- syft/pkg/cataloger/java/archive_filename.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/syft/pkg/cataloger/java/archive_filename.go b/syft/pkg/cataloger/java/archive_filename.go index cc377e438..b753def1d 100644 --- a/syft/pkg/cataloger/java/archive_filename.go +++ b/syft/pkg/cataloger/java/archive_filename.go @@ -58,19 +58,19 @@ type archiveFilename struct { func getSubexp(matches []string, subexpName string, re *regexp.Regexp, raw string) string { if len(matches) < 1 { - log.Warnf("unexpectedly empty matches for archive '%s'", raw) + log.Tracef("unexpectedly empty matches for Java archive '%s'", raw) return "" } index := re.SubexpIndex(subexpName) if index < 1 { - log.Warnf("unexpected index of '%s' capture group for Java archive '%s'", subexpName, raw) + log.Tracef("unexpected index of '%s' capture group for Java archive '%s'", subexpName, raw) return "" } // Prevent out-of-range panic if len(matches) < index+1 { - log.Warnf("no match found for '%s' in '%s'", subexpName, matches[0]) + log.Tracef("no match found for '%s' in '%s' for Java archive", subexpName, matches[0]) return "" } From ba7bf6b85e416bfc2f3c73040f63390fee8f67d9 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Mon, 9 Sep 2024 16:27:21 -0400 Subject: [PATCH 187/284] dont cleanup cache in forks (#3214) Signed-off-by: Alex Goodman --- .github/workflows/validations.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validations.yaml b/.github/workflows/validations.yaml index 0ebca5c82..0413e1637 100644 --- a/.github/workflows/validations.yaml +++ b/.github/workflows/validations.yaml @@ -206,7 +206,7 @@ jobs: Cleanup-Cache: name: "Cleanup snapshot cache" - if: always() + if: github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-20.04 permissions: actions: write From f735a428ebc51aa6c9abfb4ced2e08952af7db56 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 16:27:33 -0400 Subject: [PATCH 188/284] chore(deps): bump github.com/dave/jennifer from 1.7.0 to 1.7.1 (#3212) Bumps [github.com/dave/jennifer](https://github.com/dave/jennifer) from 1.7.0 to 1.7.1. - [Commits](https://github.com/dave/jennifer/compare/v1.7.0...v1.7.1) --- updated-dependencies: - dependency-name: github.com/dave/jennifer dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f6fc52411..8ebc9fd96 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/charmbracelet/bubbles v0.19.0 github.com/charmbracelet/bubbletea v1.0.0 github.com/charmbracelet/lipgloss v0.13.0 - github.com/dave/jennifer v1.7.0 + github.com/dave/jennifer v1.7.1 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da github.com/distribution/reference v0.6.0 github.com/docker/docker v27.2.0+incompatible diff --git a/go.sum b/go.sum index 61e20d6dd..808dca0ec 100644 --- a/go.sum +++ b/go.sum @@ -217,8 +217,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= -github.com/dave/jennifer v1.7.0 h1:uRbSBH9UTS64yXbh4FrMHfgfY762RD+C7bUPKODpSJE= -github.com/dave/jennifer v1.7.0/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc= +github.com/dave/jennifer v1.7.1 h1:B4jJJDHelWcDhlRQxWeo0Npa/pYKBLrirAQoTN45txo= +github.com/dave/jennifer v1.7.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= From 2475f7f696cbfe654340e52e369f802ba2d0c9e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 16:27:43 -0400 Subject: [PATCH 189/284] chore(deps): bump github.com/docker/docker (#3211) Bumps [github.com/docker/docker](https://github.com/docker/docker) from 27.2.0+incompatible to 27.2.1+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.2.0...v27.2.1) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8ebc9fd96..ad588d080 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/dave/jennifer v1.7.1 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da github.com/distribution/reference v0.6.0 - github.com/docker/docker v27.2.0+incompatible + github.com/docker/docker v27.2.1+incompatible github.com/dustin/go-humanize v1.0.1 github.com/elliotchance/phpserialize v1.4.0 github.com/facebookincubator/nvdtools v0.1.5 diff --git a/go.sum b/go.sum index 808dca0ec..f48e183db 100644 --- a/go.sum +++ b/go.sum @@ -233,8 +233,8 @@ github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2 github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.2.0+incompatible h1:Rk9nIVdfH3+Vz4cyI/uhbINhEZ/oLmc+CBXmH6fbNk4= -github.com/docker/docker v27.2.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.2.1+incompatible h1:fQdiLfW7VLscyoeYEBz7/J8soYFDZV1u6VW6gJEjNMI= +github.com/docker/docker v27.2.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= From 16f89840fd6909dcd6d7f2a8d2f694864c633966 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 16:27:52 -0400 Subject: [PATCH 190/284] chore(deps): bump modernc.org/sqlite from 1.32.0 to 1.33.0 (#3210) Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.32.0 to 1.33.0. - [Commits](https://gitlab.com/cznic/sqlite/compare/v1.32.0...v1.33.0) --- updated-dependencies: - dependency-name: modernc.org/sqlite dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 14 ++------------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index ad588d080..3b3ec8e44 100644 --- a/go.mod +++ b/go.mod @@ -81,7 +81,7 @@ require ( golang.org/x/mod v0.21.0 golang.org/x/net v0.28.0 gopkg.in/yaml.v3 v3.0.1 - modernc.org/sqlite v1.32.0 + modernc.org/sqlite v1.33.0 ) require google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect diff --git a/go.sum b/go.sum index f48e183db..8581512a9 100644 --- a/go.sum +++ b/go.sum @@ -1348,14 +1348,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ= -modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= -modernc.org/ccgo/v4 v4.19.2 h1:lwQZgvboKD0jBwdaeVCTouxhxAyN6iawF3STraAal8Y= -modernc.org/ccgo/v4 v4.19.2/go.mod h1:ysS3mxiMV38XGRTTcgo0DQTeTmAO4oCmJl1nX9VFI3s= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= -modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= -modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U= @@ -1364,12 +1358,8 @@ modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= -modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= -modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= -modernc.org/sqlite v1.32.0 h1:6BM4uGza7bWypsw4fdLRsLxut6bHe4c58VeqjRgST8s= -modernc.org/sqlite v1.32.0/go.mod h1:UqoylwmTb9F+IqXERT8bW9zzOWN8qwAIcLdzeBZs4hA= +modernc.org/sqlite v1.33.0 h1:WWkA/T2G17okiLGgKAj4/RMIvgyMT19yQ038160IeYk= +modernc.org/sqlite v1.33.0/go.mod h1:9uQ9hF/pCZoYZK73D/ud5Z7cIRIILSZI8NdIemVMTX8= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= From dafc6ad034340ee7027c37ca7996a47cd6ad519e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 16:28:01 -0400 Subject: [PATCH 191/284] chore(deps): bump github.com/charmbracelet/bubbles from 0.19.0 to 0.20.0 (#3209) Bumps [github.com/charmbracelet/bubbles](https://github.com/charmbracelet/bubbles) from 0.19.0 to 0.20.0. - [Release notes](https://github.com/charmbracelet/bubbles/releases) - [Changelog](https://github.com/charmbracelet/bubbles/blob/master/.goreleaser.yml) - [Commits](https://github.com/charmbracelet/bubbles/compare/v0.19.0...v0.20.0) --- updated-dependencies: - dependency-name: github.com/charmbracelet/bubbles dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 ++++------ go.sum | 20 ++++++++------------ 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 3b3ec8e44..23cca47d1 100644 --- a/go.mod +++ b/go.mod @@ -23,8 +23,8 @@ require ( // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 github.com/bmatcuk/doublestar/v4 v4.6.1 - github.com/charmbracelet/bubbles v0.19.0 - github.com/charmbracelet/bubbletea v1.0.0 + github.com/charmbracelet/bubbles v0.20.0 + github.com/charmbracelet/bubbletea v1.1.0 github.com/charmbracelet/lipgloss v0.13.0 github.com/dave/jennifer v1.7.1 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da @@ -111,10 +111,8 @@ require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/becheran/wildmatch-go v1.0.0 // indirect github.com/charmbracelet/harmonica v0.2.0 // indirect - github.com/charmbracelet/x/ansi v0.1.4 // indirect - github.com/charmbracelet/x/input v0.1.0 // indirect - github.com/charmbracelet/x/term v0.1.1 // indirect - github.com/charmbracelet/x/windows v0.1.0 // indirect + github.com/charmbracelet/x/ansi v0.2.3 // indirect + github.com/charmbracelet/x/term v0.2.0 // indirect github.com/cloudflare/circl v1.3.8 // indirect github.com/containerd/cgroups v1.1.0 // indirect github.com/containerd/containerd v1.7.11 // indirect diff --git a/go.sum b/go.sum index 8581512a9..6eaf663a3 100644 --- a/go.sum +++ b/go.sum @@ -157,22 +157,18 @@ github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charmbracelet/bubbles v0.19.0 h1:gKZkKXPP6GlDk6EcfujDK19PCQqRjaJZQ7QRERx1UF0= -github.com/charmbracelet/bubbles v0.19.0/go.mod h1:WILteEqZ+krG5c3ntGEMeG99nCupcuIk7V0/zOP0tOA= -github.com/charmbracelet/bubbletea v1.0.0 h1:BlNvkVed3DADQlV+W79eioNUOrnMUY25EEVdFUoDoGA= -github.com/charmbracelet/bubbletea v1.0.0/go.mod h1:xc4gm5yv+7tbniEvQ0naiG9P3fzYhk16cTgDZQQW6YE= +github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE= +github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU= +github.com/charmbracelet/bubbletea v1.1.0 h1:FjAl9eAL3HBCHenhz/ZPjkKdScmaS5SK69JAK2YJK9c= +github.com/charmbracelet/bubbletea v1.1.0/go.mod h1:9Ogk0HrdbHolIKHdjfFpyXJmiCzGwy+FesYkZr7hYU4= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY= -github.com/charmbracelet/x/ansi v0.1.4 h1:IEU3D6+dWwPSgZ6HBH+v6oUuZ/nVawMiWj5831KfiLM= -github.com/charmbracelet/x/ansi v0.1.4/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= -github.com/charmbracelet/x/input v0.1.0 h1:TEsGSfZYQyOtp+STIjyBq6tpRaorH0qpwZUj8DavAhQ= -github.com/charmbracelet/x/input v0.1.0/go.mod h1:ZZwaBxPF7IG8gWWzPUVqHEtWhc1+HXJPNuerJGRGZ28= -github.com/charmbracelet/x/term v0.1.1 h1:3cosVAiPOig+EV4X9U+3LDgtwwAoEzJjNdwbXDjF6yI= -github.com/charmbracelet/x/term v0.1.1/go.mod h1:wB1fHt5ECsu3mXYusyzcngVWWlu1KKUmmLhfgr/Flxw= -github.com/charmbracelet/x/windows v0.1.0 h1:gTaxdvzDM5oMa/I2ZNF7wN78X/atWemG9Wph7Ika2k4= -github.com/charmbracelet/x/windows v0.1.0/go.mod h1:GLEO/l+lizvFDBPLIOk+49gdX49L9YWMB5t+DZd0jkQ= +github.com/charmbracelet/x/ansi v0.2.3 h1:VfFN0NUpcjBRd4DnKfRaIRo53KRgey/nhOoEqosGDEY= +github.com/charmbracelet/x/ansi v0.2.3/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0= +github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= From 9c2799e379681eb94f904c020fe5734019032a85 Mon Sep 17 00:00:00 2001 From: Laurent Goderre Date: Tue, 10 Sep 2024 10:35:18 -0400 Subject: [PATCH 192/284] Add the Ocaml ecosystem (#3112) Signed-off-by: Laurent Goderre --- .../catalog_packages_cases_test.go | 8 + .../test/integration/catalog_packages_test.go | 2 + .../pkgs/opam/ocaml-base-compiler.4.14.0/opam | 93 + internal/constants.go | 2 +- internal/task/package_tasks.go | 2 + schema/json/schema-16.0.16.json | 2629 +++++++++++++++++ schema/json/schema-latest.json | 49 +- .../common/spdxhelpers/to_format_model.go | 8 + .../spdxhelpers/to_format_model_test.go | 25 + .../spdxutil/helpers/download_location.go | 2 + .../helpers/originator_supplier_test.go | 9 + .../internal/spdxutil/helpers/source_info.go | 2 + .../spdxutil/helpers/source_info_test.go | 8 + syft/internal/packagemetadata/generated.go | 1 + syft/internal/packagemetadata/names.go | 1 + syft/pkg/cataloger/ocaml/cataloger.go | 15 + syft/pkg/cataloger/ocaml/cataloger_test.go | 33 + syft/pkg/cataloger/ocaml/package.go | 37 + syft/pkg/cataloger/ocaml/package_test.go | 34 + syft/pkg/cataloger/ocaml/parse_opam.go | 150 + syft/pkg/cataloger/ocaml/parse_opam_test.go | 166 ++ .../ocaml/test-fixtures/alcotest.opam | 51 + .../glob-paths/opam/alcotest.opam | 1 + .../opam/ocaml-base-compiler.4.14.0/opam | 1 + .../ocaml-base-compiler.4.14.0/opam | 93 + syft/pkg/language.go | 4 + syft/pkg/language_test.go | 8 + syft/pkg/ocaml.go | 11 + syft/pkg/type.go | 8 +- syft/pkg/type_test.go | 4 + 30 files changed, 3454 insertions(+), 3 deletions(-) create mode 100644 cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/opam/ocaml-base-compiler.4.14.0/opam create mode 100644 schema/json/schema-16.0.16.json create mode 100644 syft/pkg/cataloger/ocaml/cataloger.go create mode 100644 syft/pkg/cataloger/ocaml/cataloger_test.go create mode 100644 syft/pkg/cataloger/ocaml/package.go create mode 100644 syft/pkg/cataloger/ocaml/package_test.go create mode 100644 syft/pkg/cataloger/ocaml/parse_opam.go create mode 100644 syft/pkg/cataloger/ocaml/parse_opam_test.go create mode 100644 syft/pkg/cataloger/ocaml/test-fixtures/alcotest.opam create mode 100644 syft/pkg/cataloger/ocaml/test-fixtures/glob-paths/opam/alcotest.opam create mode 100644 syft/pkg/cataloger/ocaml/test-fixtures/glob-paths/opam/ocaml-base-compiler.4.14.0/opam create mode 100644 syft/pkg/cataloger/ocaml/test-fixtures/ocaml-base-compiler.4.14.0/opam create mode 100644 syft/pkg/ocaml.go diff --git a/cmd/syft/internal/test/integration/catalog_packages_cases_test.go b/cmd/syft/internal/test/integration/catalog_packages_cases_test.go index 55822043e..a8ea39d09 100644 --- a/cmd/syft/internal/test/integration/catalog_packages_cases_test.go +++ b/cmd/syft/internal/test/integration/catalog_packages_cases_test.go @@ -410,6 +410,14 @@ var dirOnlyTestCases = []testCase{ "octo-org/this-repo/.github/workflows/workflow-1.yml": "172239021f7ba04fe7327647b213799853a9eb89", }, }, + { + name: "find opam package", + pkgType: pkg.OpamPkg, + pkgLanguage: pkg.OCaml, + pkgInfo: map[string]string{ + "ocaml-base-compiler": "4.14.0", + }, + }, } var commonTestCases = []testCase{ diff --git a/cmd/syft/internal/test/integration/catalog_packages_test.go b/cmd/syft/internal/test/integration/catalog_packages_test.go index e84d57839..371ddb4e5 100644 --- a/cmd/syft/internal/test/integration/catalog_packages_test.go +++ b/cmd/syft/internal/test/integration/catalog_packages_test.go @@ -52,6 +52,7 @@ func TestPkgCoverageImage(t *testing.T) { definedLanguages.Remove(pkg.Dart.String()) definedLanguages.Remove(pkg.Swift.String()) definedLanguages.Remove(pkg.Swipl.String()) + definedLanguages.Remove(pkg.OCaml.String()) definedLanguages.Remove(pkg.CPP.String()) definedLanguages.Remove(pkg.Haskell.String()) definedLanguages.Remove(pkg.Elixir.String()) @@ -78,6 +79,7 @@ func TestPkgCoverageImage(t *testing.T) { definedPkgs.Remove(string(pkg.LinuxKernelModulePkg)) definedPkgs.Remove(string(pkg.SwiftPkg)) definedPkgs.Remove(string(pkg.SwiplPackPkg)) + definedPkgs.Remove(string(pkg.OpamPkg)) definedPkgs.Remove(string(pkg.GithubActionPkg)) definedPkgs.Remove(string(pkg.GithubActionWorkflowPkg)) diff --git a/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/opam/ocaml-base-compiler.4.14.0/opam b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/opam/ocaml-base-compiler.4.14.0/opam new file mode 100644 index 000000000..15e874ec8 --- /dev/null +++ b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/opam/ocaml-base-compiler.4.14.0/opam @@ -0,0 +1,93 @@ +opam-version: "2.0" +synopsis: "Official release 4.14.0" +maintainer: [ + "David Allsopp " + "Florian Angeletti " +] +authors: "Xavier Leroy and many contributors" +license: "LGPL-2.1-or-later WITH OCaml-LGPL-linking-exception" +homepage: "https://ocaml.org" +bug-reports: "https://github.com/ocaml/opam-repository/issues" +depends: [ + "ocaml" {= "4.14.0" & post} + "base-unix" {post} + "base-bigarray" {post} + "base-threads" {post} + "host-arch-arm32" {arch = "arm32" & post} + "host-arch-arm64" {arch = "arm64" & post} + "host-arch-ppc64" {arch = "ppc64" & post} + "host-arch-riscv64" {arch = "riscv64" & post} + "host-arch-s390x" {arch = "s390x" & post} + "host-arch-x86_32" {os != "win32" & arch = "x86_32" & post} + "host-arch-x86_64" {os != "win32" & arch = "x86_64" & post} + "host-arch-unknown" + {os != "win32" & arch != "arm32" & arch != "arm64" & arch != "ppc64" & + arch != "riscv64" & + arch != "s390x" & + arch != "x86_32" & + arch != "x86_64" & + post} + (("arch-x86_64" {os = "win32" & arch = "x86_64"} & + (("system-mingw" & "mingw-w64-shims" {os-distribution = "cygwin" & post}) | + "system-msvc")) | + ("arch-x86_32" {os = "win32"} & + (("system-mingw" & "mingw-w64-shims" {os-distribution = "cygwin" & post}) | + "system-msvc")) | + "host-system-other" {os != "win32" & post}) + "ocaml-options-vanilla" {post} + "flexdll" {>= "0.36" & os = "win32"} +] +conflict-class: "ocaml-core-compiler" +flags: compiler +setenv: CAML_LD_LIBRARY_PATH = "%{lib}%/stublibs" +build: [ + [ + "./configure" + "--host=x86_64-pc-windows" + {system-msvc:installed & arch-x86_64:installed} + "--host=x86_64-w64-mingw32" + {os-distribution = "cygwin" & system-mingw:installed & + arch-x86_64:installed} + "--host=i686-pc-windows" {system-msvc:installed & arch-x86_32:installed} + "--host=i686-w64-mingw32" + {os-distribution = "cygwin" & system-mingw:installed & + arch-x86_32:installed} + "--prefix=%{prefix}%" + "--docdir=%{doc}%/ocaml" + "--with-flexdll=%{flexdll:share}%" {os = "win32" & flexdll:installed} + "-C" + "CC=cc" {os = "openbsd" | os = "macos"} + "ASPP=cc -c" {os = "openbsd" | os = "macos"} + ] + [make "-j%{jobs}%"] +] +install: [make "install"] +build-env: MSYS2_ARG_CONV_EXCL = "*" +post-messages: [ + """\ +A failure in the middle of the build may be caused by build parallelism + (enabled by default). + Please file a bug report at https://github.com/ocaml/opam-repository/issues""" + {failure & jobs > "1"} + """\ +You can try installing again including --jobs=1 + to force a sequential build instead.""" + {failure & jobs > "1" & opam-version >= "2.0.5"} +] +dev-repo: "git+https://github.com/ocaml/ocaml#4.14" +url { + src: "https://github.com/ocaml/ocaml/archive/4.14.0.tar.gz" + checksum: + "sha256=39f44260382f28d1054c5f9d8bf4753cb7ad64027da792f7938344544da155e8" +} +extra-source "ocaml-base-compiler.install" { + src: + "https://raw.githubusercontent.com/ocaml/opam-source-archives/main/patches/ocaml-base-compiler/ocaml-base-compiler.install" + checksum: [ + "sha256=79f2a1a5044a91350a0eb6ce12e261a72a2855c094c425cddf3860e58c486678" + "md5=3e969b841df1f51ca448e6e6295cb451" + ] +} +x-env-path-rewrite: [ + [CAML_LD_LIBRARY_PATH (";" {os = "win32"} ":" {os != "win32"}) "target"] +] diff --git a/internal/constants.go b/internal/constants.go index 6d1dd1974..93b0093ab 100644 --- a/internal/constants.go +++ b/internal/constants.go @@ -3,5 +3,5 @@ package internal const ( // JSONSchemaVersion is the current schema version output by the JSON encoder // This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment. - JSONSchemaVersion = "16.0.15" + JSONSchemaVersion = "16.0.16" ) diff --git a/internal/task/package_tasks.go b/internal/task/package_tasks.go index 88ce35345..4d56dc88a 100644 --- a/internal/task/package_tasks.go +++ b/internal/task/package_tasks.go @@ -21,6 +21,7 @@ import ( "github.com/anchore/syft/syft/pkg/cataloger/kernel" "github.com/anchore/syft/syft/pkg/cataloger/lua" "github.com/anchore/syft/syft/pkg/cataloger/nix" + "github.com/anchore/syft/syft/pkg/cataloger/ocaml" "github.com/anchore/syft/syft/pkg/cataloger/php" "github.com/anchore/syft/syft/pkg/cataloger/python" "github.com/anchore/syft/syft/pkg/cataloger/r" @@ -95,6 +96,7 @@ func DefaultPackageTaskFactories() PackageTaskFactories { newSimplePackageTaskFactory(swift.NewCocoapodsCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "swift", "cocoapods"), newSimplePackageTaskFactory(swift.NewSwiftPackageManagerCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "swift", "spm"), newSimplePackageTaskFactory(swipl.NewSwiplPackCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "swipl", "pack"), + newSimplePackageTaskFactory(ocaml.NewOpamPackageManagerCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "ocaml", "opam"), // language-specific package for both image and directory scans (but not necessarily declared) //////////////////////////////////////// newSimplePackageTaskFactory(dotnet.NewDotnetPortableExecutableCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, "dotnet", "c#", "binary"), diff --git a/schema/json/schema-16.0.16.json b/schema/json/schema-16.0.16.json new file mode 100644 index 000000000..a88197859 --- /dev/null +++ b/schema/json/schema-16.0.16.json @@ -0,0 +1,2629 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "anchore.io/schema/syft/json/16.0.16/document", + "$ref": "#/$defs/Document", + "$defs": { + "AlpmDbEntry": { + "properties": { + "basepackage": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "packager": { + "type": "string" + }, + "url": { + "type": "string" + }, + "validation": { + "type": "string" + }, + "reason": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "backup": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "basepackage", + "package", + "version", + "description", + "architecture", + "size", + "packager", + "url", + "validation", + "reason", + "files", + "backup" + ] + }, + "AlpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "type": { + "type": "string" + }, + "uid": { + "type": "string" + }, + "gid": { + "type": "string" + }, + "time": { + "type": "string", + "format": "date-time" + }, + "size": { + "type": "string" + }, + "link": { + "type": "string" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object" + }, + "ApkDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "originPackage": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "version": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "url": { + "type": "string" + }, + "description": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "installedSize": { + "type": "integer" + }, + "pullDependencies": { + "items": { + "type": "string" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "pullChecksum": { + "type": "string" + }, + "gitCommitOfApkPort": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/ApkFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "originPackage", + "maintainer", + "version", + "architecture", + "url", + "description", + "size", + "installedSize", + "pullDependencies", + "provides", + "pullChecksum", + "gitCommitOfApkPort", + "files" + ] + }, + "ApkFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "ownerUid": { + "type": "string" + }, + "ownerGid": { + "type": "string" + }, + "permissions": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "BinarySignature": { + "properties": { + "matches": { + "items": { + "$ref": "#/$defs/ClassifierMatch" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "matches" + ] + }, + "CConanFileEntry": { + "properties": { + "ref": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanInfoEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "build_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "py_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "options": { + "$ref": "#/$defs/KeyValues" + }, + "path": { + "type": "string" + }, + "context": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockV2Entry": { + "properties": { + "ref": { + "type": "string" + }, + "packageID": { + "type": "string" + }, + "username": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "recipeRevision": { + "type": "string" + }, + "packageRevision": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CPE": { + "properties": { + "cpe": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "cpe" + ] + }, + "ClassifierMatch": { + "properties": { + "classifier": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Location" + } + }, + "type": "object", + "required": [ + "classifier", + "location" + ] + }, + "CocoaPodfileLockEntry": { + "properties": { + "checksum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "checksum" + ] + }, + "Coordinates": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "DartPubspecLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hosted_url": { + "type": "string" + }, + "vcs_url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Descriptor": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "configuration": true + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Digest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "Document": { + "properties": { + "artifacts": { + "items": { + "$ref": "#/$defs/Package" + }, + "type": "array" + }, + "artifactRelationships": { + "items": { + "$ref": "#/$defs/Relationship" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/File" + }, + "type": "array" + }, + "source": { + "$ref": "#/$defs/Source" + }, + "distro": { + "$ref": "#/$defs/LinuxRelease" + }, + "descriptor": { + "$ref": "#/$defs/Descriptor" + }, + "schema": { + "$ref": "#/$defs/Schema" + } + }, + "type": "object", + "required": [ + "artifacts", + "artifactRelationships", + "source", + "distro", + "descriptor", + "schema" + ] + }, + "DotnetDepsEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "path": { + "type": "string" + }, + "sha512": { + "type": "string" + }, + "hashPath": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "path", + "sha512", + "hashPath" + ] + }, + "DotnetPortableExecutableEntry": { + "properties": { + "assemblyVersion": { + "type": "string" + }, + "legalCopyright": { + "type": "string" + }, + "comments": { + "type": "string" + }, + "internalName": { + "type": "string" + }, + "companyName": { + "type": "string" + }, + "productName": { + "type": "string" + }, + "productVersion": { + "type": "string" + } + }, + "type": "object", + "required": [ + "assemblyVersion", + "legalCopyright", + "companyName", + "productName", + "productVersion" + ] + }, + "DpkgDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ] + }, + "DpkgFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "isConfigFile": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "path", + "isConfigFile" + ] + }, + "ELFSecurityFeatures": { + "properties": { + "symbolTableStripped": { + "type": "boolean" + }, + "stackCanary": { + "type": "boolean" + }, + "nx": { + "type": "boolean" + }, + "relRO": { + "type": "string" + }, + "pie": { + "type": "boolean" + }, + "dso": { + "type": "boolean" + }, + "safeStack": { + "type": "boolean" + }, + "cfi": { + "type": "boolean" + }, + "fortify": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "symbolTableStripped", + "nx", + "relRO", + "pie", + "dso" + ] + }, + "ElfBinaryPackageNoteJsonPayload": { + "properties": { + "type": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "osCPE": { + "type": "string" + }, + "os": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "system": { + "type": "string" + }, + "vendor": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "commit": { + "type": "string" + } + }, + "type": "object" + }, + "ElixirMixLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "ErlangRebarLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "Executable": { + "properties": { + "format": { + "type": "string" + }, + "hasExports": { + "type": "boolean" + }, + "hasEntrypoint": { + "type": "boolean" + }, + "importedLibraries": { + "items": { + "type": "string" + }, + "type": "array" + }, + "elfSecurityFeatures": { + "$ref": "#/$defs/ELFSecurityFeatures" + } + }, + "type": "object", + "required": [ + "format", + "hasExports", + "hasEntrypoint", + "importedLibraries" + ] + }, + "File": { + "properties": { + "id": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Coordinates" + }, + "metadata": { + "$ref": "#/$defs/FileMetadataEntry" + }, + "contents": { + "type": "string" + }, + "digests": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/FileLicense" + }, + "type": "array" + }, + "executable": { + "$ref": "#/$defs/Executable" + } + }, + "type": "object", + "required": [ + "id", + "location" + ] + }, + "FileLicense": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "evidence": { + "$ref": "#/$defs/FileLicenseEvidence" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type" + ] + }, + "FileLicenseEvidence": { + "properties": { + "confidence": { + "type": "integer" + }, + "offset": { + "type": "integer" + }, + "extent": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "confidence", + "offset", + "extent" + ] + }, + "FileMetadataEntry": { + "properties": { + "mode": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "linkDestination": { + "type": "string" + }, + "userID": { + "type": "integer" + }, + "groupID": { + "type": "integer" + }, + "mimeType": { + "type": "string" + }, + "size": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "mode", + "type", + "userID", + "groupID", + "mimeType", + "size" + ] + }, + "GoModuleBuildinfoEntry": { + "properties": { + "goBuildSettings": { + "$ref": "#/$defs/KeyValues" + }, + "goCompiledVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "h1Digest": { + "type": "string" + }, + "mainModule": { + "type": "string" + }, + "goCryptoSettings": { + "items": { + "type": "string" + }, + "type": "array" + }, + "goExperiments": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "goCompiledVersion", + "architecture" + ] + }, + "GoModuleEntry": { + "properties": { + "h1Digest": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackEntry": { + "properties": { + "pkgHash": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackLockEntry": { + "properties": { + "pkgHash": { + "type": "string" + }, + "snapshotURL": { + "type": "string" + } + }, + "type": "object" + }, + "IDLikes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "JavaArchive": { + "properties": { + "virtualPath": { + "type": "string" + }, + "manifest": { + "$ref": "#/$defs/JavaManifest" + }, + "pomProperties": { + "$ref": "#/$defs/JavaPomProperties" + }, + "pomProject": { + "$ref": "#/$defs/JavaPomProject" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "virtualPath" + ] + }, + "JavaManifest": { + "properties": { + "main": { + "$ref": "#/$defs/KeyValues" + }, + "sections": { + "items": { + "$ref": "#/$defs/KeyValues" + }, + "type": "array" + } + }, + "type": "object" + }, + "JavaPomParent": { + "properties": { + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object", + "required": [ + "groupId", + "artifactId", + "version" + ] + }, + "JavaPomProject": { + "properties": { + "path": { + "type": "string" + }, + "parent": { + "$ref": "#/$defs/JavaPomParent" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "groupId", + "artifactId", + "version", + "name" + ] + }, + "JavaPomProperties": { + "properties": { + "path": { + "type": "string" + }, + "name": { + "type": "string" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "extraFields": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "name", + "groupId", + "artifactId", + "version" + ] + }, + "JavascriptNpmPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "private": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "homepage", + "description", + "url", + "private" + ] + }, + "JavascriptNpmPackageLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "JavascriptYarnLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "KeyValue": { + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "key", + "value" + ] + }, + "KeyValues": { + "items": { + "$ref": "#/$defs/KeyValue" + }, + "type": "array" + }, + "License": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "urls": { + "items": { + "type": "string" + }, + "type": "array" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type", + "urls", + "locations" + ] + }, + "LinuxKernelArchive": { + "properties": { + "name": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "version": { + "type": "string" + }, + "extendedVersion": { + "type": "string" + }, + "buildTime": { + "type": "string" + }, + "author": { + "type": "string" + }, + "format": { + "type": "string" + }, + "rwRootFS": { + "type": "boolean" + }, + "swapDevice": { + "type": "integer" + }, + "rootDevice": { + "type": "integer" + }, + "videoMode": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "architecture", + "version" + ] + }, + "LinuxKernelModule": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "path": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "license": { + "type": "string" + }, + "kernelVersion": { + "type": "string" + }, + "versionMagic": { + "type": "string" + }, + "parameters": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/LinuxKernelModuleParameter" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "LinuxKernelModuleParameter": { + "properties": { + "type": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "type": "object" + }, + "LinuxRelease": { + "properties": { + "prettyName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" + }, + "idLike": { + "$ref": "#/$defs/IDLikes" + }, + "version": { + "type": "string" + }, + "versionID": { + "type": "string" + }, + "versionCodename": { + "type": "string" + }, + "buildID": { + "type": "string" + }, + "imageID": { + "type": "string" + }, + "imageVersion": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "variantID": { + "type": "string" + }, + "homeURL": { + "type": "string" + }, + "supportURL": { + "type": "string" + }, + "bugReportURL": { + "type": "string" + }, + "privacyPolicyURL": { + "type": "string" + }, + "cpeName": { + "type": "string" + }, + "supportEnd": { + "type": "string" + } + }, + "type": "object" + }, + "Location": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + }, + "accessPath": { + "type": "string" + }, + "annotations": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "accessPath" + ] + }, + "LuarocksPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "dependencies": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "name", + "version", + "license", + "homepage", + "description", + "url", + "dependencies" + ] + }, + "MicrosoftKbPatch": { + "properties": { + "product_id": { + "type": "string" + }, + "kb": { + "type": "string" + } + }, + "type": "object", + "required": [ + "product_id", + "kb" + ] + }, + "NixStoreEntry": { + "properties": { + "outputHash": { + "type": "string" + }, + "output": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "outputHash", + "files" + ] + }, + "OpamPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "licenses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "url": { + "type": "string" + }, + "checksum": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "licenses", + "url", + "checksum", + "homepage", + "dependencies" + ] + }, + "Package": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "foundBy": { + "type": "string" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "licenses": { + "$ref": "#/$defs/licenses" + }, + "language": { + "type": "string" + }, + "cpes": { + "$ref": "#/$defs/cpes" + }, + "purl": { + "type": "string" + }, + "metadataType": { + "type": "string" + }, + "metadata": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/AlpmDbEntry" + }, + { + "$ref": "#/$defs/ApkDbEntry" + }, + { + "$ref": "#/$defs/BinarySignature" + }, + { + "$ref": "#/$defs/CConanFileEntry" + }, + { + "$ref": "#/$defs/CConanInfoEntry" + }, + { + "$ref": "#/$defs/CConanLockEntry" + }, + { + "$ref": "#/$defs/CConanLockV2Entry" + }, + { + "$ref": "#/$defs/CocoaPodfileLockEntry" + }, + { + "$ref": "#/$defs/DartPubspecLockEntry" + }, + { + "$ref": "#/$defs/DotnetDepsEntry" + }, + { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + }, + { + "$ref": "#/$defs/DpkgDbEntry" + }, + { + "$ref": "#/$defs/ElfBinaryPackageNoteJsonPayload" + }, + { + "$ref": "#/$defs/ElixirMixLockEntry" + }, + { + "$ref": "#/$defs/ErlangRebarLockEntry" + }, + { + "$ref": "#/$defs/GoModuleBuildinfoEntry" + }, + { + "$ref": "#/$defs/GoModuleEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackLockEntry" + }, + { + "$ref": "#/$defs/JavaArchive" + }, + { + "$ref": "#/$defs/JavascriptNpmPackage" + }, + { + "$ref": "#/$defs/JavascriptNpmPackageLockEntry" + }, + { + "$ref": "#/$defs/JavascriptYarnLockEntry" + }, + { + "$ref": "#/$defs/LinuxKernelArchive" + }, + { + "$ref": "#/$defs/LinuxKernelModule" + }, + { + "$ref": "#/$defs/LuarocksPackage" + }, + { + "$ref": "#/$defs/MicrosoftKbPatch" + }, + { + "$ref": "#/$defs/NixStoreEntry" + }, + { + "$ref": "#/$defs/OpamPackage" + }, + { + "$ref": "#/$defs/PhpComposerInstalledEntry" + }, + { + "$ref": "#/$defs/PhpComposerLockEntry" + }, + { + "$ref": "#/$defs/PhpPeclEntry" + }, + { + "$ref": "#/$defs/PortageDbEntry" + }, + { + "$ref": "#/$defs/PythonPackage" + }, + { + "$ref": "#/$defs/PythonPipRequirementsEntry" + }, + { + "$ref": "#/$defs/PythonPipfileLockEntry" + }, + { + "$ref": "#/$defs/PythonPoetryLockEntry" + }, + { + "$ref": "#/$defs/RDescription" + }, + { + "$ref": "#/$defs/RpmArchive" + }, + { + "$ref": "#/$defs/RpmDbEntry" + }, + { + "$ref": "#/$defs/RubyGemspec" + }, + { + "$ref": "#/$defs/RustCargoAuditEntry" + }, + { + "$ref": "#/$defs/RustCargoLockEntry" + }, + { + "$ref": "#/$defs/SwiftPackageManagerLockEntry" + }, + { + "$ref": "#/$defs/SwiplpackPackage" + }, + { + "$ref": "#/$defs/WordpressPluginEntry" + } + ] + } + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "foundBy", + "locations", + "licenses", + "language", + "cpes", + "purl" + ] + }, + "PhpComposerAuthors": { + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name" + ] + }, + "PhpComposerExternalReference": { + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "shasum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "type", + "url", + "reference" + ] + }, + "PhpComposerInstalledEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpComposerLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpPeclEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "PortageDbEntry": { + "properties": { + "installedSize": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/PortageFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "installedSize", + "files" + ] + }, + "PortageFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonDirectURLOriginInfo": { + "properties": { + "url": { + "type": "string" + }, + "commitId": { + "type": "string" + }, + "vcs": { + "type": "string" + } + }, + "type": "object", + "required": [ + "url" + ] + }, + "PythonFileDigest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "PythonFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/PythonFileDigest" + }, + "size": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/PythonFileRecord" + }, + "type": "array" + }, + "sitePackagesRootPath": { + "type": "string" + }, + "topLevelPackages": { + "items": { + "type": "string" + }, + "type": "array" + }, + "directUrlOrigin": { + "$ref": "#/$defs/PythonDirectURLOriginInfo" + }, + "requiresPython": { + "type": "string" + }, + "requiresDist": { + "items": { + "type": "string" + }, + "type": "array" + }, + "providesExtra": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "platform", + "sitePackagesRootPath" + ] + }, + "PythonPipRequirementsEntry": { + "properties": { + "name": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + }, + "versionConstraint": { + "type": "string" + }, + "url": { + "type": "string" + }, + "markers": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "versionConstraint" + ] + }, + "PythonPipfileLockEntry": { + "properties": { + "hashes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "index": { + "type": "string" + } + }, + "type": "object", + "required": [ + "hashes", + "index" + ] + }, + "PythonPoetryLockDependencyEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "optional": { + "type": "boolean" + }, + "markers": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "optional" + ] + }, + "PythonPoetryLockEntry": { + "properties": { + "index": { + "type": "string" + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonPoetryLockDependencyEntry" + }, + "type": "array" + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonPoetryLockExtraEntry" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ] + }, + "PythonPoetryLockExtraEntry": { + "properties": { + "name": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ] + }, + "RDescription": { + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "url": { + "items": { + "type": "string" + }, + "type": "array" + }, + "repository": { + "type": "string" + }, + "built": { + "type": "string" + }, + "needsCompilation": { + "type": "boolean" + }, + "imports": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "suggests": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "Relationship": { + "properties": { + "parent": { + "type": "string" + }, + "child": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "parent", + "child", + "type" + ] + }, + "RpmArchive": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmDbEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "mode": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "userName": { + "type": "string" + }, + "groupName": { + "type": "string" + }, + "flags": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "mode", + "size", + "digest", + "userName", + "groupName", + "flags" + ] + }, + "RubyGemspec": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "RustCargoAuditEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source" + ] + }, + "RustCargoLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + }, + "checksum": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "checksum", + "dependencies" + ] + }, + "Schema": { + "properties": { + "version": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "version", + "url" + ] + }, + "Source": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "metadata" + ] + }, + "SwiftPackageManagerLockEntry": { + "properties": { + "revision": { + "type": "string" + } + }, + "type": "object", + "required": [ + "revision" + ] + }, + "SwiplpackPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "packager": { + "type": "string" + }, + "packagerEmail": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "packager", + "packagerEmail", + "homepage", + "dependencies" + ] + }, + "WordpressPluginEntry": { + "properties": { + "pluginInstallDirectory": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorUri": { + "type": "string" + } + }, + "type": "object", + "required": [ + "pluginInstallDirectory" + ] + }, + "cpes": { + "items": { + "$ref": "#/$defs/CPE" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/License" + }, + "type": "array" + } + } +} diff --git a/schema/json/schema-latest.json b/schema/json/schema-latest.json index 1bab78aa6..a88197859 100644 --- a/schema/json/schema-latest.json +++ b/schema/json/schema-latest.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "anchore.io/schema/syft/json/16.0.15/document", + "$id": "anchore.io/schema/syft/json/16.0.16/document", "$ref": "#/$defs/Document", "$defs": { "AlpmDbEntry": { @@ -1436,6 +1436,50 @@ "files" ] }, + "OpamPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "licenses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "url": { + "type": "string" + }, + "checksum": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "licenses", + "url", + "checksum", + "homepage", + "dependencies" + ] + }, "Package": { "properties": { "id": { @@ -1563,6 +1607,9 @@ { "$ref": "#/$defs/NixStoreEntry" }, + { + "$ref": "#/$defs/OpamPackage" + }, { "$ref": "#/$defs/PhpComposerInstalledEntry" }, diff --git a/syft/format/common/spdxhelpers/to_format_model.go b/syft/format/common/spdxhelpers/to_format_model.go index 3fd136e84..3f93883cf 100644 --- a/syft/format/common/spdxhelpers/to_format_model.go +++ b/syft/format/common/spdxhelpers/to_format_model.go @@ -505,6 +505,14 @@ func toPackageChecksums(p pkg.Package) ([]spdx.Checksum, bool) { Algorithm: spdx.ChecksumAlgorithm(algo), Value: hexStr, }) + case pkg.OpamPackage: + for _, checksum := range meta.Checksums { + parts := strings.Split(checksum, "=") + checksums = append(checksums, spdx.Checksum{ + Algorithm: spdx.ChecksumAlgorithm(strings.ToUpper(parts[0])), + Value: parts[1], + }) + } } return checksums, filesAnalyzed } diff --git a/syft/format/common/spdxhelpers/to_format_model_test.go b/syft/format/common/spdxhelpers/to_format_model_test.go index e986069bb..934fc95dd 100644 --- a/syft/format/common/spdxhelpers/to_format_model_test.go +++ b/syft/format/common/spdxhelpers/to_format_model_test.go @@ -335,6 +335,31 @@ func Test_toPackageChecksums(t *testing.T) { }, filesAnalyzed: false, }, + { + name: "Opam Package", + pkg: pkg.Package{ + Name: "test", + Version: "1.0.0", + Language: pkg.Go, + Metadata: pkg.OpamPackage{ + Checksums: []string{ + "sha256=f5f1c0b4ad2e0dfa6f79eaaaa3586411925c16f61702208ddd4bad2fc17dc47c", + "sha512=05a359dc8400d4ca200ff255dbd030acd33d2c4acb5020838f772c02cdb5f243f3dbafbc43a8cd51e6b5923a140f84c9e7ea25b2c0fa277bb68b996190d36e3b", + }, + }, + }, + expected: []spdx.Checksum{ + { + Algorithm: "SHA256", + Value: "f5f1c0b4ad2e0dfa6f79eaaaa3586411925c16f61702208ddd4bad2fc17dc47c", + }, + { + Algorithm: "SHA512", + Value: "05a359dc8400d4ca200ff255dbd030acd33d2c4acb5020838f772c02cdb5f243f3dbafbc43a8cd51e6b5923a140f84c9e7ea25b2c0fa277bb68b996190d36e3b", + }, + }, + filesAnalyzed: false, + }, { name: "Package with no metadata type", pkg: pkg.Package{ diff --git a/syft/format/internal/spdxutil/helpers/download_location.go b/syft/format/internal/spdxutil/helpers/download_location.go index 3ed1c9ed6..b2bae8f96 100644 --- a/syft/format/internal/spdxutil/helpers/download_location.go +++ b/syft/format/internal/spdxutil/helpers/download_location.go @@ -26,6 +26,8 @@ func DownloadLocation(p pkg.Package) string { return NoneIfEmpty(metadata.Dist.URL) case pkg.PhpComposerInstalledEntry: return NoneIfEmpty(metadata.Dist.URL) + case pkg.OpamPackage: + return NoneIfEmpty(metadata.URL) } } return NOASSERTION diff --git a/syft/format/internal/spdxutil/helpers/originator_supplier_test.go b/syft/format/internal/spdxutil/helpers/originator_supplier_test.go index 51965925d..67abf1dc5 100644 --- a/syft/format/internal/spdxutil/helpers/originator_supplier_test.go +++ b/syft/format/internal/spdxutil/helpers/originator_supplier_test.go @@ -41,6 +41,7 @@ func Test_OriginatorSupplier(t *testing.T) { pkg.RustCargoLockEntry{}, pkg.SwiftPackageManagerResolvedEntry{}, pkg.SwiplPackEntry{}, + pkg.OpamPackage{}, pkg.YarnLockEntry{}, ) tests := []struct { @@ -350,6 +351,14 @@ func Test_OriginatorSupplier(t *testing.T) { originator: "Person: auth (auth@auth.gov)", supplier: "Person: me (me@auth.com)", }, + { + name: "from ocaml opam", + input: pkg.Package{ + Metadata: pkg.OpamPackage{}, + }, + originator: "", + supplier: "", + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { diff --git a/syft/format/internal/spdxutil/helpers/source_info.go b/syft/format/internal/spdxutil/helpers/source_info.go index 770577112..bf8b27218 100644 --- a/syft/format/internal/spdxutil/helpers/source_info.go +++ b/syft/format/internal/spdxutil/helpers/source_info.go @@ -64,6 +64,8 @@ func SourceInfo(p pkg.Package) string { answer = "acquired package info from resolved Swift package manifest" case pkg.SwiplPackPkg: answer = "acquired package info from SWI Prolo pack package file" + case pkg.OpamPkg: + answer = "acquired package info from OCaml opam package file" case pkg.GithubActionPkg, pkg.GithubActionWorkflowPkg: answer = "acquired package info from GitHub Actions workflow file or composite action file" case pkg.WordpressPluginPkg: diff --git a/syft/format/internal/spdxutil/helpers/source_info_test.go b/syft/format/internal/spdxutil/helpers/source_info_test.go index df76ac7eb..d7da0eab1 100644 --- a/syft/format/internal/spdxutil/helpers/source_info_test.go +++ b/syft/format/internal/spdxutil/helpers/source_info_test.go @@ -271,6 +271,14 @@ func Test_SourceInfo(t *testing.T) { "acquired package info from SWI Prolo pack package file", }, }, + { + input: pkg.Package{ + Type: pkg.OpamPkg, + }, + expected: []string{ + "acquired package info from OCaml opam package file", + }, + }, { input: pkg.Package{ Type: pkg.GithubActionPkg, diff --git a/syft/internal/packagemetadata/generated.go b/syft/internal/packagemetadata/generated.go index db843261c..24b961753 100644 --- a/syft/internal/packagemetadata/generated.go +++ b/syft/internal/packagemetadata/generated.go @@ -34,6 +34,7 @@ func AllTypes() []any { pkg.NixStoreEntry{}, pkg.NpmPackage{}, pkg.NpmPackageLockEntry{}, + pkg.OpamPackage{}, pkg.PhpComposerInstalledEntry{}, pkg.PhpComposerLockEntry{}, pkg.PhpPeclEntry{}, diff --git a/syft/internal/packagemetadata/names.go b/syft/internal/packagemetadata/names.go index 52deebce0..8f8390c29 100644 --- a/syft/internal/packagemetadata/names.go +++ b/syft/internal/packagemetadata/names.go @@ -103,6 +103,7 @@ var jsonTypes = makeJSONTypes( jsonNamesWithoutLookup(pkg.RpmArchive{}, "rpm-archive", "RpmMetadata"), // the legacy value is split into two types, where the other is preferred jsonNames(pkg.SwiftPackageManagerResolvedEntry{}, "swift-package-manager-lock-entry", "SwiftPackageManagerMetadata"), jsonNames(pkg.SwiplPackEntry{}, "swiplpack-package"), + jsonNames(pkg.OpamPackage{}, "opam-package"), jsonNames(pkg.RustCargoLockEntry{}, "rust-cargo-lock-entry", "RustCargoPackageMetadata"), jsonNamesWithoutLookup(pkg.RustBinaryAuditEntry{}, "rust-cargo-audit-entry", "RustCargoPackageMetadata"), // the legacy value is split into two types, where the other is preferred jsonNames(pkg.WordpressPluginEntry{}, "wordpress-plugin-entry", "WordpressMetadata"), diff --git a/syft/pkg/cataloger/ocaml/cataloger.go b/syft/pkg/cataloger/ocaml/cataloger.go new file mode 100644 index 000000000..c41ef477b --- /dev/null +++ b/syft/pkg/cataloger/ocaml/cataloger.go @@ -0,0 +1,15 @@ +/* +Package ocaml provides a concrete Cataloger implementation for packages relating to the OCaml language ecosystem. +*/ +package ocaml + +import ( + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/generic" +) + +// NewOpamPackageManagerCataloger returns a new cataloger object for OCaml opam. +func NewOpamPackageManagerCataloger() pkg.Cataloger { + return generic.NewCataloger("opam-cataloger"). + WithParserByGlobs(parseOpamPackage, "*opam") +} diff --git a/syft/pkg/cataloger/ocaml/cataloger_test.go b/syft/pkg/cataloger/ocaml/cataloger_test.go new file mode 100644 index 000000000..b17f13c78 --- /dev/null +++ b/syft/pkg/cataloger/ocaml/cataloger_test.go @@ -0,0 +1,33 @@ +package ocaml + +import ( + "testing" + + "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" +) + +func Test_PackageCataloger_Globs(t *testing.T) { + tests := []struct { + name string + fixture string + expected []string + }{ + { + name: "obtain package files", + fixture: "test-fixtures/glob-paths", + expected: []string{ + "opam/alcotest.opam", + "opam/ocaml-base-compiler.4.14.0/opam", + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + pkgtest.NewCatalogTester(). + FromDirectory(t, test.fixture). + ExpectsResolverContentQueries(test.expected). + TestCataloger(t, NewOpamPackageManagerCataloger()) + }) + } +} diff --git a/syft/pkg/cataloger/ocaml/package.go b/syft/pkg/cataloger/ocaml/package.go new file mode 100644 index 000000000..5144add41 --- /dev/null +++ b/syft/pkg/cataloger/ocaml/package.go @@ -0,0 +1,37 @@ +package ocaml + +import ( + "github.com/anchore/packageurl-go" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" +) + +func newOpamPackage(m pkg.OpamPackage, fileLocation file.Location) pkg.Package { + p := pkg.Package{ + Name: m.Name, + Version: m.Version, + Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(fileLocation, m.Licenses...)...), + PURL: opamPackageURL(m.Name, m.Version), + Locations: file.NewLocationSet(fileLocation), + Type: pkg.OpamPkg, + Language: pkg.OCaml, + Metadata: m, + } + + p.SetID() + + return p +} + +func opamPackageURL(name, version string) string { + var qualifiers packageurl.Qualifiers + + return packageurl.NewPackageURL( + "opam", + "", + name, + version, + qualifiers, + "", + ).ToString() +} diff --git a/syft/pkg/cataloger/ocaml/package_test.go b/syft/pkg/cataloger/ocaml/package_test.go new file mode 100644 index 000000000..551c04524 --- /dev/null +++ b/syft/pkg/cataloger/ocaml/package_test.go @@ -0,0 +1,34 @@ +package ocaml + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_packageURL(t *testing.T) { + + type args struct { + name string + version string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "go case", + args: args{ + name: "ocaml-base-compiler", + version: "5.2.0", + }, + want: "pkg:opam/ocaml-base-compiler@5.2.0", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.want, opamPackageURL(tt.args.name, tt.args.version)) + }) + } +} diff --git a/syft/pkg/cataloger/ocaml/parse_opam.go b/syft/pkg/cataloger/ocaml/parse_opam.go new file mode 100644 index 000000000..6e56db757 --- /dev/null +++ b/syft/pkg/cataloger/ocaml/parse_opam.go @@ -0,0 +1,150 @@ +package ocaml + +import ( + "context" + "encoding/json" + "io" + "path" + "regexp" + "strings" + + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/generic" +) + +//nolint:funlen +func parseOpamPackage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { + var pkgs []pkg.Package + + opamVersionRe := regexp.MustCompile(`(?m)opam-version:\s*"[0-9]+\.[0-9]+"`) + versionRe := regexp.MustCompile(`(?m)^version:\s*"(?P[^"]*)"`) + licenseRe := regexp.MustCompile(`(?m)^license:\s*(?P(?:"[^"]*")|(?:\[[^\]]*\]))`) + homepageRe := regexp.MustCompile(`(?m)homepage:\s*"(?P[^"]+)"`) + urlRe := regexp.MustCompile(`(?m)url\s*{(?P[^}]+)}`) + + data, err := io.ReadAll(reader) + if err != nil { + log.WithFields("error", err).Trace("unable to read opam package") + return nil, nil, nil + } + + if opamVersionRe.FindSubmatch(data) == nil { + log.WithFields("warning", err).Trace("opam version not found") + return nil, nil, nil + } + + // If name is inferred from file name/path + var name, version string + var licenses []string + loc := reader.Location.LocationData.AccessPath + dir, file := path.Split(loc) + + if file == "opam" { + // folder name is the package name and version + s := strings.SplitN(path.Base(dir), ".", 2) + name = s[0] + + if len(s) > 1 { + version = s[1] + } + } else { + // filename is the package name and version is in the content + name = strings.Replace(file, ".opam", "", 1) + + m := versionRe.FindSubmatch(data) + + if m != nil { + version = string(m[1]) + } + } + + entry := pkg.OpamPackage{ + Name: name, + Version: version, + } + + licenseMatch := licenseRe.FindSubmatch(data) + if licenseMatch != nil { + licenses = parseLicenses(string(licenseMatch[1])) + + entry.Licenses = licenses + } + + urlMatch := urlRe.FindSubmatch(data) + if urlMatch != nil { + url, checksums := parseURL(urlMatch[1]) + + if url != "" { + entry.URL = url + } + + if checksums != nil { + entry.Checksums = checksums + } + } + + homepageMatch := homepageRe.FindSubmatch(data) + if homepageMatch != nil { + entry.Homepage = string(homepageMatch[1]) + } + + pkgs = append( + pkgs, + newOpamPackage( + entry, + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + ) + + return pkgs, nil, nil +} + +func parseLicenses(licensesStr string) []string { + licenses := []string{} + + if licensesStr[:1] == `"` { + content := licensesStr[1 : len(licensesStr)-1] + licenses = append(licenses, content) + } else { + var d []string + err := json.Unmarshal([]byte(licensesStr), &d) + + if err == nil { + licenses = append(licenses, d...) + } + } + + return licenses +} + +func parseURL(data []byte) (string, []string) { + urlRe := regexp.MustCompile(`(?m)src:\s*"(?P.*)"`) + checksumsRe := regexp.MustCompile(`(?m)checksum:\s*("[^"]*"|\[\s*((?:"[^"]*"\s*)+)\])`) + + urlMatch := urlRe.FindSubmatch(data) + if urlMatch == nil { + return "", nil + } + + url := urlMatch[1] + + var checksum []string + checksumMatch := checksumsRe.FindSubmatch(data) + if checksumMatch != nil { + var fields []string + if checksumMatch[2] != nil { + fields = strings.Fields(string(checksumMatch[2])) + } else { + fields = strings.Fields(string(checksumMatch[1])) + } + + for _, f := range fields { + checksum = append(checksum, strings.ReplaceAll(f, `"`, "")) + } + } + + return string(url), checksum +} diff --git a/syft/pkg/cataloger/ocaml/parse_opam_test.go b/syft/pkg/cataloger/ocaml/parse_opam_test.go new file mode 100644 index 000000000..f25563be4 --- /dev/null +++ b/syft/pkg/cataloger/ocaml/parse_opam_test.go @@ -0,0 +1,166 @@ +package ocaml + +import ( + "testing" + + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" + "github.com/stretchr/testify/assert" +) + +func TestParseOpamPackage(t *testing.T) { + fixture1 := "test-fixtures/ocaml-base-compiler.4.14.0/opam" + location1 := file.NewLocation(fixture1) + + fixture2 := "test-fixtures/alcotest.opam" + location2 := file.NewLocation(fixture2) + + tests := []struct { + fixture string + want []pkg.Package + }{ + { + fixture: fixture1, + want: []pkg.Package{ + { + Name: "ocaml-base-compiler", + Version: "4.14.0", + PURL: "pkg:opam/ocaml-base-compiler@4.14.0", + Locations: file.NewLocationSet(location1), + Licenses: pkg.NewLicenseSet( + pkg.NewLicensesFromLocation( + location1, + "LGPL-2.1-or-later WITH OCaml-LGPL-linking-exception", + )..., + ), + Language: pkg.OCaml, + Type: pkg.OpamPkg, + Metadata: pkg.OpamPackage{ + Name: "ocaml-base-compiler", + Version: "4.14.0", + Licenses: []string{"LGPL-2.1-or-later WITH OCaml-LGPL-linking-exception"}, + URL: "https://github.com/ocaml/ocaml/archive/4.14.0.tar.gz", + Checksums: []string{ + "sha256=39f44260382f28d1054c5f9d8bf4753cb7ad64027da792f7938344544da155e8", + }, + Homepage: "https://ocaml.org", + }, + }, + }, + }, + { + fixture: fixture2, + want: []pkg.Package{ + { + Name: "alcotest", + Version: "1.5.0", + PURL: "pkg:opam/alcotest@1.5.0", + Locations: file.NewLocationSet(location2), + Licenses: pkg.NewLicenseSet( + pkg.NewLicensesFromLocation( + location2, + "ISC", + )..., + ), + Language: pkg.OCaml, + Type: pkg.OpamPkg, + Metadata: pkg.OpamPackage{ + Name: "alcotest", + Version: "1.5.0", + Licenses: []string{"ISC"}, + Homepage: "https://github.com/mirage/alcotest", + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.fixture, func(t *testing.T) { + // TODO: no relationships are under test yet + var expectedRelationships []artifact.Relationship + + pkgtest.TestFileParser(t, tt.fixture, parseOpamPackage, tt.want, expectedRelationships) + }) + } +} + +func TestParseLicense(t *testing.T) { + tests := []struct { + name string + input string + want []string + }{ + { + name: "single license", + input: `"MIT"`, + want: []string{ + "MIT", + }, + }, + { + name: "multiple license", + input: `[ + "MIT", "IST" + ]`, + want: []string{ + "MIT", + "IST", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.want, parseLicenses(tt.input)) + }) + } +} + +func TestParseUrl(t *testing.T) { + tests := []struct { + name string + input string + wantUrl string + wantChecksums []string + }{ + { + name: "single checksums", + input: ` +src: + "https://github.com/mirage/mirage-clock/releases/download/v4.2.0/mirage-clock-4.2.0.tbz" + checksum: + "sha256=fa17d15d5be23c79ba741f5f7cb88ed7112de16a4410cea81c71b98086889847" + `, + wantUrl: "https://github.com/mirage/mirage-clock/releases/download/v4.2.0/mirage-clock-4.2.0.tbz", + wantChecksums: []string{ + "sha256=fa17d15d5be23c79ba741f5f7cb88ed7112de16a4410cea81c71b98086889847", + }, + }, + { + name: "multiple checksums", + input: ` +src: + "https://github.com/mirage/mirage-clock/releases/download/v4.2.0/mirage-clock-4.2.0.tbz" + checksum: [ + "sha256=fa17d15d5be23c79ba741f5f7cb88ed7112de16a4410cea81c71b98086889847" + "sha512=05a359dc8400d4ca200ff255dbd030acd33d2c4acb5020838f772c02cdb5f243f3dbafbc43a8cd51e6b5923a140f84c9e7ea25b2c0fa277bb68b996190d36e3b" + "sha1024=05a359dc8400d4ca200ff255dbd030acd33d2c4acb5020838f772c02cdb5f243f3dbafbc43a8cd51e6b5923a140f84c9e7ea25b2c0fa277bb68b996190d36e3b" + ] + `, + wantUrl: "https://github.com/mirage/mirage-clock/releases/download/v4.2.0/mirage-clock-4.2.0.tbz", + wantChecksums: []string{ + "sha256=fa17d15d5be23c79ba741f5f7cb88ed7112de16a4410cea81c71b98086889847", + "sha512=05a359dc8400d4ca200ff255dbd030acd33d2c4acb5020838f772c02cdb5f243f3dbafbc43a8cd51e6b5923a140f84c9e7ea25b2c0fa277bb68b996190d36e3b", + "sha1024=05a359dc8400d4ca200ff255dbd030acd33d2c4acb5020838f772c02cdb5f243f3dbafbc43a8cd51e6b5923a140f84c9e7ea25b2c0fa277bb68b996190d36e3b", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + url, checksums := parseURL([]byte(tt.input)) + assert.Equal(t, tt.wantUrl, url) + assert.Equal(t, tt.wantChecksums, checksums) + }) + } +} diff --git a/syft/pkg/cataloger/ocaml/test-fixtures/alcotest.opam b/syft/pkg/cataloger/ocaml/test-fixtures/alcotest.opam new file mode 100644 index 000000000..f1ef6f7a3 --- /dev/null +++ b/syft/pkg/cataloger/ocaml/test-fixtures/alcotest.opam @@ -0,0 +1,51 @@ +version: "1.5.0" +# This file is generated by dune, edit dune-project instead +opam-version: "2.0" +synopsis: "Alcotest is a lightweight and colourful test framework" +description: """ +Alcotest exposes simple interface to perform unit tests. It exposes +a simple TESTABLE module type, a check function to assert test +predicates and a run function to perform a list of unit -> unit +test callbacks. + +Alcotest provides a quiet and colorful output where only faulty runs +are fully displayed at the end of the run (with the full logs ready to +inspect), with a simple (yet expressive) query language to select the +tests to run. +""" +maintainer: ["thomas@gazagnaire.org"] +authors: ["Thomas Gazagnaire"] +license: "ISC" +homepage: "https://github.com/mirage/alcotest" +doc: "https://mirage.github.io/alcotest" +bug-reports: "https://github.com/mirage/alcotest/issues" +depends: [ + "dune" {>= "2.8"} + "ocaml" {>= "4.03.0"} + "fmt" {>= "0.8.7"} + "astring" + "cmdliner" {>= "1.0.0"} + "re" + "stdlib-shims" + "uutf" + "ocaml-syntax-shims" + "odoc" {with-doc} +] +conflicts: [ + "result" {< "1.5"} +] +build: [ + ["dune" "subst"] {dev} + [ + "dune" + "build" + "-p" + name + "-j" + jobs + "@install" + "@runtest" {with-test} + "@doc" {with-doc} + ] +] +dev-repo: "git+https://github.com/mirage/alcotest.git" \ No newline at end of file diff --git a/syft/pkg/cataloger/ocaml/test-fixtures/glob-paths/opam/alcotest.opam b/syft/pkg/cataloger/ocaml/test-fixtures/glob-paths/opam/alcotest.opam new file mode 100644 index 000000000..882b6040c --- /dev/null +++ b/syft/pkg/cataloger/ocaml/test-fixtures/glob-paths/opam/alcotest.opam @@ -0,0 +1 @@ +bogus \ No newline at end of file diff --git a/syft/pkg/cataloger/ocaml/test-fixtures/glob-paths/opam/ocaml-base-compiler.4.14.0/opam b/syft/pkg/cataloger/ocaml/test-fixtures/glob-paths/opam/ocaml-base-compiler.4.14.0/opam new file mode 100644 index 000000000..882b6040c --- /dev/null +++ b/syft/pkg/cataloger/ocaml/test-fixtures/glob-paths/opam/ocaml-base-compiler.4.14.0/opam @@ -0,0 +1 @@ +bogus \ No newline at end of file diff --git a/syft/pkg/cataloger/ocaml/test-fixtures/ocaml-base-compiler.4.14.0/opam b/syft/pkg/cataloger/ocaml/test-fixtures/ocaml-base-compiler.4.14.0/opam new file mode 100644 index 000000000..15e874ec8 --- /dev/null +++ b/syft/pkg/cataloger/ocaml/test-fixtures/ocaml-base-compiler.4.14.0/opam @@ -0,0 +1,93 @@ +opam-version: "2.0" +synopsis: "Official release 4.14.0" +maintainer: [ + "David Allsopp " + "Florian Angeletti " +] +authors: "Xavier Leroy and many contributors" +license: "LGPL-2.1-or-later WITH OCaml-LGPL-linking-exception" +homepage: "https://ocaml.org" +bug-reports: "https://github.com/ocaml/opam-repository/issues" +depends: [ + "ocaml" {= "4.14.0" & post} + "base-unix" {post} + "base-bigarray" {post} + "base-threads" {post} + "host-arch-arm32" {arch = "arm32" & post} + "host-arch-arm64" {arch = "arm64" & post} + "host-arch-ppc64" {arch = "ppc64" & post} + "host-arch-riscv64" {arch = "riscv64" & post} + "host-arch-s390x" {arch = "s390x" & post} + "host-arch-x86_32" {os != "win32" & arch = "x86_32" & post} + "host-arch-x86_64" {os != "win32" & arch = "x86_64" & post} + "host-arch-unknown" + {os != "win32" & arch != "arm32" & arch != "arm64" & arch != "ppc64" & + arch != "riscv64" & + arch != "s390x" & + arch != "x86_32" & + arch != "x86_64" & + post} + (("arch-x86_64" {os = "win32" & arch = "x86_64"} & + (("system-mingw" & "mingw-w64-shims" {os-distribution = "cygwin" & post}) | + "system-msvc")) | + ("arch-x86_32" {os = "win32"} & + (("system-mingw" & "mingw-w64-shims" {os-distribution = "cygwin" & post}) | + "system-msvc")) | + "host-system-other" {os != "win32" & post}) + "ocaml-options-vanilla" {post} + "flexdll" {>= "0.36" & os = "win32"} +] +conflict-class: "ocaml-core-compiler" +flags: compiler +setenv: CAML_LD_LIBRARY_PATH = "%{lib}%/stublibs" +build: [ + [ + "./configure" + "--host=x86_64-pc-windows" + {system-msvc:installed & arch-x86_64:installed} + "--host=x86_64-w64-mingw32" + {os-distribution = "cygwin" & system-mingw:installed & + arch-x86_64:installed} + "--host=i686-pc-windows" {system-msvc:installed & arch-x86_32:installed} + "--host=i686-w64-mingw32" + {os-distribution = "cygwin" & system-mingw:installed & + arch-x86_32:installed} + "--prefix=%{prefix}%" + "--docdir=%{doc}%/ocaml" + "--with-flexdll=%{flexdll:share}%" {os = "win32" & flexdll:installed} + "-C" + "CC=cc" {os = "openbsd" | os = "macos"} + "ASPP=cc -c" {os = "openbsd" | os = "macos"} + ] + [make "-j%{jobs}%"] +] +install: [make "install"] +build-env: MSYS2_ARG_CONV_EXCL = "*" +post-messages: [ + """\ +A failure in the middle of the build may be caused by build parallelism + (enabled by default). + Please file a bug report at https://github.com/ocaml/opam-repository/issues""" + {failure & jobs > "1"} + """\ +You can try installing again including --jobs=1 + to force a sequential build instead.""" + {failure & jobs > "1" & opam-version >= "2.0.5"} +] +dev-repo: "git+https://github.com/ocaml/ocaml#4.14" +url { + src: "https://github.com/ocaml/ocaml/archive/4.14.0.tar.gz" + checksum: + "sha256=39f44260382f28d1054c5f9d8bf4753cb7ad64027da792f7938344544da155e8" +} +extra-source "ocaml-base-compiler.install" { + src: + "https://raw.githubusercontent.com/ocaml/opam-source-archives/main/patches/ocaml-base-compiler/ocaml-base-compiler.install" + checksum: [ + "sha256=79f2a1a5044a91350a0eb6ce12e261a72a2855c094c425cddf3860e58c486678" + "md5=3e969b841df1f51ca448e6e6295cb451" + ] +} +x-env-path-rewrite: [ + [CAML_LD_LIBRARY_PATH (";" {os = "win32"} ":" {os != "win32"}) "target"] +] diff --git a/syft/pkg/language.go b/syft/pkg/language.go index 24e2de35f..d9289b2da 100644 --- a/syft/pkg/language.go +++ b/syft/pkg/language.go @@ -22,6 +22,7 @@ const ( Java Language = "java" JavaScript Language = "javascript" Lua Language = "lua" + OCaml Language = "ocaml" PHP Language = "php" Python Language = "python" R Language = "R" @@ -43,6 +44,7 @@ var AllLanguages = []Language{ Java, JavaScript, Lua, + OCaml, PHP, Python, R, @@ -92,6 +94,8 @@ func LanguageByName(name string) Language { return Swift case "swipl", string(SwiplPackPkg): return Swipl + case "ocaml", string(OpamPkg): + return OCaml case packageurl.TypeConan, string(CPP): return CPP case packageurl.TypeHackage, string(Haskell): diff --git a/syft/pkg/language_test.go b/syft/pkg/language_test.go index 5519a332b..d5ce5af26 100644 --- a/syft/pkg/language_test.go +++ b/syft/pkg/language_test.go @@ -86,6 +86,10 @@ func TestLanguageFromPURL(t *testing.T) { purl: "pkg:luarocks/kong@3.7.0", want: Lua, }, + { + purl: "pkg:opam/ocaml-base-compiler@ 5.2.0", + want: OCaml, + }, } var languages = strset.New() @@ -227,6 +231,10 @@ func TestLanguageByName(t *testing.T) { name: "swiplpack", language: Swipl, }, + { + name: "opam", + language: OCaml, + }, { name: "pod", language: Swift, diff --git a/syft/pkg/ocaml.go b/syft/pkg/ocaml.go new file mode 100644 index 000000000..350d04339 --- /dev/null +++ b/syft/pkg/ocaml.go @@ -0,0 +1,11 @@ +package pkg + +type OpamPackage struct { + Name string `toml:"name" json:"name"` + Version string `toml:"version" json:"version"` + Licenses []string `mapstructure:"licenses" json:"licenses"` + URL string `mapstructure:"url" json:"url"` + Checksums []string `mapstructure:"checksums" json:"checksum"` + Homepage string `json:"homepage"` + Dependencies []string `toml:"dependencies" json:"dependencies"` +} diff --git a/syft/pkg/type.go b/syft/pkg/type.go index cdb063828..7cebaa8e1 100644 --- a/syft/pkg/type.go +++ b/syft/pkg/type.go @@ -43,6 +43,7 @@ const ( RustPkg Type = "rust-crate" SwiftPkg Type = "swift" SwiplPackPkg Type = "swiplpack" + OpamPkg Type = "opam" WordpressPluginPkg Type = "wordpress-plugin" ) @@ -80,12 +81,13 @@ var AllPkgs = []Type{ RustPkg, SwiftPkg, SwiplPackPkg, + OpamPkg, WordpressPluginPkg, } // PackageURLType returns the PURL package type for the current package. // -//nolint:funlen +//nolint:funlen, gocyclo func (t Type) PackageURLType() string { switch t { case AlpmPkg: @@ -145,6 +147,8 @@ func (t Type) PackageURLType() string { return packageurl.TypeSwift case SwiplPackPkg: return "swiplpack" + case OpamPkg: + return "opam" case WordpressPluginPkg: return "wordpress-plugin" default: @@ -223,6 +227,8 @@ func TypeByName(name string) Type { return SwiftPkg case "swiplpack": return SwiplPackPkg + case "opam": + return OpamPkg case "wordpress-plugin": return WordpressPluginPkg default: diff --git a/syft/pkg/type_test.go b/syft/pkg/type_test.go index b79ad772d..6607abd06 100644 --- a/syft/pkg/type_test.go +++ b/syft/pkg/type_test.go @@ -115,6 +115,10 @@ func TestTypeFromPURL(t *testing.T) { purl: "pkg:swiplpack/condition@0.1.1", expected: SwiplPackPkg, }, + { + purl: "pkg:opam/ocaml-base-compiler@5.2.0", + expected: OpamPkg, + }, } var pkgTypes []string From 98bd4e99b65f6a02c50c25d8e4cff8433cf381a0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 10:35:43 -0400 Subject: [PATCH 193/284] chore(deps): bump golang.org/x/net from 0.28.0 to 0.29.0 (#3203) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.28.0 to 0.29.0. - [Commits](https://github.com/golang/net/compare/v0.28.0...v0.29.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 23cca47d1..30a9bb0e1 100644 --- a/go.mod +++ b/go.mod @@ -79,7 +79,7 @@ require ( github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1 go.uber.org/goleak v1.3.0 golang.org/x/mod v0.21.0 - golang.org/x/net v0.28.0 + golang.org/x/net v0.29.0 gopkg.in/yaml.v3 v3.0.1 modernc.org/sqlite v1.33.0 ) @@ -227,11 +227,11 @@ require ( go.opentelemetry.io/otel/trace v1.19.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect - golang.org/x/crypto v0.26.0 // indirect + golang.org/x/crypto v0.27.0 // indirect golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.24.0 // indirect - golang.org/x/term v0.23.0 // indirect - golang.org/x/text v0.17.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/term v0.24.0 // indirect + golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect diff --git a/go.sum b/go.sum index 6eaf663a3..3d6c2b9f1 100644 --- a/go.sum +++ b/go.sum @@ -864,8 +864,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -954,8 +954,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1067,15 +1067,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= -golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1088,8 +1088,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From fce14fd5378c543fbf6f2dc5fbe11bf4ee5d83a1 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 10:36:50 -0400 Subject: [PATCH 194/284] chore(deps): update CPE dictionary index (#3206) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: wagoodman <590471+wagoodman@users.noreply.github.com> --- .../dictionary/data/cpe-index.json | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index abd3b6ca8..3227665cd 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -2528,6 +2528,9 @@ "chart.js": [ "cpe:2.3:a:chartjs:chart.js:*:*:*:*:*:node.js:*:*" ], + "chartist": [ + "cpe:2.3:a:chartist:chartist:*:*:*:*:*:node.js:*:*" + ], "chatbyvista": [ "cpe:2.3:a:chatbyvista_project:chatbyvista:*:*:*:*:*:node.js:*:*" ], @@ -5567,8 +5570,8 @@ "cpe:2.3:a:pyconuk:conference-scheduler-cli:*:*:*:*:*:*:*:*" ], "cryptography": [ - "cpe:2.3:a:cryptography_project:cryptography:*:*:*:*:*:python:*:*", - "cpe:2.3:a:python-cryptography_project:python-cryptography:*:*:*:*:*:*:*:*" + "cpe:2.3:a:cryptography.io:cryptography:*:*:*:*:*:*:*:*", + "cpe:2.3:a:cryptography.io:cryptography:*:*:*:*:*:python:*:*" ], "cvxopt": [ "cpe:2.3:a:cvxopt_project:cvxopt:*:*:*:*:*:python:*:*" @@ -7659,6 +7662,9 @@ "apollo13-framework-extensions": [ "cpe:2.3:a:apollo13themes:apollo13_framework_extensions:*:*:*:*:*:wordpress:*:*" ], + "app-builder": [ + "cpe:2.3:a:appcheap:app_builder:*:*:*:*:*:wordpress:*:*" + ], "apply-online": [ "cpe:2.3:a:spiderteams:applyonline_-_application_form_builder_and_manager:*:*:*:*:*:wordpress:*:*" ], @@ -7881,6 +7887,9 @@ "ays-popup-box": [ "cpe:2.3:a:ays-pro:popup_box:*:*:*:*:*:wordpress:*:*" ], + "azurecurve-toggle-showhide": [ + "cpe:2.3:a:azurecurve:toggle_show\\/hide:*:*:*:*:*:wordpress:*:*" + ], "b2bking-wholesale-for-woocommerce": [ "cpe:2.3:a:webwizards:b2bking:*:*:*:*:*:wordpress:*:*" ], @@ -8064,6 +8073,7 @@ "cpe:2.3:a:bitapps:bit_assist:*:*:*:*:*:wordpress:*:*" ], "bit-form": [ + "cpe:2.3:a:bitapps:bit_form:*:*:*:*:free:wordpress:*:*", "cpe:2.3:a:bitapps:contact_form_builder:*:*:*:*:*:wordpress:*:*" ], "bitcoin-faucet": [ @@ -8078,6 +8088,9 @@ "blackhole-bad-bots": [ "cpe:2.3:a:plugin-planet:blackhole_for_bad_bots:*:*:*:*:*:wordpress:*:*" ], + "block-for-font-awesome": [ + "cpe:2.3:a:getbutterfly:block_for_font_awesome:*:*:*:*:*:wordpress:*:*" + ], "block-options": [ "cpe:2.3:a:extendify:editorskit:*:*:*:*:*:wordpress:*:*" ], @@ -10085,6 +10098,9 @@ "embed-comment-images": [ "cpe:2.3:a:embed_images_in_comments_project:embed_images_in_comments:*:*:*:*:*:wordpress:*:*" ], + "embed-power-bi": [ + "cpe:2.3:a:atlaspolicy:power_bi_embedded:*:*:*:*:*:wordpress:*:*" + ], "embed-swagger": [ "cpe:2.3:a:embed_swagger_project:embed_swagger:*:*:*:*:*:wordpress:*:*" ], @@ -10783,6 +10799,9 @@ "furikake": [ "cpe:2.3:a:furikake_project:furikake:*:*:*:*:*:wordpress:*:*" ], + "fusion-slider": [ + "cpe:2.3:a:webhuntinfotech:universal_slider:*:*:*:*:*:wordpress:*:*" + ], "futurio-extra": [ "cpe:2.3:a:futuriowp:futurio_extra:*:*:*:*:*:wordpress:*:*" ], @@ -12215,6 +12234,9 @@ "login-lockdown": [ "cpe:2.3:a:webfactoryltd:wp_login_lockdown:*:*:*:*:*:wordpress:*:*" ], + "login-logo-editor-by-oizuled": [ + "cpe:2.3:a:amplifyplugins:login_logo_editor:*:*:*:*:*:wordpress:*:*" + ], "login-logout-menu": [ "cpe:2.3:a:wpbrigade:login_logout_menu:*:*:*:*:*:wordpress:*:*" ], @@ -15716,6 +15738,9 @@ "template-events-calendar": [ "cpe:2.3:a:coolplugins:events_shortcodes_for_the_events_calendar:*:*:*:*:*:wordpress:*:*" ], + "template-kit-export": [ + "cpe:2.3:a:envato:template_kit_-_export:*:*:*:*:*:wordpress:*:*" + ], "templately": [ "cpe:2.3:a:templately:templately:*:*:*:*:*:wordpress:*:*" ], @@ -17680,6 +17705,9 @@ "wp-knowledgebase": [ "cpe:2.3:a:wpknowledgebase:wordpress_knowledge_base_\\\u0026_documentation_plugin:*:*:*:*:*:wordpress:*:*" ], + "wp-last-modified-info": [ + "cpe:2.3:a:sayandatta:wp_last_modified_info:*:*:*:*:*:wordpress:*:*" + ], "wp-latest-posts": [ "cpe:2.3:a:joomunited:wp_latest_posts:*:*:*:*:*:wordpress:*:*" ], @@ -18636,6 +18664,9 @@ "yith-woocommerce-product-add-ons": [ "cpe:2.3:a:yithemes:yith_woocommerce_product_add-ons:*:*:*:*:free:wordpress:*:*" ], + "yith-woocommerce-tab-manager": [ + "cpe:2.3:a:yithemes:yith_woocommerce_tab_manager:*:*:*:*:*:wordpress:*:*" + ], "ymc-smart-filter": [ "cpe:2.3:a:ymc-22:filter_\\\u0026_grids:*:*:*:*:*:wordpress:*:*" ], @@ -18714,7 +18745,9 @@ "cpe:2.3:a:zendrop:zendrop:*:*:*:*:*:wordpress:*:*" ], "zephyr-project-manager": [ - "cpe:2.3:a:zephyr_project_manager_project:zephyr_project_manager:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:zephyr-one:zephyr_project_manager:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:zephyr_project_manager_project:zephyr_project_manager:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:zephyrproject:zephyr_project_manager:*:*:*:*:*:wordpress:*:*" ], "zero-bs-crm": [ "cpe:2.3:a:automattic:jetpack_crm:*:*:*:*:*:wordpress:*:*" From dbc4238f63c027efc09ce5fe51e069c1145f6846 Mon Sep 17 00:00:00 2001 From: Laurent Goderre Date: Tue, 10 Sep 2024 10:58:20 -0400 Subject: [PATCH 195/284] Add haskell binaries cataloger (#3078) Signed-off-by: Laurent Goderre --- .../binary/classifier_cataloger_test.go | 22 +++++++++++++ syft/pkg/cataloger/binary/classifiers.go | 30 ++++++++++++++++++ .../haskell-cabal/3.10.3.0/linux-amd64/cabal | Bin 0 -> 350 bytes .../haskell-ghc/9.6.5/linux-amd64/ghc-9.6.5 | Bin 0 -> 353 bytes .../binary/test-fixtures/config.yaml | 16 ++++++++++ 5 files changed, 68 insertions(+) create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/haskell-cabal/3.10.3.0/linux-amd64/cabal create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/haskell-ghc/9.6.5/linux-amd64/ghc-9.6.5 diff --git a/syft/pkg/cataloger/binary/classifier_cataloger_test.go b/syft/pkg/cataloger/binary/classifier_cataloger_test.go index 4e283a56a..c1bfbb322 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger_test.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger_test.go @@ -961,6 +961,28 @@ func Test_Cataloger_PositiveCases(t *testing.T) { Metadata: metadata("swipl-binary"), }, }, + { + logicalFixture: "haskell-ghc/9.6.5/linux-amd64", + expected: pkg.Package{ + Name: "haskell/ghc", + Version: "9.6.5", + Type: "binary", + PURL: "pkg:generic/haskell/ghc@9.6.5", + Locations: locations("ghc-9.6.5"), + Metadata: metadata("haskell-ghc-binary"), + }, + }, + { + logicalFixture: "haskell-cabal/3.10.3.0/linux-amd64", + expected: pkg.Package{ + Name: "haskell/cabal", + Version: "3.10.3.0", + Type: "binary", + PURL: "pkg:generic/haskell/cabal@3.10.3.0", + Locations: locations("cabal"), + Metadata: metadata("haskell-cabal-binary"), + }, + }, { logicalFixture: "nginx/1.25.1/linux-amd64", expected: pkg.Package{ diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index 46afa87f5..5290b4d98 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -447,6 +447,36 @@ func DefaultClassifiers() []Classifier { PURL: mustPURL("pkg:generic/swipl@version"), CPEs: singleCPE("cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, + { + Class: "haskell-ghc-binary", + FileGlob: "**/ghc*", + EvidenceMatcher: FileContentsVersionMatcher( + `(?m)\x00GHC (?P[0-9]+\.[0-9]+\.[0-9]+)\x00`, + ), + Package: "haskell/ghc", + PURL: mustPURL("pkg:generic/haskell/ghc@version"), + CPEs: singleCPE("cpe:2.3:a:haskell:ghc:*:*:*:*:*:*:*:*"), + }, + { + Class: "haskell-cabal-binary", + FileGlob: "**/cabal", + EvidenceMatcher: FileContentsVersionMatcher( + `(?m)\x00Cabal-(?P[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?)-`, + ), + Package: "haskell/cabal", + PURL: mustPURL("pkg:generic/haskell/cabal@version"), + CPEs: singleCPE("cpe:2.3:a:haskell:cabal:*:*:*:*:*:*:*:*"), + }, + { + Class: "haskell-stack-binary", + FileGlob: "**/stack", + EvidenceMatcher: FileContentsVersionMatcher( + `(?m)Version\s*(?P[0-9]+\.[0-9]+\.[0-9]+),\s*Git`, + ), + Package: "haskell/stack", + PURL: mustPURL("pkg:generic/haskell/stack@version"), + CPEs: singleCPE("cpe:2.3:a:haskell:stack:*:*:*:*:*:*:*:*"), + }, { Class: "consul-binary", FileGlob: "**/consul", diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/haskell-cabal/3.10.3.0/linux-amd64/cabal b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/haskell-cabal/3.10.3.0/linux-amd64/cabal new file mode 100644 index 0000000000000000000000000000000000000000..efc08c38af003803204a2647b785bfd5834dc757 GIT binary patch literal 350 zcmb7?5Loj5kGC4gE(U=`cTxNTf%$<9`e1IP0%Y6~0pd$s|j0U~eo?vyuRC8!`XDTU6G zf;FJmt97fz3?T+XCd@J=K~h+EugL}}HBJHuY|7HkND9pq zYVVYuHgFIbTb6~V&w>2sO+GrOUTgp0vtp$;aUG?e;@W0@EN#EL|K5BtLP=qSyp(p- Vm~ne3=XfjWef+_Qr$+rh;1>r0X=DHZ literal 0 HcmV?d00001 diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/haskell-ghc/9.6.5/linux-amd64/ghc-9.6.5 b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/haskell-ghc/9.6.5/linux-amd64/ghc-9.6.5 new file mode 100644 index 0000000000000000000000000000000000000000..551b9978c44ce488763aaccc19ff43a019c84c31 GIT binary patch literal 353 zcmXv~v2Mg53}t4h)IUIX%T;O+U?7mSLvQcc35dBwmm{YpQq@oFUzMb-2g}dT@5y!v zH|*GDNR8)~8#?E_;My_S8sn9u6PC+5RICJD%6Pxy`Zfe*Y{$SEXwhMmR_Tm7^&r70 z516FSPGOK9werfx)&)$ihoGgky=avcBGNog_;03_N-0~++GdSL%ie`xbWSaT>#G}} z2*UXc#z2B3LRCZr5usuiC_NsJEPk!X{?=sc%WTR)!5q8Sgvd=d9L_$dOtMNxvsigu@cw_?zrNzsejw`hv$7@#gE&jsl4Wr H+l~JL51U@J literal 0 HcmV?d00001 diff --git a/syft/pkg/cataloger/binary/test-fixtures/config.yaml b/syft/pkg/cataloger/binary/test-fixtures/config.yaml index ac433555c..58408325b 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/config.yaml +++ b/syft/pkg/cataloger/binary/test-fixtures/config.yaml @@ -78,6 +78,22 @@ from-images: paths: - /usr/lib/swipl/bin/x86_64-linux/swipl + - name: haskell-ghc + version: 9.6.5 + images: + - ref: haskell:9.6.5-slim-buster@sha256:04a7293eb792b82335dffa7f08532657517ed9b4f01d52c1b499ad22deb3c6b1 + platform: linux/amd64 + paths: + - /opt/ghc/9.6.5/lib/ghc-9.6.5/bin/ghc-9.6.5 + + - name: haskell-cabal + version: 3.10.3.0 + images: + - ref: haskell:9.6.5-slim-buster@sha256:04a7293eb792b82335dffa7f08532657517ed9b4f01d52c1b499ad22deb3c6b1 + platform: linux/amd64 + paths: + - /usr/local/bin/cabal + - version: 1.21.3 images: - ref: golang:1.21.3@sha256:3ce8313c3513515040870c55e0c041a2b94f3576a58cfd3948633604214aa811 From c33a51d3d839ba619ea2217ee00a56be23f9fb9f Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Tue, 10 Sep 2024 15:19:05 -0400 Subject: [PATCH 196/284] chore: restore ci-check.sh script (#3218) Signed-off-by: Keith Zantow --- .github/scripts/ci-check.sh | 11 +++++++++++ Taskfile.yaml | 11 +---------- 2 files changed, 12 insertions(+), 10 deletions(-) create mode 100644 .github/scripts/ci-check.sh diff --git a/.github/scripts/ci-check.sh b/.github/scripts/ci-check.sh new file mode 100644 index 000000000..0ab83a318 --- /dev/null +++ b/.github/scripts/ci-check.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +red=$(tput setaf 1) +bold=$(tput bold) +normal=$(tput sgr0) + +# assert we are running in CI (or die!) +if [[ -z "$CI" ]]; then + echo "${bold}${red}This step should ONLY be run in CI. Exiting...${normal}" + exit 1 +fi diff --git a/Taskfile.yaml b/Taskfile.yaml index feb12f636..5e7f2c000 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -593,16 +593,7 @@ tasks: ci-check: # desc: "[CI only] Are you in CI?" cmds: - - cmd: | - red=$(tput setaf 1) - bold=$(tput bold) - normal=$(tput sgr0) - - # assert we are running in CI (or die!) - if [[ -z "$CI" ]]; then - echo "${bold}${red}This step should ONLY be run in CI. Exiting...${normal}" - exit 1 - fi + - cmd: .github/scripts/ci-check.sh silent: true ci-release: From 61a9fde01c9d5409898c4ae0a94bb7078428538c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 21:20:43 +0000 Subject: [PATCH 197/284] chore(deps): bump github.com/opencontainers/runc from 1.1.12 to 1.1.14 (#3219) Bumps [github.com/opencontainers/runc](https://github.com/opencontainers/runc) from 1.1.12 to 1.1.14. - [Release notes](https://github.com/opencontainers/runc/releases) - [Changelog](https://github.com/opencontainers/runc/blob/main/CHANGELOG.md) - [Commits](https://github.com/opencontainers/runc/compare/v1.1.12...v1.1.14) --- updated-dependencies: - dependency-name: github.com/opencontainers/runc dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 30a9bb0e1..29c60e19d 100644 --- a/go.mod +++ b/go.mod @@ -181,7 +181,7 @@ require ( github.com/ncruces/go-strftime v0.1.9 // indirect github.com/nwaples/rardecode v1.1.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect - github.com/opencontainers/runc v1.1.12 // indirect + github.com/opencontainers/runc v1.1.14 // indirect github.com/opencontainers/runtime-spec v1.1.0-rc.1 // indirect github.com/opencontainers/selinux v1.11.0 // indirect github.com/pborman/indent v1.2.1 // indirect diff --git a/go.sum b/go.sum index 3d6c2b9f1..9e2e0333b 100644 --- a/go.sum +++ b/go.sum @@ -609,8 +609,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= -github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= -github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= +github.com/opencontainers/runc v1.1.14 h1:rgSuzbmgz5DUJjeSnw337TxDbRuqjs6iqQck/2weR6w= +github.com/opencontainers/runc v1.1.14/go.mod h1:E4C2z+7BxR7GHXp0hAY53mek+x49X1LjPNeMTfRGvOA= github.com/opencontainers/runtime-spec v1.1.0-rc.1 h1:wHa9jroFfKGQqFHj0I1fMRKLl0pfj+ynAqBxo3v6u9w= github.com/opencontainers/runtime-spec v1.1.0-rc.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= From fcd5ec951de6b3fc1f1aa2a36968356d2eb22170 Mon Sep 17 00:00:00 2001 From: Ryuichi Okumura Date: Wed, 11 Sep 2024 23:02:37 +0900 Subject: [PATCH 198/284] chore: make ci-check.sh an executable file (#3220) Signed-off-by: Ryuichi Okumura --- .github/scripts/ci-check.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 .github/scripts/ci-check.sh diff --git a/.github/scripts/ci-check.sh b/.github/scripts/ci-check.sh old mode 100644 new mode 100755 From 1b863268df8945a7bfcf7f27272c1b1fa8e34371 Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Thu, 12 Sep 2024 10:45:18 -0400 Subject: [PATCH 199/284] feat: --enrich flag for data enrichment feature enablement (#3182) Signed-off-by: Keith Zantow --- cmd/syft/internal/options/catalog.go | 99 ++++++++++++++++++----- cmd/syft/internal/options/catalog_test.go | 66 +++++++++++++++ cmd/syft/internal/options/golang.go | 8 +- cmd/syft/internal/options/java.go | 8 +- cmd/syft/internal/options/javascript.go | 2 +- go.mod | 24 +++--- go.sum | 52 ++++++------ internal/task/package_tasks.go | 31 +++++-- 8 files changed, 217 insertions(+), 73 deletions(-) diff --git a/cmd/syft/internal/options/catalog.go b/cmd/syft/internal/options/catalog.go index 99359abec..8d1851860 100644 --- a/cmd/syft/internal/options/catalog.go +++ b/cmd/syft/internal/options/catalog.go @@ -11,6 +11,7 @@ import ( "github.com/anchore/fangs" intFile "github.com/anchore/syft/internal/file" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/task" "github.com/anchore/syft/syft" "github.com/anchore/syft/syft/cataloging" "github.com/anchore/syft/syft/cataloging/filecataloging" @@ -36,6 +37,7 @@ type Catalog struct { Scope string `yaml:"scope" json:"scope" mapstructure:"scope"` Parallelism int `yaml:"parallelism" json:"parallelism" mapstructure:"parallelism"` // the number of catalog workers to run in parallel Relationships relationshipsConfig `yaml:"relationships" json:"relationships" mapstructure:"relationships"` + Enrich []string `yaml:"enrich" json:"enrich" mapstructure:"enrich"` // ecosystem-specific cataloger configuration Golang golangConfig `yaml:"golang" json:"golang" mapstructure:"golang"` @@ -55,7 +57,7 @@ type Catalog struct { var _ interface { clio.FlagAdder clio.PostLoader - fangs.FieldDescriber + clio.FieldDescriber } = (*Catalog)(nil) func DefaultCatalog() Catalog { @@ -130,9 +132,9 @@ func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config { return pkgcataloging.Config{ Binary: binary.DefaultClassifierCatalogerConfig(), Golang: golang.DefaultCatalogerConfig(). - WithSearchLocalModCacheLicenses(cfg.Golang.SearchLocalModCacheLicenses). + WithSearchLocalModCacheLicenses(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Go, task.Golang), cfg.Golang.SearchLocalModCacheLicenses)). WithLocalModCacheDir(cfg.Golang.LocalModCacheDir). - WithSearchRemoteLicenses(cfg.Golang.SearchRemoteLicenses). + WithSearchRemoteLicenses(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Go, task.Golang), cfg.Golang.SearchRemoteLicenses)). WithProxy(cfg.Golang.Proxy). WithNoProxy(cfg.Golang.NoProxy). WithMainModuleVersion( @@ -142,7 +144,7 @@ func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config { WithFromLDFlags(cfg.Golang.MainModuleVersion.FromLDFlags), ), JavaScript: javascript.DefaultCatalogerConfig(). - WithSearchRemoteLicenses(cfg.JavaScript.SearchRemoteLicenses). + WithSearchRemoteLicenses(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.JavaScript, task.Node, task.NPM), cfg.JavaScript.SearchRemoteLicenses)). WithNpmBaseURL(cfg.JavaScript.NpmBaseURL), LinuxKernel: kernel.LinuxKernelCatalogerConfig{ CatalogModules: cfg.LinuxKernel.CatalogModules, @@ -151,9 +153,9 @@ func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config { GuessUnpinnedRequirements: cfg.Python.GuessUnpinnedRequirements, }, JavaArchive: java.DefaultArchiveCatalogerConfig(). - WithUseMavenLocalRepository(cfg.Java.UseMavenLocalRepository). + WithUseMavenLocalRepository(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Java, task.Maven), cfg.Java.UseMavenLocalRepository)). WithMavenLocalRepositoryDir(cfg.Java.MavenLocalRepositoryDir). - WithUseNetwork(cfg.Java.UseNetwork). + WithUseNetwork(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Java, task.Maven), cfg.Java.UseNetwork)). WithMavenBaseURL(cfg.Java.MavenURL). WithArchiveTraversal(archiveSearch, cfg.Java.MaxParentRecursiveDepth), } @@ -193,6 +195,9 @@ func (cfg *Catalog) AddFlags(flags clio.FlagSet) { flags.StringArrayVarP(&cfg.SelectCatalogers, "select-catalogers", "", "add, remove, and filter the catalogers to be used") + flags.StringArrayVarP(&cfg.Enrich, "enrich", "", + fmt.Sprintf("enable package data enrichment from local and online sources (options: %s)", strings.Join(publicisedEnrichmentOptions, ", "))) + flags.StringVarP(&cfg.Source.Name, "source-name", "", "set the name of the target being analyzed") @@ -205,6 +210,10 @@ func (cfg *Catalog) AddFlags(flags clio.FlagSet) { func (cfg *Catalog) DescribeFields(descriptions fangs.FieldDescriptionSet) { descriptions.Add(&cfg.Parallelism, "number of cataloger workers to run in parallel") + + descriptions.Add(&cfg.Enrich, fmt.Sprintf(`Enable data enrichment operations, which can utilize services such as Maven Central and NPM. +By default all enrichment is disabled, use: all to enable everything. +Available options are: %s`, strings.Join(publicisedEnrichmentOptions, ", "))) } func (cfg *Catalog) PostLoad() error { @@ -215,23 +224,12 @@ func (cfg *Catalog) PostLoad() error { return fmt.Errorf("cannot use both 'catalogers' and 'select-catalogers'/'default-catalogers' flags") } - flatten := func(l []string) []string { - var out []string - for _, v := range l { - for _, s := range strings.Split(v, ",") { - out = append(out, strings.TrimSpace(s)) - } - } - sort.Strings(out) - - return out - } - cfg.From = flatten(cfg.From) cfg.Catalogers = flatten(cfg.Catalogers) cfg.DefaultCatalogers = flatten(cfg.DefaultCatalogers) cfg.SelectCatalogers = flatten(cfg.SelectCatalogers) + cfg.Enrich = flatten(cfg.Enrich) // for backwards compatibility cfg.DefaultCatalogers = append(cfg.DefaultCatalogers, cfg.Catalogers...) @@ -243,3 +241,68 @@ func (cfg *Catalog) PostLoad() error { return nil } + +func flatten(commaSeparatedEntries []string) []string { + var out []string + for _, v := range commaSeparatedEntries { + for _, s := range strings.Split(v, ",") { + out = append(out, strings.TrimSpace(s)) + } + } + sort.Strings(out) + return out +} + +var publicisedEnrichmentOptions = []string{ + "all", + task.Golang, + task.Java, + task.JavaScript, +} + +func enrichmentEnabled(enrichDirectives []string, features ...string) *bool { + if len(enrichDirectives) == 0 { + return nil + } + + enabled := func(features ...string) *bool { + for _, directive := range enrichDirectives { + enable := true + directive = strings.TrimPrefix(directive, "+") // +java and java are equivalent + if strings.HasPrefix(directive, "-") { + directive = directive[1:] + enable = false + } + for _, feature := range features { + if directive == feature { + return &enable + } + } + } + return nil + } + + enableAll := enabled("all") + disableAll := enabled("none") + + if disableAll != nil && *disableAll { + if enableAll != nil { + log.Warn("you have specified to both enable and disable all enrichment functionality, defaulting to disabled") + } + enableAll = ptr(false) + } + + // check for explicit enable/disable of feature names + for _, feat := range features { + enableFeature := enabled(feat) + if enableFeature != nil { + return enableFeature + } + } + + return enableAll +} + +func ptr[T any](val T) *T { + return &val +} diff --git a/cmd/syft/internal/options/catalog_test.go b/cmd/syft/internal/options/catalog_test.go index f9a54249a..cf02630bf 100644 --- a/cmd/syft/internal/options/catalog_test.go +++ b/cmd/syft/internal/options/catalog_test.go @@ -70,3 +70,69 @@ func TestCatalog_PostLoad(t *testing.T) { }) } } + +func Test_enrichmentEnabled(t *testing.T) { + tests := []struct { + directives string + test string + expected *bool + }{ + { + directives: "", + test: "java", + expected: nil, + }, + { + directives: "none", + test: "java", + expected: ptr(false), + }, + { + directives: "none,+java", + test: "java", + expected: ptr(true), + }, + { + directives: "all,none", + test: "java", + expected: ptr(false), + }, + { + directives: "all", + test: "java", + expected: ptr(true), + }, + { + directives: "golang,js", + test: "java", + expected: nil, + }, + { + directives: "golang,-js,java", + test: "java", + expected: ptr(true), + }, + { + directives: "golang,js,-java", + test: "java", + expected: ptr(false), + }, + { + directives: "all", + test: "java", + expected: ptr(true), + }, + { + directives: "all,-java", + test: "java", + expected: ptr(false), + }, + } + + for _, test := range tests { + t.Run(test.directives, func(t *testing.T) { + got := enrichmentEnabled(flatten([]string{test.directives}), test.test) + assert.Equal(t, test.expected, got) + }) + } +} diff --git a/cmd/syft/internal/options/golang.go b/cmd/syft/internal/options/golang.go index 63ac1bcc7..59fe421fe 100644 --- a/cmd/syft/internal/options/golang.go +++ b/cmd/syft/internal/options/golang.go @@ -8,9 +8,9 @@ import ( ) type golangConfig struct { - SearchLocalModCacheLicenses bool `json:"search-local-mod-cache-licenses" yaml:"search-local-mod-cache-licenses" mapstructure:"search-local-mod-cache-licenses"` + SearchLocalModCacheLicenses *bool `json:"search-local-mod-cache-licenses" yaml:"search-local-mod-cache-licenses" mapstructure:"search-local-mod-cache-licenses"` LocalModCacheDir string `json:"local-mod-cache-dir" yaml:"local-mod-cache-dir" mapstructure:"local-mod-cache-dir"` - SearchRemoteLicenses bool `json:"search-remote-licenses" yaml:"search-remote-licenses" mapstructure:"search-remote-licenses"` + SearchRemoteLicenses *bool `json:"search-remote-licenses" yaml:"search-remote-licenses" mapstructure:"search-remote-licenses"` Proxy string `json:"proxy" yaml:"proxy" mapstructure:"proxy"` NoProxy string `json:"no-proxy" yaml:"no-proxy" mapstructure:"no-proxy"` MainModuleVersion golangMainModuleVersionConfig `json:"main-module-version" yaml:"main-module-version" mapstructure:"main-module-version"` @@ -47,9 +47,9 @@ type golangMainModuleVersionConfig struct { func defaultGolangConfig() golangConfig { def := golang.DefaultCatalogerConfig() return golangConfig{ - SearchLocalModCacheLicenses: def.SearchLocalModCacheLicenses, + SearchLocalModCacheLicenses: nil, // this defaults to false, which is the API default LocalModCacheDir: def.LocalModCacheDir, - SearchRemoteLicenses: def.SearchRemoteLicenses, + SearchRemoteLicenses: nil, // this defaults to false, which is the API default Proxy: strings.Join(def.Proxies, ","), NoProxy: strings.Join(def.NoProxy, ","), MainModuleVersion: golangMainModuleVersionConfig{ diff --git a/cmd/syft/internal/options/java.go b/cmd/syft/internal/options/java.go index 8894c760b..6244de44f 100644 --- a/cmd/syft/internal/options/java.go +++ b/cmd/syft/internal/options/java.go @@ -6,8 +6,8 @@ import ( ) type javaConfig struct { - UseNetwork bool `yaml:"use-network" json:"use-network" mapstructure:"use-network"` - UseMavenLocalRepository bool `yaml:"use-maven-local-repository" json:"use-maven-local-repository" mapstructure:"use-maven-local-repository"` + UseNetwork *bool `yaml:"use-network" json:"use-network" mapstructure:"use-network"` + UseMavenLocalRepository *bool `yaml:"use-maven-local-repository" json:"use-maven-local-repository" mapstructure:"use-maven-local-repository"` MavenLocalRepositoryDir string `yaml:"maven-local-repository-dir" json:"maven-local-repository-dir" mapstructure:"maven-local-repository-dir"` MavenURL string `yaml:"maven-url" json:"maven-url" mapstructure:"maven-url"` MaxParentRecursiveDepth int `yaml:"max-parent-recursive-depth" json:"max-parent-recursive-depth" mapstructure:"max-parent-recursive-depth"` @@ -17,9 +17,9 @@ func defaultJavaConfig() javaConfig { def := java.DefaultArchiveCatalogerConfig() return javaConfig{ - UseNetwork: def.UseNetwork, + UseNetwork: nil, // this defaults to false, which is the API default MaxParentRecursiveDepth: def.MaxParentRecursiveDepth, - UseMavenLocalRepository: def.UseMavenLocalRepository, + UseMavenLocalRepository: nil, // this defaults to false, which is the API default MavenLocalRepositoryDir: def.MavenLocalRepositoryDir, MavenURL: def.MavenBaseURL, } diff --git a/cmd/syft/internal/options/javascript.go b/cmd/syft/internal/options/javascript.go index 5f88c0f33..e618037cc 100644 --- a/cmd/syft/internal/options/javascript.go +++ b/cmd/syft/internal/options/javascript.go @@ -3,7 +3,7 @@ package options import "github.com/anchore/clio" type javaScriptConfig struct { - SearchRemoteLicenses bool `json:"search-remote-licenses" yaml:"search-remote-licenses" mapstructure:"search-remote-licenses"` + SearchRemoteLicenses *bool `json:"search-remote-licenses" yaml:"search-remote-licenses" mapstructure:"search-remote-licenses"` NpmBaseURL string `json:"npm-base-url" yaml:"npm-base-url" mapstructure:"npm-base-url"` } diff --git a/go.mod b/go.mod index 29c60e19d..38b4a8300 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/acobaugh/osrelease v0.1.0 github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9 github.com/anchore/clio v0.0.0-20240522144804-d81e109008aa - github.com/anchore/fangs v0.0.0-20240508143433-f016b099950f + github.com/anchore/fangs v0.0.0-20240903175602-e716ef12c23d github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537 github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb @@ -84,7 +84,7 @@ require ( modernc.org/sqlite v1.33.0 ) -require google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect +require google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect require ( github.com/BurntSushi/toml v1.4.0 @@ -135,13 +135,13 @@ require ( github.com/emirpasic/gods v1.18.1 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/felixge/fgprof v0.9.3 // indirect - github.com/felixge/httpsnoop v1.0.3 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.4 // indirect github.com/gkampitakis/ciinfo v0.3.0 // indirect github.com/gkampitakis/go-diff v1.3.2 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-restruct/restruct v1.2.0-alpha // indirect github.com/gogo/protobuf v1.3.2 // indirect @@ -185,7 +185,7 @@ require ( github.com/opencontainers/runtime-spec v1.1.0-rc.1 // indirect github.com/opencontainers/selinux v1.11.0 // indirect github.com/pborman/indent v1.2.1 // indirect - github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pierrec/lz4/v4 v4.1.19 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -204,7 +204,7 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/cast v1.7.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.18.2 // indirect + github.com/spf13/viper v1.19.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/sylabs/sif/v2 v2.17.1 // indirect github.com/sylabs/squashfs v1.0.0 // indirect @@ -221,10 +221,10 @@ require ( github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect - go.opentelemetry.io/otel v1.19.0 // indirect - go.opentelemetry.io/otel/metric v1.19.0 // indirect - go.opentelemetry.io/otel/trace v1.19.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/crypto v0.27.0 // indirect @@ -234,8 +234,8 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect - google.golang.org/grpc v1.59.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect + google.golang.org/grpc v1.62.1 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect diff --git a/go.sum b/go.sum index 9e2e0333b..d4b999ae8 100644 --- a/go.sum +++ b/go.sum @@ -99,8 +99,8 @@ github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9 h1:p0ZIe0htYOX284Y4 github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9/go.mod h1:3ZsFB9tzW3vl4gEiUeuSOMDnwroWxIxJelOOHUp8dSw= github.com/anchore/clio v0.0.0-20240522144804-d81e109008aa h1:pwlAn4O9SBUnlgfa69YcqIynbUyobLVFYu8HxSoCffA= github.com/anchore/clio v0.0.0-20240522144804-d81e109008aa/go.mod h1:nD3H5uIvjxlfmakOBgtyFQbk5Zjp3l538kxfpHPslzI= -github.com/anchore/fangs v0.0.0-20240508143433-f016b099950f h1:NOhzafCyNYFi88qxkBFjMzQo4dRa1vDhBzx+0Uovx8Q= -github.com/anchore/fangs v0.0.0-20240508143433-f016b099950f/go.mod h1:sVpRS2yNCw6tLVpvA1QSDVWTJVpCuAm8JNZgn4Sjz/k= +github.com/anchore/fangs v0.0.0-20240903175602-e716ef12c23d h1:ZD4wdCBgJJzJybjTUIEiiupLF7B9H3WLuBTjspBO2Mc= +github.com/anchore/fangs v0.0.0-20240903175602-e716ef12c23d/go.mod h1:Xh4ObY3fmoMzOEVXwDtS1uK44JC7+nRD0n29/1KYFYg= github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537 h1:GjNGuwK5jWjJMyVppBjYS54eOiiSNv4Ba869k4wh72Q= github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537/go.mod h1:1aiktV46ATCkuVg0O573ZrH56BUawTECPETbZyBcqT8= github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a h1:nJ2G8zWKASyVClGVgG7sfM5mwoZlZ2zYpIzN2OhjWkw= @@ -275,8 +275,8 @@ github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA= github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI= github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= @@ -313,8 +313,8 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-restruct/restruct v1.2.0-alpha h1:2Lp474S/9660+SJjpVxoKuWX09JsXHSrdV7Nv3/gkvc= @@ -622,8 +622,8 @@ github.com/pborman/indent v1.2.1/go.mod h1:FitS+t35kIYtB5xWTZAPhnmrxcciEEOdbyrrp github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.19 h1:tYLzDnjDXh9qIxSTKHwXwOYmm9d887Y7Y1ZkyXYHAN4= github.com/pierrec/lz4/v4 v4.1.19/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= @@ -731,8 +731,8 @@ github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= -github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= -github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -824,20 +824,20 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZx8cOF0+Kkazoc7lwUNMGy0LrzEMxTm4BbTxg= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q= -go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= -go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= -go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= -go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= -go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= -go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= @@ -1261,12 +1261,12 @@ google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ= -google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY= -google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo= -google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= +google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= +google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= +google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 h1:rIo7ocm2roD9DcFIX67Ym8icoGCKSARAiPljFhh5suQ= +google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c h1:lfpJ/2rWPa/kJgxyyXM8PrNnfCzcmxJ265mADgwmvLI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1294,8 +1294,8 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= +google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= diff --git a/internal/task/package_tasks.go b/internal/task/package_tasks.go index 4d56dc88a..c38299f4d 100644 --- a/internal/task/package_tasks.go +++ b/internal/task/package_tasks.go @@ -34,6 +34,21 @@ import ( "github.com/anchore/syft/syft/pkg/cataloger/wordpress" ) +const ( + // Java ecosystem labels + Java = "java" + Maven = "maven" + + // Go ecosystem labels + Go = "go" + Golang = "golang" + + // JavaScript ecosystem labels + JavaScript = "javascript" + Node = "node" + NPM = "npm" +) + //nolint:funlen func DefaultPackageTaskFactories() PackageTaskFactories { return []packageTaskFactory{ @@ -49,7 +64,7 @@ func DefaultPackageTaskFactories() PackageTaskFactories { // language-specific package installed catalogers /////////////////////////////////////////////////////////////////////////// newSimplePackageTaskFactory(cpp.NewConanInfoCataloger, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, "cpp", "conan"), - newSimplePackageTaskFactory(javascript.NewPackageCataloger, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, "javascript", "node"), + newSimplePackageTaskFactory(javascript.NewPackageCataloger, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, JavaScript, Node), newSimplePackageTaskFactory(php.NewComposerInstalledCataloger, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, "php", "composer"), newSimplePackageTaskFactory(r.NewPackageCataloger, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, "r"), newSimplePackageTaskFactory(ruby.NewInstalledGemSpecCataloger, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, "ruby", "gem", "gemspec"), @@ -67,20 +82,20 @@ func DefaultPackageTaskFactories() PackageTaskFactories { func(cfg CatalogingFactoryConfig) pkg.Cataloger { return golang.NewGoModuleFileCataloger(cfg.PackagesConfig.Golang) }, - pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "go", "golang", "gomod", + pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, Go, Golang, "gomod", ), - newSimplePackageTaskFactory(java.NewGradleLockfileCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "java", "gradle"), + newSimplePackageTaskFactory(java.NewGradleLockfileCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, Java, "gradle"), newPackageTaskFactory( func(cfg CatalogingFactoryConfig) pkg.Cataloger { return java.NewPomCataloger(cfg.PackagesConfig.JavaArchive) }, - pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "java", "maven", + pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, Java, Maven, ), newPackageTaskFactory( func(cfg CatalogingFactoryConfig) pkg.Cataloger { return javascript.NewLockCataloger(cfg.PackagesConfig.JavaScript) }, - pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "javascript", "node", "npm", + pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, JavaScript, Node, NPM, ), newSimplePackageTaskFactory(php.NewComposerLockCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "php", "composer"), newSimplePackageTaskFactory(php.NewPeclCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, pkgcataloging.ImageTag, "php", "pecl"), @@ -105,15 +120,15 @@ func DefaultPackageTaskFactories() PackageTaskFactories { func(cfg CatalogingFactoryConfig) pkg.Cataloger { return golang.NewGoModuleBinaryCataloger(cfg.PackagesConfig.Golang) }, - pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, "go", "golang", "gomod", "binary", + pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, Go, Golang, "gomod", "binary", ), newPackageTaskFactory( func(cfg CatalogingFactoryConfig) pkg.Cataloger { return java.NewArchiveCataloger(cfg.PackagesConfig.JavaArchive) }, - pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, "java", "maven", + pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, Java, Maven, ), - newSimplePackageTaskFactory(java.NewNativeImageCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, "java"), + newSimplePackageTaskFactory(java.NewNativeImageCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, Java), newSimplePackageTaskFactory(nix.NewStoreCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, "nix"), newSimplePackageTaskFactory(lua.NewPackageCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, "lua"), From 38e51f16ec36565f5b7ebe0e8c64d8880643b7a2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2024 11:30:58 -0400 Subject: [PATCH 200/284] chore(deps): bump modernc.org/sqlite from 1.33.0 to 1.33.1 (#3229) Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.33.0 to 1.33.1. - [Commits](https://gitlab.com/cznic/sqlite/compare/v1.33.0...v1.33.1) --- updated-dependencies: - dependency-name: modernc.org/sqlite dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 38b4a8300..7068ee0d4 100644 --- a/go.mod +++ b/go.mod @@ -81,7 +81,7 @@ require ( golang.org/x/mod v0.21.0 golang.org/x/net v0.29.0 gopkg.in/yaml.v3 v3.0.1 - modernc.org/sqlite v1.33.0 + modernc.org/sqlite v1.33.1 ) require google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect diff --git a/go.sum b/go.sum index d4b999ae8..7b71bbe47 100644 --- a/go.sum +++ b/go.sum @@ -1344,8 +1344,14 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ= +modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= +modernc.org/ccgo/v4 v4.19.2 h1:lwQZgvboKD0jBwdaeVCTouxhxAyN6iawF3STraAal8Y= +modernc.org/ccgo/v4 v4.19.2/go.mod h1:ysS3mxiMV38XGRTTcgo0DQTeTmAO4oCmJl1nX9VFI3s= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= +modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= +modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U= @@ -1354,8 +1360,12 @@ modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= -modernc.org/sqlite v1.33.0 h1:WWkA/T2G17okiLGgKAj4/RMIvgyMT19yQ038160IeYk= -modernc.org/sqlite v1.33.0/go.mod h1:9uQ9hF/pCZoYZK73D/ud5Z7cIRIILSZI8NdIemVMTX8= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= +modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= +modernc.org/sqlite v1.33.1 h1:trb6Z3YYoeM9eDL1O8do81kP+0ejv+YzgyFo+Gwy0nM= +modernc.org/sqlite v1.33.1/go.mod h1:pXV2xHxhzXZsgT/RtTFAPY6JJDEvOTcTdwADQCCWD4k= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= From 2b4d5c275f0b15b7374913d5781bd62b7844af43 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2024 11:31:09 -0400 Subject: [PATCH 201/284] chore(deps): bump peter-evans/create-pull-request from 7.0.1 to 7.0.2 (#3226) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.1 to 7.0.2. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/8867c4aba1b742c39f8d0ba35429c2dfa4b6cb20...d121e62763d8cc35b5fb1710e887d6e69a52d3a4) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-bootstrap-tools.yml | 2 +- .github/workflows/update-cpe-dictionary-index.yml | 2 +- .github/workflows/update-stereoscope-release.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/update-bootstrap-tools.yml b/.github/workflows/update-bootstrap-tools.yml index 3cdedf52a..e6fd35974 100644 --- a/.github/workflows/update-bootstrap-tools.yml +++ b/.github/workflows/update-bootstrap-tools.yml @@ -49,7 +49,7 @@ jobs: app_id: ${{ secrets.TOKEN_APP_ID }} private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@8867c4aba1b742c39f8d0ba35429c2dfa4b6cb20 #v7.0.1 + - uses: peter-evans/create-pull-request@d121e62763d8cc35b5fb1710e887d6e69a52d3a4 #v7.0.2 with: signoff: true delete-branch: true diff --git a/.github/workflows/update-cpe-dictionary-index.yml b/.github/workflows/update-cpe-dictionary-index.yml index cec2d9399..024755ffe 100644 --- a/.github/workflows/update-cpe-dictionary-index.yml +++ b/.github/workflows/update-cpe-dictionary-index.yml @@ -33,7 +33,7 @@ jobs: app_id: ${{ secrets.TOKEN_APP_ID }} private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@8867c4aba1b742c39f8d0ba35429c2dfa4b6cb20 #v7.0.1 + - uses: peter-evans/create-pull-request@d121e62763d8cc35b5fb1710e887d6e69a52d3a4 #v7.0.2 with: signoff: true delete-branch: true diff --git a/.github/workflows/update-stereoscope-release.yml b/.github/workflows/update-stereoscope-release.yml index 1a3e22623..a0c97eaa6 100644 --- a/.github/workflows/update-stereoscope-release.yml +++ b/.github/workflows/update-stereoscope-release.yml @@ -44,7 +44,7 @@ jobs: app_id: ${{ secrets.TOKEN_APP_ID }} private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@8867c4aba1b742c39f8d0ba35429c2dfa4b6cb20 #v7.0.1 + - uses: peter-evans/create-pull-request@d121e62763d8cc35b5fb1710e887d6e69a52d3a4 #v7.0.2 with: signoff: true delete-branch: true From 834027e32d523c627a5d9014b50e83f12d0fd78c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2024 13:51:17 -0400 Subject: [PATCH 202/284] chore(deps): bump github.com/charmbracelet/bubbletea from 1.1.0 to 1.1.1 (#3225) Bumps [github.com/charmbracelet/bubbletea](https://github.com/charmbracelet/bubbletea) from 1.1.0 to 1.1.1. - [Release notes](https://github.com/charmbracelet/bubbletea/releases) - [Changelog](https://github.com/charmbracelet/bubbletea/blob/main/.goreleaser.yml) - [Commits](https://github.com/charmbracelet/bubbletea/compare/v1.1.0...v1.1.1) --- updated-dependencies: - dependency-name: github.com/charmbracelet/bubbletea dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7068ee0d4..0e72b1b84 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 github.com/bmatcuk/doublestar/v4 v4.6.1 github.com/charmbracelet/bubbles v0.20.0 - github.com/charmbracelet/bubbletea v1.1.0 + github.com/charmbracelet/bubbletea v1.1.1 github.com/charmbracelet/lipgloss v0.13.0 github.com/dave/jennifer v1.7.1 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da diff --git a/go.sum b/go.sum index 7b71bbe47..0751642fa 100644 --- a/go.sum +++ b/go.sum @@ -159,8 +159,8 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE= github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU= -github.com/charmbracelet/bubbletea v1.1.0 h1:FjAl9eAL3HBCHenhz/ZPjkKdScmaS5SK69JAK2YJK9c= -github.com/charmbracelet/bubbletea v1.1.0/go.mod h1:9Ogk0HrdbHolIKHdjfFpyXJmiCzGwy+FesYkZr7hYU4= +github.com/charmbracelet/bubbletea v1.1.1 h1:KJ2/DnmpfqFtDNVTvYZ6zpPFL9iRCRr0qqKOCvppbPY= +github.com/charmbracelet/bubbletea v1.1.1/go.mod h1:9Ogk0HrdbHolIKHdjfFpyXJmiCzGwy+FesYkZr7hYU4= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= From 58100fec9f62549426e3ec10d99a49ea1fb8a07f Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2024 15:05:50 -0400 Subject: [PATCH 203/284] chore(deps): update tools to latest versions (#3205) * chore(deps): update tools to latest versions Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * chore: disable gosec(G115) A change to the rule gosec(G115) made a large amount of FP for gosec appear when updating to the latest golang-ci linter. https://github.com/securego/gosec/issues/1185 https://github.com/securego/gosec/pull/1149 We're going to ignore this rule for the time being while waiting for gosec to get updates so that bound checking and example snippets of `valid` code is added for this rule Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> --------- Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 10 +++++----- .golangci.yaml | 3 +++ internal/file/zip_read_closer.go | 4 ++-- syft/file/cataloger/executable/elf.go | 2 +- syft/format/syftjson/to_syft_model.go | 2 +- syft/pkg/cataloger/debian/parse_dpkg_db.go | 2 +- .../cataloger/java/graalvm_native_image_cataloger.go | 6 +++--- syft/pkg/cataloger/php/parse_pecl_serialized.go | 4 ++-- syft/pkg/cataloger/redhat/parse_rpm_archive.go | 4 ++-- 9 files changed, 20 insertions(+), 17 deletions(-) diff --git a/.binny.yaml b/.binny.yaml index cab909d29..7d30d69c5 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -26,7 +26,7 @@ tools: # used for linting - name: golangci-lint version: - want: v1.60.3 + want: v1.61.0 method: github-release with: repo: golangci/golangci-lint @@ -58,7 +58,7 @@ tools: # used to release all artifacts - name: goreleaser version: - want: v2.2.0 + want: v2.3.0 method: github-release with: repo: goreleaser/goreleaser @@ -103,7 +103,7 @@ tools: # used for running all local and CI tasks - name: task version: - want: v3.38.0 + want: v3.39.0 method: github-release with: repo: go-task/task @@ -111,7 +111,7 @@ tools: # used for triggering a release - name: gh version: - want: v2.55.0 + want: v2.56.0 method: github-release with: repo: cli/cli @@ -130,4 +130,4 @@ tools: want: v4.44.3 method: github-release with: - repo: mikefarah/yq \ No newline at end of file + repo: mikefarah/yq diff --git a/.golangci.yaml b/.golangci.yaml index 3ea4697ae..3fefa111c 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -57,6 +57,9 @@ linters-settings: settings: ruleguard: rules: "test/rules/rules.go" + gosec: + excludes: + - G115 output: uniq-by-line: false run: diff --git a/internal/file/zip_read_closer.go b/internal/file/zip_read_closer.go index 5f82a2127..4c0f523e7 100644 --- a/internal/file/zip_read_closer.go +++ b/internal/file/zip_read_closer.go @@ -56,7 +56,7 @@ func OpenZip(filepath string) (*ZipReadCloser, error) { if offset > math.MaxInt64 { return nil, fmt.Errorf("archive start offset too large: %v", offset) } - offset64 := int64(offset) //nolint:gosec // lint bug, checked above: https://github.com/securego/gosec/issues/1187 + offset64 := int64(offset) size := fi.Size() - offset64 @@ -183,7 +183,7 @@ func findDirectory64End(r io.ReaderAt, directoryEndOffset int64) (int64, error) if b.uint32() != 1 { // total number of disks return -1, nil // the file is not a valid zip64-file } - return int64(p), nil //nolint:gosec + return int64(p), nil } // readDirectory64End reads the zip64 directory end and updates the diff --git a/syft/file/cataloger/executable/elf.go b/syft/file/cataloger/executable/elf.go index 9c6ad6151..dec6abd34 100644 --- a/syft/file/cataloger/executable/elf.go +++ b/syft/file/cataloger/executable/elf.go @@ -175,7 +175,7 @@ func hasElfDynTag(f *elf.File, tag elf.DynTag) bool { t = elf.DynTag(f.ByteOrder.Uint32(d[0:4])) d = d[8:] case elf.ELFCLASS64: - t = elf.DynTag(f.ByteOrder.Uint64(d[0:8])) //nolint:gosec + t = elf.DynTag(f.ByteOrder.Uint64(d[0:8])) d = d[16:] } if t == tag { diff --git a/syft/format/syftjson/to_syft_model.go b/syft/format/syftjson/to_syft_model.go index 289e91fda..b2b1916e2 100644 --- a/syft/format/syftjson/to_syft_model.go +++ b/syft/format/syftjson/to_syft_model.go @@ -146,7 +146,7 @@ func safeFileModeConvert(val int) (fs.FileMode, error) { if err != nil { return 0, err } - return os.FileMode(mode), nil //nolint:gosec + return os.FileMode(mode), nil } func toSyftLicenses(m []model.License) (p []pkg.License) { diff --git a/syft/pkg/cataloger/debian/parse_dpkg_db.go b/syft/pkg/cataloger/debian/parse_dpkg_db.go index 87428d608..077e5bef9 100644 --- a/syft/pkg/cataloger/debian/parse_dpkg_db.go +++ b/syft/pkg/cataloger/debian/parse_dpkg_db.go @@ -230,7 +230,7 @@ func handleNewKeyValue(line string) (key string, val interface{}, err error) { if err != nil { return "", nil, fmt.Errorf("bad installed-size value=%q: %w", val, err) } - return key, int(s), nil //nolint:gosec + return key, int(s), nil default: return key, val, nil } diff --git a/syft/pkg/cataloger/java/graalvm_native_image_cataloger.go b/syft/pkg/cataloger/java/graalvm_native_image_cataloger.go index 5dd74a654..add09a458 100644 --- a/syft/pkg/cataloger/java/graalvm_native_image_cataloger.go +++ b/syft/pkg/cataloger/java/graalvm_native_image_cataloger.go @@ -268,7 +268,7 @@ func newPE(filename string, r io.ReaderAt) (nativeImage, error) { } exportSymbolsOffset := uint64(exportSymbolsDataDirectory.VirtualAddress) exports := make([]byte, exportSymbolsDataDirectory.Size) - _, err = r.ReadAt(exports, int64(exportSymbolsOffset)) //nolint:gosec + _, err = r.ReadAt(exports, int64(exportSymbolsOffset)) if err != nil { return fileError(filename, fmt.Errorf("could not read the exported symbols data directory: %w", err)) } @@ -412,7 +412,7 @@ func (ni nativeImagePE) fetchExportAttribute(i int) (uint32, error) { func (ni nativeImagePE) fetchExportFunctionPointer(functionsBase uint32, i uint32) (uint32, error) { var pointer uint32 - n := uint32(len(ni.exports)) //nolint:gosec + n := uint32(len(ni.exports)) sz := uint32(unsafe.Sizeof(ni.t.functionPointer)) j := functionsBase + i*sz if j+sz >= n { @@ -457,7 +457,7 @@ func (ni nativeImagePE) fetchSbomSymbols(content *exportContentPE) { sbomBytes := []byte(nativeImageSbomSymbol + "\x00") sbomLengthBytes := []byte(nativeImageSbomLengthSymbol + "\x00") svmVersionInfoBytes := []byte(nativeImageSbomVersionSymbol + "\x00") - n := uint32(len(ni.exports)) //nolint:gosec + n := uint32(len(ni.exports)) // Find SBOM, SBOM Length, and SVM Version Symbol for i := uint32(0); i < content.numberOfNames; i++ { diff --git a/syft/pkg/cataloger/php/parse_pecl_serialized.go b/syft/pkg/cataloger/php/parse_pecl_serialized.go index 84c5c4c3b..7f48f2096 100644 --- a/syft/pkg/cataloger/php/parse_pecl_serialized.go +++ b/syft/pkg/cataloger/php/parse_pecl_serialized.go @@ -60,10 +60,10 @@ func readStruct(metadata any, fields ...string) string { if len(fields) > 0 { value, ok := metadata.(map[any]any) if !ok { - log.Tracef("unable to read '%s' from: %v", fields[0], metadata) //nolint:gosec + log.Tracef("unable to read '%s' from: %v", fields[0], metadata) return "" } - return readStruct(value[fields[0]], fields[1:]...) //nolint:gosec + return readStruct(value[fields[0]], fields[1:]...) } value, ok := metadata.(string) if !ok { diff --git a/syft/pkg/cataloger/redhat/parse_rpm_archive.go b/syft/pkg/cataloger/redhat/parse_rpm_archive.go index e7d4b2287..8c4b395a7 100644 --- a/syft/pkg/cataloger/redhat/parse_rpm_archive.go +++ b/syft/pkg/cataloger/redhat/parse_rpm_archive.go @@ -88,12 +88,12 @@ func mapFiles(files []rpmutils.FileInfo, digestAlgorithm string) []pkg.RpmFileRe } out = append(out, pkg.RpmFileRecord{ Path: f.Name(), - Mode: pkg.RpmFileMode(f.Mode()), //nolint:gosec + Mode: pkg.RpmFileMode(f.Mode()), Size: int(f.Size()), Digest: digest, UserName: f.UserName(), GroupName: f.GroupName(), - Flags: rpmdb.FileFlags(f.Flags()).String(), //nolint:gosec + Flags: rpmdb.FileFlags(f.Flags()).String(), }) } return out From 41e9630409a3b4b4d6bf0006be693d7a0ac6562d Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 09:08:50 -0400 Subject: [PATCH 204/284] chore(deps): update CPE dictionary index (#3232) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: wagoodman <590471+wagoodman@users.noreply.github.com> --- .../dictionary/data/cpe-index.json | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index 3227665cd..90f50b878 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -4201,6 +4201,9 @@ "node-static": [ "cpe:2.3:a:node-static_project:node-static:*:*:*:*:*:node.js:*:*" ], + "node-stringbuilder": [ + "cpe:2.3:a:magiclen:stringbuilder:*:*:*:*:*:node.js:*:*" + ], "node-thulac": [ "cpe:2.3:a:geohey:node-thulac:*:*:*:*:*:node.js:*:*" ], @@ -6615,6 +6618,9 @@ "heapless": [ "cpe:2.3:a:heapless_project:heapless:*:*:*:*:*:rust:*:*" ], + "ic_cdk": [ + "cpe:2.3:a:dfinity:canister_developer_kit_for_the_internet_computer:*:*:*:*:*:rust:*:*" + ], "iced-x86": [ "cpe:2.3:a:iced-x86_project:iced-x86:*:*:*:*:*:rust:*:*" ], @@ -7880,6 +7886,9 @@ "awin-data-feed": [ "cpe:2.3:a:awin:awin_data_feed:*:*:*:*:*:wordpress:*:*" ], + "awsm-team": [ + "cpe:2.3:a:awsm:awsm_team:*:*:*:*:free:wordpress:*:*" + ], "ays-facebook-popup-likebox": [ "cpe:2.3:a:ays-pro:popup_box:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:aysproextensions:popup_like:*:*:*:*:*:wordpress:*:*" @@ -8016,7 +8025,7 @@ "cpe:2.3:a:bertha:bertha_ai:*:*:*:*:*:wordpress:*:*" ], "best-restaurant-menu-by-pricelisto": [ - "cpe:2.3:a:pricelisto:best_restaurant_menu_by_pricelisto:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:pricelisto:great_restaurant_menu_wp:*:*:*:*:*:wordpress:*:*" ], "bestbooks": [ "cpe:2.3:a:presspage:bestbooks:*:*:*:*:*:wordpress:*:*" @@ -9480,6 +9489,9 @@ "dark-mode": [ "cpe:2.3:a:dark_mode_project:dark_mode:*:*:*:*:*:wordpress:*:*" ], + "dark-mode-for-wp-dashboard": [ + "cpe:2.3:a:naiches:dark_mode_for_wp_dashboard:*:*:*:*:*:wordpress:*:*" + ], "dashboard-to-do-list": [ "cpe:2.3:a:arwebdesign:dashboard_to-do_list:*:*:*:*:*:wordpress:*:*" ], @@ -9842,6 +9854,9 @@ "easy-custom-auto-excerpt": [ "cpe:2.3:a:tonjoostudio:easy_custom_auto_excerpt:*:*:*:*:*:wordpress:*:*" ], + "easy-custom-code": [ + "cpe:2.3:a:web357:easy_custom_code:*:*:*:*:*:wordpress:*:*" + ], "easy-digital-downloads": [ "cpe:2.3:a:sandhillsdev:easy_digital_downloads:*:*:*:*:*:wordpress:*:*" ], @@ -10603,6 +10618,9 @@ "floating-social-media-icon": [ "cpe:2.3:a:acurax:floating_social_media_icon:*:*:*:*:*:wordpress:*:*" ], + "floating-social-media-links": [ + "cpe:2.3:a:celloexpressions:floating_social_media_links:*:*:*:*:*:wordpress:*:*" + ], "flog": [ "cpe:2.3:a:flog_project:flog:*:*:*:*:*:*:*:*" ], @@ -10718,7 +10736,7 @@ "cpe:2.3:a:formilla:live_chat:*:*:*:*:*:wordpress:*:*" ], "forminator": [ - "cpe:2.3:a:incsub:forminator:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:incsub:forminator:*:*:*:*:free:wordpress:*:*" ], "formlift": [ "cpe:2.3:a:formlift:formlift_for_infusionsoft_web_forms:*:*:*:*:*:wordpress:*:*" @@ -11226,6 +11244,9 @@ "gutenslider": [ "cpe:2.3:a:gutenslider:gutenslider:*:*:*:*:*:wordpress:*:*" ], + "gutentor": [ + "cpe:2.3:a:gutentor:gutentor:*:*:*:*:*:wordpress:*:*" + ], "gutenverse": [ "cpe:2.3:a:jegstudio:gutenverse:*:*:*:*:*:wordpress:*:*" ], @@ -11803,6 +11824,9 @@ "jeg-elementor-kit": [ "cpe:2.3:a:jegtheme:jeg_elementor_kit:*:*:*:*:*:wordpress:*:*" ], + "jet-elements": [ + "cpe:2.3:a:crocoblock:jetelements:*:*:*:*:*:wordpress:*:*" + ], "jetformbuilder": [ "cpe:2.3:a:crocoblock:jetformbuilder:*:*:*:*:*:wordpress:*:*" ], @@ -12371,6 +12395,9 @@ "make-paths-relative": [ "cpe:2.3:a:yasglobal:make_paths_relative:*:*:*:*:*:wordpress:*:*" ], + "makecommerce": [ + "cpe:2.3:a:makecommerce:makecommerce_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], "makestories-helper": [ "cpe:2.3:a:makestories:makestories_\\(for_google_web_stories\\):*:*:*:*:*:wordpress:*:*" ], @@ -14314,6 +14341,9 @@ "cpe:2.3:a:cyberchimps:gutenberg_\\\u0026_elementor_templates_importer_for_responsive:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:cyberchimps:responsive_addons:*:*:*:*:*:wordpress:*:*" ], + "responsive-block-editor-addons": [ + "cpe:2.3:a:cyberchimps:responsive_blocks:*:*:*:*:*:wordpress:*:*" + ], "responsive-column-widgets": [ "cpe:2.3:a:michaeluno:responsive_column_widgets:*:*:*:*:*:wordpress:*:*" ], @@ -15172,6 +15202,9 @@ "slidedeck2": [ "cpe:2.3:a:hbwsl:slidedeck_2:*:*:*:*:lite:wordpress:*:*" ], + "slider-blocks": [ + "cpe:2.3:a:makegutenblock:gutslider:*:*:*:*:*:wordpress:*:*" + ], "slider-hero": [ "cpe:2.3:a:quantumcloud:slider_hero:*:*:*:*:*:wordpress:*:*" ], @@ -16169,11 +16202,15 @@ "cpe:2.3:a:ultimatesmsnotifications:ultimate_sms_notifications_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], "ultimate-social-media-icons": [ + "cpe:2.3:a:inisev:social_media_share_buttons_\\\u0026_social_sharing_icons:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:ultimatelysocial:social_media_share_buttons_\\\u0026_social_sharing_icons:*:*:*:*:*:wordpress:*:*" ], "ultimate-social-media-plus": [ "cpe:2.3:a:socialshare:social_share_icons_\\\u0026_social_share_buttons:*:*:*:*:*:wordpress:*:*" ], + "ultimate-store-kit": [ + "cpe:2.3:a:bdthemes:ultimate_store_kit:*:*:*:*:free:wordpress:*:*" + ], "ultimate-tables": [ "cpe:2.3:a:webpsilon:ultimate_tables:*:*:*:*:*:wordpress:*:*" ], @@ -18553,6 +18590,9 @@ "wrc-pricing-tables": [ "cpe:2.3:a:realwebcare:wrc_pricing_tables:*:*:*:*:*:wordpress:*:*" ], + "ws-contact-form": [ + "cpe:2.3:a:uusweb:ws_contact_form:*:*:*:*:*:wordpress:*:*" + ], "ws-form": [ "cpe:2.3:a:westguardsolutions:ws_form:*:*:*:*:lite:wordpress:*:*" ], From 7b4feb7c168f0065dac76226085e5105e5eebbae Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 09:09:11 -0400 Subject: [PATCH 205/284] chore(deps): update tools to latest versions (#3231) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index 7d30d69c5..e33ce2f70 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -58,7 +58,7 @@ tools: # used to release all artifacts - name: goreleaser version: - want: v2.3.0 + want: v2.3.1 method: github-release with: repo: goreleaser/goreleaser From 9cc3641ac6feb744e8e77f41460a2ae740f1f3cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:53:51 -0400 Subject: [PATCH 206/284] chore(deps): bump peter-evans/create-pull-request from 7.0.2 to 7.0.3 (#3240) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.2 to 7.0.3. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/d121e62763d8cc35b5fb1710e887d6e69a52d3a4...6cd32fd93684475c31847837f87bb135d40a2b79) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-bootstrap-tools.yml | 2 +- .github/workflows/update-cpe-dictionary-index.yml | 2 +- .github/workflows/update-stereoscope-release.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/update-bootstrap-tools.yml b/.github/workflows/update-bootstrap-tools.yml index e6fd35974..01133c610 100644 --- a/.github/workflows/update-bootstrap-tools.yml +++ b/.github/workflows/update-bootstrap-tools.yml @@ -49,7 +49,7 @@ jobs: app_id: ${{ secrets.TOKEN_APP_ID }} private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@d121e62763d8cc35b5fb1710e887d6e69a52d3a4 #v7.0.2 + - uses: peter-evans/create-pull-request@6cd32fd93684475c31847837f87bb135d40a2b79 #v7.0.3 with: signoff: true delete-branch: true diff --git a/.github/workflows/update-cpe-dictionary-index.yml b/.github/workflows/update-cpe-dictionary-index.yml index 024755ffe..b6f69d0dd 100644 --- a/.github/workflows/update-cpe-dictionary-index.yml +++ b/.github/workflows/update-cpe-dictionary-index.yml @@ -33,7 +33,7 @@ jobs: app_id: ${{ secrets.TOKEN_APP_ID }} private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@d121e62763d8cc35b5fb1710e887d6e69a52d3a4 #v7.0.2 + - uses: peter-evans/create-pull-request@6cd32fd93684475c31847837f87bb135d40a2b79 #v7.0.3 with: signoff: true delete-branch: true diff --git a/.github/workflows/update-stereoscope-release.yml b/.github/workflows/update-stereoscope-release.yml index a0c97eaa6..ee4a65af0 100644 --- a/.github/workflows/update-stereoscope-release.yml +++ b/.github/workflows/update-stereoscope-release.yml @@ -44,7 +44,7 @@ jobs: app_id: ${{ secrets.TOKEN_APP_ID }} private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@d121e62763d8cc35b5fb1710e887d6e69a52d3a4 #v7.0.2 + - uses: peter-evans/create-pull-request@6cd32fd93684475c31847837f87bb135d40a2b79 #v7.0.3 with: signoff: true delete-branch: true From 48c1c45d12bb0943d1781bea031dc542abae7a19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:54:01 -0400 Subject: [PATCH 207/284] chore(deps): bump github/codeql-action from 3.26.6 to 3.26.7 (#3241) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.6 to 3.26.7. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/4dd16135b69a43b6c8efb853346f8437d92d3c93...8214744c546c1e5c8f03dde8fab3a7353211988d) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 65d23b352..5dfe204da 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@4dd16135b69a43b6c8efb853346f8437d92d3c93 #v3.26.6 + uses: github/codeql-action/init@8214744c546c1e5c8f03dde8fab3a7353211988d #v3.26.7 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@4dd16135b69a43b6c8efb853346f8437d92d3c93 #v3.26.6 + uses: github/codeql-action/autobuild@8214744c546c1e5c8f03dde8fab3a7353211988d #v3.26.7 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@4dd16135b69a43b6c8efb853346f8437d92d3c93 #v3.26.6 + uses: github/codeql-action/analyze@8214744c546c1e5c8f03dde8fab3a7353211988d #v3.26.7 From b9efac4d78dd44f847901da3aa4ff85dd83d1edc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:54:12 -0400 Subject: [PATCH 208/284] chore(deps): bump github.com/CycloneDX/cyclonedx-go from 0.9.0 to 0.9.1 (#3242) Bumps [github.com/CycloneDX/cyclonedx-go](https://github.com/CycloneDX/cyclonedx-go) from 0.9.0 to 0.9.1. - [Release notes](https://github.com/CycloneDX/cyclonedx-go/releases) - [Changelog](https://github.com/CycloneDX/cyclonedx-go/blob/master/.goreleaser.yml) - [Commits](https://github.com/CycloneDX/cyclonedx-go/compare/v0.9.0...v0.9.1) --- updated-dependencies: - dependency-name: github.com/CycloneDX/cyclonedx-go dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0e72b1b84..ebf850666 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/anchore/syft go 1.22.0 require ( - github.com/CycloneDX/cyclonedx-go v0.9.0 + github.com/CycloneDX/cyclonedx-go v0.9.1 github.com/Masterminds/semver v1.5.0 github.com/Masterminds/sprig/v3 v3.3.0 github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d diff --git a/go.sum b/go.sum index 0751642fa..6ccd3e6f3 100644 --- a/go.sum +++ b/go.sum @@ -60,8 +60,8 @@ github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/CycloneDX/cyclonedx-go v0.9.0 h1:inaif7qD8bivyxp7XLgxUYtOXWtDez7+j72qKTMQTb8= -github.com/CycloneDX/cyclonedx-go v0.9.0/go.mod h1:NE/EWvzELOFlG6+ljX/QeMlVt9VKcTwu8u0ccsACEsw= +github.com/CycloneDX/cyclonedx-go v0.9.1 h1:yffaWOZsv77oTJa/SdVZYdgAgFioCeycBUKkqS2qzQM= +github.com/CycloneDX/cyclonedx-go v0.9.1/go.mod h1:NE/EWvzELOFlG6+ljX/QeMlVt9VKcTwu8u0ccsACEsw= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= From 79346964632449b1f377b2478f8074950c4b5154 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Tue, 17 Sep 2024 12:30:07 -0400 Subject: [PATCH 209/284] chore(deps): update tools to latest versions (#3243) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index e33ce2f70..1ecb17880 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -111,7 +111,7 @@ tools: # used for triggering a release - name: gh version: - want: v2.56.0 + want: v2.57.0 method: github-release with: repo: cli/cli From a2f12fef0c4244bb90204156d53267079bd4892d Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2024 13:13:24 -0400 Subject: [PATCH 210/284] chore(deps): update tools to latest versions (#3247) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index 1ecb17880..aca15d746 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -58,7 +58,7 @@ tools: # used to release all artifacts - name: goreleaser version: - want: v2.3.1 + want: v2.3.2 method: github-release with: repo: goreleaser/goreleaser From 50016c3172f55ef579f574622e64b672ee4384bf Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:15:12 -0400 Subject: [PATCH 211/284] chore(deps): update tools to latest versions (#3251) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index aca15d746..49dc00d3d 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -103,7 +103,7 @@ tools: # used for running all local and CI tasks - name: task version: - want: v3.39.0 + want: v3.39.1 method: github-release with: repo: go-task/task From cb0de97bc3b6306c36e30359e7e7ac8000888c9d Mon Sep 17 00:00:00 2001 From: "Krystian G." <108719245+krysgor@users.noreply.github.com> Date: Thu, 19 Sep 2024 15:15:54 +0200 Subject: [PATCH 212/284] fix: capture-snippet.sh can handle leading whitespaces now (#3249) (#3250) Signed-off-by: Gorny Krystian Co-authored-by: Gorny Krystian --- syft/pkg/cataloger/binary/test-fixtures/capture-snippet.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/syft/pkg/cataloger/binary/test-fixtures/capture-snippet.sh b/syft/pkg/cataloger/binary/test-fixtures/capture-snippet.sh index 2c7fb063e..088776f48 100755 --- a/syft/pkg/cataloger/binary/test-fixtures/capture-snippet.sh +++ b/syft/pkg/cataloger/binary/test-fixtures/capture-snippet.sh @@ -69,6 +69,11 @@ if ! command -v xxd &> /dev/null; then exit 1 fi +# check if xargs is even installed +if ! command -v xargs &> /dev/null; then + echo "xargs not found. Please install xargs." + exit 1 +fi PATTERN=${SEARCH_FOR:-$VERSION} @@ -116,7 +121,7 @@ while $CONTINUE_LOOP; do fi # search for the pattern in the binary file and capture the offset - OFFSET=$(echo "${SELECTED_RESULT}" | cut -d ' ' -f 1) + OFFSET=$(echo "${SELECTED_RESULT}" | xargs | cut -d ' ' -f 1) if [ -z "$OFFSET" ]; then echo "Pattern not found." From 6a95a5f2ed9ea35c8a718de859d9bf171854c5d5 Mon Sep 17 00:00:00 2001 From: "Krystian G." <108719245+krysgor@users.noreply.github.com> Date: Thu, 19 Sep 2024 15:21:02 +0200 Subject: [PATCH 213/284] feat: add binary classifiers for lighttp, proftpd, zstd, xz, gzip, jq, and sqlcipher (#3252) * feat: detect lighttpd binaries Signed-off-by: Krystian Gorny * feat: detect proftpd binaries Signed-off-by: Krystian Gorny * feat: detect zstd binaries Signed-off-by: Krystian Gorny * feat: detect xz utils binarie Signed-off-by: Krystian Gorny * feat: detect gzip binaries Signed-off-by: Krystian Gorny * feat: detect sqlcipher binaries Signed-off-by: Krystian Gorny * feat: detect jq binaries Signed-off-by: Krystian Gorny * add tests + snippets Signed-off-by: Alex Goodman --------- Signed-off-by: Krystian Gorny Signed-off-by: Alex Goodman Co-authored-by: Krystian Gorny Co-authored-by: Alex Goodman --- .../binary/classifier_cataloger_test.go | 88 ++++++++++++++++++ syft/pkg/cataloger/binary/classifiers.go | 70 ++++++++++++++ .../snippets/gzip/1.12/linux-amd64/gzip | Bin 0 -> 346 bytes .../snippets/jq/1.7.1/linux-amd64/jq | Bin 0 -> 346 bytes .../lighttpd/1.4.76/linux-amd64/lighttpd | Bin 0 -> 351 bytes .../proftpd/1.3.8b/linux-amd64/proftpd | Bin 0 -> 350 bytes .../sqlcipher/4.5.5/linux-amd64/sqlcipher | Bin 0 -> 353 bytes .../snippets/xz/5.6.2/linux-amd64/xz | Bin 0 -> 344 bytes .../snippets/zstd/1.5.6/linux-amd64/zstd | Bin 0 -> 348 bytes .../binary/test-fixtures/config.yaml | 55 +++++++++++ 10 files changed, 213 insertions(+) create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/gzip/1.12/linux-amd64/gzip create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/jq/1.7.1/linux-amd64/jq create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/lighttpd/1.4.76/linux-amd64/lighttpd create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/proftpd/1.3.8b/linux-amd64/proftpd create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/sqlcipher/4.5.5/linux-amd64/sqlcipher create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/xz/5.6.2/linux-amd64/xz create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/zstd/1.5.6/linux-amd64/zstd diff --git a/syft/pkg/cataloger/binary/classifier_cataloger_test.go b/syft/pkg/cataloger/binary/classifier_cataloger_test.go index c1bfbb322..22f59b1b3 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger_test.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger_test.go @@ -1082,6 +1082,94 @@ func Test_Cataloger_PositiveCases(t *testing.T) { Metadata: metadata("wordpress-cli-binary"), }, }, + { + logicalFixture: "lighttpd/1.4.76/linux-amd64", + expected: pkg.Package{ + Name: "lighttpd", + Version: "1.4.76", + Type: "binary", + PURL: "pkg:generic/lighttpd@1.4.76", + Locations: locations("lighttpd"), + Metadata: metadata("lighttpd-binary"), + }, + }, + { + logicalFixture: "proftpd/1.3.8b/linux-amd64", + expected: pkg.Package{ + Name: "proftpd", + Version: "1.3.8b", + Type: "binary", + PURL: "pkg:generic/proftpd@1.3.8b", + Locations: locations("proftpd"), + Metadata: metadata("proftpd-binary"), + }, + }, + { + logicalFixture: "zstd/1.5.6/linux-amd64", + expected: pkg.Package{ + Name: "zstd", + Version: "1.5.6", + Type: "binary", + PURL: "pkg:generic/zstd@1.5.6", + Locations: locations("zstd"), + Metadata: metadata("zstd-binary"), + }, + }, + { + logicalFixture: "zstd/1.5.6/linux-amd64", + expected: pkg.Package{ + Name: "zstd", + Version: "1.5.6", + Type: "binary", + PURL: "pkg:generic/zstd@1.5.6", + Locations: locations("zstd"), + Metadata: metadata("zstd-binary"), + }, + }, + { + logicalFixture: "xz/5.6.2/linux-amd64", + expected: pkg.Package{ + Name: "xz", + Version: "5.6.2", + Type: "binary", + PURL: "pkg:generic/xz@5.6.2", + Locations: locations("xz"), + Metadata: metadata("xz-binary"), + }, + }, + { + logicalFixture: "gzip/1.12/linux-amd64", + expected: pkg.Package{ + Name: "gzip", + Version: "1.12", + Type: "binary", + PURL: "pkg:generic/gzip@1.12", + Locations: locations("gzip"), + Metadata: metadata("gzip-binary"), + }, + }, + { + logicalFixture: "sqlcipher/4.5.5/linux-amd64", + expected: pkg.Package{ + Name: "sqlcipher", + Version: "4.5.5", + Type: "binary", + PURL: "pkg:generic/sqlcipher@4.5.5", + Locations: locations("sqlcipher"), + Metadata: metadata("sqlcipher-binary"), + }, + }, + { + logicalFixture: "jq/1.7.1/linux-amd64", + expected: pkg.Package{ + Name: "jq", + Version: "1.7.1", + Type: "binary", + PURL: "pkg:generic/jq@1.7.1", + Locations: locations("jq"), + Metadata: metadata("jq-binary"), + }, + }, } for _, test := range tests { diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index 5290b4d98..0a2a1a9b8 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -574,6 +574,76 @@ func DefaultClassifiers() []Classifier { PURL: mustPURL("pkg:generic/curl@version"), CPEs: singleCPE("cpe:2.3:a:haxx:curl:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, + { + Class: "lighttpd-binary", + FileGlob: "**/lighttpd", + EvidenceMatcher: FileContentsVersionMatcher( + `\x00lighttpd/(?P[0-9]+\.[0-9]+\.[0-9]+)\x00`, + ), + Package: "lighttpd", + PURL: mustPURL("pkg:generic/lighttpd@version"), + CPEs: singleCPE("cpe:2.3:a:lighttpd:lighttpd:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "proftpd-binary", + FileGlob: "**/proftpd", + EvidenceMatcher: FileContentsVersionMatcher( + `\x00ProFTPD Version (?P[0-9]+\.[0-9]+\.[0-9]+[a-z]?)\x00`, + ), + Package: "proftpd", + PURL: mustPURL("pkg:generic/proftpd@version"), + CPEs: singleCPE("cpe:2.3:a:proftpd:proftpd:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "zstd-binary", + FileGlob: "**/zstd", + EvidenceMatcher: FileContentsVersionMatcher( + `\x00v(?P[0-9]+\.[0-9]+\.[0-9]+)\x00`, + ), + Package: "zstd", + PURL: mustPURL("pkg:generic/zstd@version"), + CPEs: singleCPE("cpe:2.3:a:facebook:zstandard:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "xz-binary", + FileGlob: "**/xz", + EvidenceMatcher: FileContentsVersionMatcher( + `\x00xz \(XZ Utils\) (?P[0-9]+\.[0-9]+\.[0-9]+)\x00`, + ), + Package: "xz", + PURL: mustPURL("pkg:generic/xz@version"), + CPEs: singleCPE("cpe:2.3:a:tukaani:xz:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "gzip-binary", + FileGlob: "**/gzip", + EvidenceMatcher: FileContentsVersionMatcher( + `\x00(?P[0-9]+\.[0-9]+)\x00`, + ), + Package: "gzip", + PURL: mustPURL("pkg:generic/gzip@version"), + CPEs: singleCPE("cpe:2.3:a:gnu:gzip:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "sqlcipher-binary", + FileGlob: "**/sqlcipher", + EvidenceMatcher: FileContentsVersionMatcher( + `[^0-9]\x00(?P[0-9]+\.[0-9]+\.[0-9]+)\x00`, + ), + Package: "sqlcipher", + PURL: mustPURL("pkg:generic/sqlcipher@version"), + CPEs: singleCPE("cpe:2.3:a:zetetic:sqlcipher:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "jq-binary", + FileGlob: "**/jq", + EvidenceMatcher: FileContentsVersionMatcher( + `\x00(?P[0-9]{1,3}\.[0-9]{1,3}(\.[0-9]+)?)\x00`, + ), + Package: "jq", + PURL: mustPURL("pkg:generic/jq@version"), + CPEs: singleCPE("cpe:2.3:a:jqlang:jq:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, } } diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/gzip/1.12/linux-amd64/gzip b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/gzip/1.12/linux-amd64/gzip new file mode 100644 index 0000000000000000000000000000000000000000..64510d6c4de9f3b608baf906b49210a910c8ab55 GIT binary patch literal 346 zcmZ{eOHRZv5JbK9DO!pm!DbY@<6o}93EFmhCL)QWi2=ds2_slii??~IQf;*I1lO;5 zm$j6G+XN1M@N(hp+HMmlJ;-C5_nq6zjkK{7=sZ@teTl}9_l3@KB8Qen zZ_pN|Fp@WxwL%Ooc+I0M^TK~)A$W&4gs2Lt;0nf(?V!dK66!c4# mev;{&f;O)w#oLzZy5IRYIE#n=2ckC@Rr+4QQ>%@Z5X?CrA%Q{AgG)NEN#-buA0VD3nRIq%7$@_{viSE#SHW9#RZ(3v`w#5c zxYC@`j-_LuWNU<>6VAtSs<+^DpND0^@_O<@n~tI3Mua{}E1Zix2MOLNZn$;IYQ@2D z2;QW&H7fO50FNn3BeX!Jz11`g6aIy1r$p}pcT%ASj%WabM9D=f69k!1XjcQAbW(aJ zW7}&REJSd(|(^+no|PvJ literal 0 HcmV?d00001 diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/lighttpd/1.4.76/linux-amd64/lighttpd b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/lighttpd/1.4.76/linux-amd64/lighttpd new file mode 100644 index 0000000000000000000000000000000000000000..c6147b7a9bb095d9fe53316e3b6298c56be26119 GIT binary patch literal 351 zcmXw!yKciU3`Mh6UqK*4r>1&X4|^#JWGT?42>JoEOvOf3NwAd${`)#;!{r`;yu4(> zZ|WdU=dso@upGidwF9Z0m6kj{L+G3$ zWw}D-+O}_7ElCWB+_c_$s{}dYDfEGbDbjsetA$mXqv6{45O^@sYh?%RTeO;6gHkn0 zTfK2Z{g%)O9JF+s^v*lR_WM2bYbE$U6KaN#W6W3BT8uqB!Rh0Dx(!@P$#Z49`_s?j z&>XDUEj0hoy!)%ynPANqNSC_63mkKLtbnD&6%bCJZ%62-dJC!Jv}~MkUfE{7;+&>* K?!d?Fzu*@sSY~$s literal 0 HcmV?d00001 diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/proftpd/1.3.8b/linux-amd64/proftpd b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/proftpd/1.3.8b/linux-amd64/proftpd new file mode 100644 index 0000000000000000000000000000000000000000..f9bc1cae5a539902b3716f2ad1230ba377c5fc66 GIT binary patch literal 350 zcmXw!PfNrw6vTV(r+Bc)US!Rmwn=&uL@y$O;{7Fg*$sA+lBT=(?X9Bcnfc93!ZVF9 zmmKQs+Z@6|b%a4mCHi)vbgZWlxM1y);yhD*JE7=@5wu~NSZIvQgc)r$g=V;V6PwUF{bxi2Hvra5zJ;VqZGG{9mvX_J~K+f5? z0Bi@!J}@#cnZZXV95Wdw9aB^?75)v&0DXrPe6}G`Fd!0;hKLTO_eO{UXD3lQK~5^HtL_SANug`ac04Uu|Rn literal 0 HcmV?d00001 diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/xz/5.6.2/linux-amd64/xz b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/xz/5.6.2/linux-amd64/xz new file mode 100644 index 0000000000000000000000000000000000000000..ed3dc45093f841a8eba7ea7305dae8f96d5713be GIT binary patch literal 344 zcmY+8J5R$f6h=GyS6rz=f~C54Y{$;T#L9q>5St&@jfE3OjS(fko|ebJdd{b#Z*~(6 zaNbx=X{9!R7RD%6Xg;=a04|WNb6yr|Poon`Uj{N6l*y-r&MMUr2}`0!)jK0avXZ)< zc<>PslSw`*sZ3BlN}~z;$Wku!7wbGyQaXAHD!539T6f%P9;Eku2s(!qvAv!hS9$`B0jXo2+JwSL;e+N@CTo}pDKO81 zpianOSvMr5BSlFqwUOzhxRxZ%IsTRPbQ+}-!E5i8N{KP4BaS{9jfpzN1EV|{g~4D% z9fj@;t*~m;oFO5*-46V%MfjZwZGp7pynI5pNSl{ZCo;UbQsCHmY{SM5>Y#`B+FU_* zML51Z5BvQd>c_e+*H(W{8J@nsfgDdR++d@J2YejvdG@fyYwgAGP|1+*@}Isq*uDT~ CC1;iZ literal 0 HcmV?d00001 diff --git a/syft/pkg/cataloger/binary/test-fixtures/config.yaml b/syft/pkg/cataloger/binary/test-fixtures/config.yaml index 58408325b..51607b51a 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/config.yaml +++ b/syft/pkg/cataloger/binary/test-fixtures/config.yaml @@ -610,3 +610,58 @@ from-images: paths: - /usr/bin/curl + - name: lighttpd + version: 1.4.76 + images: + - ref: jitesoft/lighttpd:1.4.76-cgi@sha256:f5d4500bfb992a20ca39369ae1ca1d8a7a9463bb8c59ee8dd85ddb6d96fc9fc1 + platform: linux/amd64 + paths: + - /usr/local/sbin/lighttpd + + - name: proftpd + version: 1.3.8b + images: + - ref: mekayelanik/proftpd-server-alpine:1.3.8b-r2@sha256:a1ef73a2de04999e53bf728b548ef9922febab8f5709037e40e0141cedcd66db + platform: linux/amd64 + paths: + - /usr/sbin/proftpd + + - name: zstd + version: 1.5.6 + images: + - ref: danysk/zstd:1.5.6@sha256:5eceba085b3a399592755dd66a37b8adfb83538af3f56b51bec6e6cc955e3b5f + platform: linux/amd64 + paths: + - /usr/local/bin/zstd + + - name: xz + version: 5.6.2 + images: + - ref: docker:27.2.1@sha256:c51fa20028ff6590588d9ed97d3b16865d503a3d7228aa885871c5c292afa5ca + platform: linux/amd64 + paths: + - /usr/bin/xz + + - name: gzip + version: 1.12 + images: + - ref: ubuntu:24.04@sha256:d35dfc2fe3ef66bcc085ca00d3152b482e6cafb23cdda1864154caf3b19094ba + platform: linux/amd64 + paths: + - /usr/bin/gzip + + - name: sqlcipher + version: 4.5.5 + images: + - ref: yspreen/sqlcipher@sha256:93189cc465661f16ad23f3ace4206179bdd19967deaf08c54da5ac1e34bb6fb7 + platform: linux/amd64 + paths: + - /usr/local/bin/sqlcipher + + - name: jq + version: 1.7.1 + images: + - ref: efrecon/jq:1.7.1@sha256:0ad05e2e6d1dea5fe0852ecc23114eb768d60c4ce0985d729eb958809e7f31dd + platform: linux/amd64 + paths: + - /usr/local/bin/jq From 98c96ce36120cc600957a3e8c14fd81fbb7f4ca4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 10:49:22 -0400 Subject: [PATCH 214/284] chore(deps): bump github.com/docker/docker (#3260) Bumps [github.com/docker/docker](https://github.com/docker/docker) from 27.2.1+incompatible to 27.3.0+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.2.1...v27.3.0) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ebf850666..1a524ca4e 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/dave/jennifer v1.7.1 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da github.com/distribution/reference v0.6.0 - github.com/docker/docker v27.2.1+incompatible + github.com/docker/docker v27.3.0+incompatible github.com/dustin/go-humanize v1.0.1 github.com/elliotchance/phpserialize v1.4.0 github.com/facebookincubator/nvdtools v0.1.5 diff --git a/go.sum b/go.sum index 6ccd3e6f3..129cd0406 100644 --- a/go.sum +++ b/go.sum @@ -229,8 +229,8 @@ github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2 github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.2.1+incompatible h1:fQdiLfW7VLscyoeYEBz7/J8soYFDZV1u6VW6gJEjNMI= -github.com/docker/docker v27.2.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.3.0+incompatible h1:BNb1QY6o4JdKpqwi9IB+HUYcRRrVN4aGFUTvDmWYK1A= +github.com/docker/docker v27.3.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= From a08ea86aa63d3406baf47089e0363fd30a8933aa Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 10:49:37 -0400 Subject: [PATCH 215/284] chore(deps): update tools to latest versions (#3259) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index 49dc00d3d..2857aa797 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -103,7 +103,7 @@ tools: # used for running all local and CI tasks - name: task version: - want: v3.39.1 + want: v3.39.2 method: github-release with: repo: go-task/task From 9b5cf1db51004528f3f1eea6913d0f57643d06ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 10:49:55 -0400 Subject: [PATCH 216/284] chore(deps): bump github/codeql-action from 3.26.7 to 3.26.8 (#3256) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.7 to 3.26.8. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/8214744c546c1e5c8f03dde8fab3a7353211988d...294a9d92911152fe08befb9ec03e240add280cb3) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 5dfe204da..b02e5a3b0 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@8214744c546c1e5c8f03dde8fab3a7353211988d #v3.26.7 + uses: github/codeql-action/init@294a9d92911152fe08befb9ec03e240add280cb3 #v3.26.8 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@8214744c546c1e5c8f03dde8fab3a7353211988d #v3.26.7 + uses: github/codeql-action/autobuild@294a9d92911152fe08befb9ec03e240add280cb3 #v3.26.8 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@8214744c546c1e5c8f03dde8fab3a7353211988d #v3.26.7 + uses: github/codeql-action/analyze@294a9d92911152fe08befb9ec03e240add280cb3 #v3.26.8 From 7c12e3f3b3df17d18a0b9359a56d2c48c04aa92a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 10:50:03 -0400 Subject: [PATCH 217/284] chore(deps): bump peter-evans/create-pull-request from 7.0.3 to 7.0.5 (#3255) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.3 to 7.0.5. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/6cd32fd93684475c31847837f87bb135d40a2b79...5e914681df9dc83aa4e4905692ca88beb2f9e91f) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-bootstrap-tools.yml | 2 +- .github/workflows/update-cpe-dictionary-index.yml | 2 +- .github/workflows/update-stereoscope-release.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/update-bootstrap-tools.yml b/.github/workflows/update-bootstrap-tools.yml index 01133c610..5ae63dd08 100644 --- a/.github/workflows/update-bootstrap-tools.yml +++ b/.github/workflows/update-bootstrap-tools.yml @@ -49,7 +49,7 @@ jobs: app_id: ${{ secrets.TOKEN_APP_ID }} private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@6cd32fd93684475c31847837f87bb135d40a2b79 #v7.0.3 + - uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f #v7.0.5 with: signoff: true delete-branch: true diff --git a/.github/workflows/update-cpe-dictionary-index.yml b/.github/workflows/update-cpe-dictionary-index.yml index b6f69d0dd..2bc9ff5db 100644 --- a/.github/workflows/update-cpe-dictionary-index.yml +++ b/.github/workflows/update-cpe-dictionary-index.yml @@ -33,7 +33,7 @@ jobs: app_id: ${{ secrets.TOKEN_APP_ID }} private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@6cd32fd93684475c31847837f87bb135d40a2b79 #v7.0.3 + - uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f #v7.0.5 with: signoff: true delete-branch: true diff --git a/.github/workflows/update-stereoscope-release.yml b/.github/workflows/update-stereoscope-release.yml index ee4a65af0..2c136b23d 100644 --- a/.github/workflows/update-stereoscope-release.yml +++ b/.github/workflows/update-stereoscope-release.yml @@ -44,7 +44,7 @@ jobs: app_id: ${{ secrets.TOKEN_APP_ID }} private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@6cd32fd93684475c31847837f87bb135d40a2b79 #v7.0.3 + - uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f #v7.0.5 with: signoff: true delete-branch: true From 60bbd240317e76fe65e3c704309dd4d1683cfcfe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 10:50:16 -0400 Subject: [PATCH 218/284] chore(deps): bump github.com/github/go-spdx/v2 from 2.3.1 to 2.3.2 (#3254) Bumps [github.com/github/go-spdx/v2](https://github.com/github/go-spdx) from 2.3.1 to 2.3.2. - [Release notes](https://github.com/github/go-spdx/releases) - [Commits](https://github.com/github/go-spdx/compare/v2.3.1...v2.3.2) --- updated-dependencies: - dependency-name: github.com/github/go-spdx/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1a524ca4e..8cd36e216 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/dustin/go-humanize v1.0.1 github.com/elliotchance/phpserialize v1.4.0 github.com/facebookincubator/nvdtools v0.1.5 - github.com/github/go-spdx/v2 v2.3.1 + github.com/github/go-spdx/v2 v2.3.2 github.com/gkampitakis/go-snaps v0.5.7 github.com/go-git/go-billy/v5 v5.5.0 github.com/go-git/go-git/v5 v5.12.0 diff --git a/go.sum b/go.sum index 129cd0406..16e38c986 100644 --- a/go.sum +++ b/go.sum @@ -285,8 +285,8 @@ github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyT github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I= github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/github/go-spdx/v2 v2.3.1 h1:ffGuHTbHuHzWPt53n8f9o8clGutuLPObo3zB4JAjxU8= -github.com/github/go-spdx/v2 v2.3.1/go.mod h1:2ZxKsOhvBp+OYBDlsGnUMcchLeo2mrpEBn2L1C+U3IQ= +github.com/github/go-spdx/v2 v2.3.2 h1:IfdyNHTqzs4zAJjXdVQfRnxt1XMfycXoHBE2Vsm1bjs= +github.com/github/go-spdx/v2 v2.3.2/go.mod h1:2ZxKsOhvBp+OYBDlsGnUMcchLeo2mrpEBn2L1C+U3IQ= github.com/gkampitakis/ciinfo v0.3.0 h1:gWZlOC2+RYYttL0hBqcoQhM7h1qNkVqvRCV1fOvpAv8= github.com/gkampitakis/ciinfo v0.3.0/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= From 963ea594c8ae4e294d07148e9f17d1149fe43dfb Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Fri, 20 Sep 2024 12:50:47 -0400 Subject: [PATCH 219/284] Add compliance policy for empty name and version (#3257) * add policy for empty name and version Signed-off-by: Alex Goodman * default stub version Signed-off-by: Alex Goodman * modifying ids requires augmenting relationships Signed-off-by: Alex Goodman --------- Signed-off-by: Alex Goodman --- cmd/syft/internal/options/catalog.go | 10 ++ cmd/syft/internal/options/compliance.go | 35 ++++ internal/relationship/index.go | 56 +++++-- internal/relationship/index_test.go | 177 ++++++++++++++++++++ internal/task/package_task_factory.go | 172 +++++++++++++++---- internal/task/package_task_factory_test.go | 85 ++++++++++ syft/cataloging/compliance.go | 47 ++++++ syft/create_sbom_config.go | 9 + syft/pkg/cataloger/ocaml/parse_opam_test.go | 3 +- 9 files changed, 547 insertions(+), 47 deletions(-) create mode 100644 cmd/syft/internal/options/compliance.go create mode 100644 syft/cataloging/compliance.go diff --git a/cmd/syft/internal/options/catalog.go b/cmd/syft/internal/options/catalog.go index 8d1851860..ec75d392f 100644 --- a/cmd/syft/internal/options/catalog.go +++ b/cmd/syft/internal/options/catalog.go @@ -37,6 +37,7 @@ type Catalog struct { Scope string `yaml:"scope" json:"scope" mapstructure:"scope"` Parallelism int `yaml:"parallelism" json:"parallelism" mapstructure:"parallelism"` // the number of catalog workers to run in parallel Relationships relationshipsConfig `yaml:"relationships" json:"relationships" mapstructure:"relationships"` + Compliance complianceConfig `yaml:"compliance" json:"compliance" mapstructure:"compliance"` Enrich []string `yaml:"enrich" json:"enrich" mapstructure:"enrich"` // ecosystem-specific cataloger configuration @@ -62,6 +63,7 @@ var _ interface { func DefaultCatalog() Catalog { return Catalog{ + Compliance: defaultComplianceConfig(), Scope: source.SquashedScope.String(), Package: defaultPackageConfig(), LinuxKernel: defaultLinuxKernelConfig(), @@ -79,6 +81,7 @@ func (cfg Catalog) ToSBOMConfig(id clio.Identification) *syft.CreateSBOMConfig { WithTool(id.Name, id.Version). WithParallelism(cfg.Parallelism). WithRelationshipsConfig(cfg.ToRelationshipsConfig()). + WithComplianceConfig(cfg.ToComplianceConfig()). WithSearchConfig(cfg.ToSearchConfig()). WithPackagesConfig(cfg.ToPackagesConfig()). WithFilesConfig(cfg.ToFilesConfig()). @@ -104,6 +107,13 @@ func (cfg Catalog) ToRelationshipsConfig() cataloging.RelationshipsConfig { } } +func (cfg Catalog) ToComplianceConfig() cataloging.ComplianceConfig { + return cataloging.ComplianceConfig{ + MissingName: cfg.Compliance.MissingName, + MissingVersion: cfg.Compliance.MissingVersion, + } +} + func (cfg Catalog) ToFilesConfig() filecataloging.Config { hashers, err := intFile.Hashers(cfg.File.Metadata.Digests...) if err != nil { diff --git a/cmd/syft/internal/options/compliance.go b/cmd/syft/internal/options/compliance.go new file mode 100644 index 000000000..a48b21441 --- /dev/null +++ b/cmd/syft/internal/options/compliance.go @@ -0,0 +1,35 @@ +package options + +import ( + "github.com/anchore/fangs" + "github.com/anchore/syft/syft/cataloging" +) + +var ( + _ fangs.FieldDescriber = (*complianceConfig)(nil) + _ fangs.PostLoader = (*complianceConfig)(nil) +) + +type complianceConfig struct { + MissingName cataloging.ComplianceAction `mapstructure:"missing-name" json:"missing-name" yaml:"missing-name"` + MissingVersion cataloging.ComplianceAction `mapstructure:"missing-version" json:"missing-version" yaml:"missing-version"` +} + +func defaultComplianceConfig() complianceConfig { + def := cataloging.DefaultComplianceConfig() + return complianceConfig{ + MissingName: def.MissingName, + MissingVersion: def.MissingVersion, + } +} + +func (r *complianceConfig) DescribeFields(descriptions fangs.FieldDescriptionSet) { + descriptions.Add(&r.MissingName, "action to take when a package is missing a name") + descriptions.Add(&r.MissingVersion, "action to take when a package is missing a version") +} + +func (r *complianceConfig) PostLoad() error { + r.MissingName = r.MissingName.Parse() + r.MissingVersion = r.MissingVersion.Parse() + return nil +} diff --git a/internal/relationship/index.go b/internal/relationship/index.go index a94c84f85..ab78c62b4 100644 --- a/internal/relationship/index.go +++ b/internal/relationship/index.go @@ -17,20 +17,16 @@ type Index struct { // NewIndex returns a new relationship Index func NewIndex(relationships ...artifact.Relationship) *Index { - out := Index{} + out := Index{ + fromID: make(map[artifact.ID]*mappedRelationships), + toID: make(map[artifact.ID]*mappedRelationships), + } out.Add(relationships...) return &out } // Add adds all the given relationships to the index, without adding duplicates func (i *Index) Add(relationships ...artifact.Relationship) { - if i.fromID == nil { - i.fromID = map[artifact.ID]*mappedRelationships{} - } - if i.toID == nil { - i.toID = map[artifact.ID]*mappedRelationships{} - } - // store appropriate indexes for stable ordering to minimize ID() calls for _, r := range relationships { // prevent duplicates @@ -68,6 +64,39 @@ func (i *Index) Add(relationships ...artifact.Relationship) { } } +func (i *Index) Remove(id artifact.ID) { + delete(i.fromID, id) + delete(i.toID, id) + + for idx := 0; idx < len(i.all); { + if i.all[idx].from == id || i.all[idx].to == id { + i.all = append(i.all[:idx], i.all[idx+1:]...) + } else { + idx++ + } + } +} + +func (i *Index) Replace(ogID artifact.ID, replacement artifact.Identifiable) { + for _, mapped := range fromMappedByID(i.fromID, ogID) { + i.Add(artifact.Relationship{ + From: replacement, + To: mapped.relationship.To, + Type: mapped.relationship.Type, + }) + } + + for _, mapped := range fromMappedByID(i.toID, ogID) { + i.Add(artifact.Relationship{ + From: mapped.relationship.From, + To: replacement, + Type: mapped.relationship.Type, + }) + } + + i.Remove(ogID) +} + // From returns all relationships from the given identifiable, with specified types func (i *Index) From(identifiable artifact.Identifiable, types ...artifact.RelationshipType) []artifact.Relationship { return toSortedSlice(fromMapped(i.fromID, identifiable), types) @@ -110,10 +139,17 @@ func (i *Index) All(types ...artifact.RelationshipType) []artifact.Relationship } func fromMapped(idMap map[artifact.ID]*mappedRelationships, identifiable artifact.Identifiable) []*sortableRelationship { - if identifiable == nil || idMap == nil { + if identifiable == nil { + return nil + } + return fromMappedByID(idMap, identifiable.ID()) +} + +func fromMappedByID(idMap map[artifact.ID]*mappedRelationships, id artifact.ID) []*sortableRelationship { + if idMap == nil { return nil } - mapped := idMap[identifiable.ID()] + mapped := idMap[id] if mapped == nil { return nil } diff --git a/internal/relationship/index_test.go b/internal/relationship/index_test.go index 1f4e66c27..8f0d010f2 100644 --- a/internal/relationship/index_test.go +++ b/internal/relationship/index_test.go @@ -3,6 +3,7 @@ package relationship import ( "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/anchore/syft/syft/artifact" @@ -231,3 +232,179 @@ func (i id) ID() artifact.ID { func slice[T any](values ...T) []T { return values } + +func TestRemove(t *testing.T) { + p1 := pkg.Package{Name: "pkg-1"} + p2 := pkg.Package{Name: "pkg-2"} + p3 := pkg.Package{Name: "pkg-3"} + c1 := file.Coordinates{RealPath: "/coords/1"} + c2 := file.Coordinates{RealPath: "/coords/2"} + c3 := file.Coordinates{RealPath: "/coords/3"} + c4 := file.Coordinates{RealPath: "/coords/4"} + + for _, p := range []*pkg.Package{&p1, &p2, &p3} { + p.SetID() + } + + r1 := artifact.Relationship{ + From: p1, + To: p2, + Type: artifact.DependencyOfRelationship, + } + r2 := artifact.Relationship{ + From: p1, + To: p3, + Type: artifact.DependencyOfRelationship, + } + r3 := artifact.Relationship{ + From: p1, + To: c1, + Type: artifact.ContainsRelationship, + } + r4 := artifact.Relationship{ + From: p2, + To: c2, + Type: artifact.ContainsRelationship, + } + r5 := artifact.Relationship{ + From: p3, + To: c1, + Type: artifact.ContainsRelationship, + } + r6 := artifact.Relationship{ + From: p3, + To: c2, + Type: artifact.ContainsRelationship, + } + r7 := artifact.Relationship{ + From: c1, + To: c3, + Type: artifact.ContainsRelationship, + } + r8 := artifact.Relationship{ + From: c3, + To: c4, + Type: artifact.ContainsRelationship, + } + + index := NewIndex(r1, r2, r3, r4, r5, r6, r7, r8) + + assert.Equal(t, 8, len(index.All())) + + // removal of p1 should remove r1, r2, and r3 + index.Remove(p1.ID()) + remaining := index.All() + + assert.Equal(t, 5, len(remaining)) + assert.NotContains(t, remaining, r1) + assert.NotContains(t, remaining, r2) + assert.NotContains(t, remaining, r3) + + assert.Empty(t, index.From(p1)) + assert.Empty(t, index.To(p1)) + + // removal of c1 should remove r5 and r7 + index.Remove(c1.ID()) + remaining = index.All() + + // r8 remains since c3->c4 should still exist + assert.Equal(t, 3, len(remaining)) + assert.NotContains(t, remaining, r5) + assert.NotContains(t, remaining, r7) + assert.Contains(t, remaining, r8) + + assert.Empty(t, index.From(c1)) + assert.Empty(t, index.To(c1)) + + // removal of c3 should remove r8 + index.Remove(c3.ID()) + remaining = index.All() + + assert.Equal(t, 2, len(remaining)) + assert.Contains(t, remaining, r4) + assert.Contains(t, remaining, r6) + + assert.Empty(t, index.From(c3)) + assert.Empty(t, index.To(c3)) +} + +func TestReplace(t *testing.T) { + p1 := pkg.Package{Name: "pkg-1"} + p2 := pkg.Package{Name: "pkg-2"} + p3 := pkg.Package{Name: "pkg-3"} + p4 := pkg.Package{Name: "pkg-4"} + + for _, p := range []*pkg.Package{&p1, &p2, &p3, &p4} { + p.SetID() + } + + r1 := artifact.Relationship{ + From: p1, + To: p2, + Type: artifact.DependencyOfRelationship, + } + r2 := artifact.Relationship{ + From: p3, + To: p1, + Type: artifact.DependencyOfRelationship, + } + r3 := artifact.Relationship{ + From: p2, + To: p3, + Type: artifact.ContainsRelationship, + } + + index := NewIndex(r1, r2, r3) + + // replace p1 with p4 in the relationships + index.Replace(p1.ID(), &p4) + + expectedRels := []artifact.Relationship{ + { + From: p4, // replaced + To: p2, + Type: artifact.DependencyOfRelationship, + }, + { + From: p3, + To: p4, // replaced + Type: artifact.DependencyOfRelationship, + }, + { + From: p2, + To: p3, + Type: artifact.ContainsRelationship, + }, + } + + compareRelationships(t, expectedRels, index.All()) +} + +func compareRelationships(t testing.TB, expected, actual []artifact.Relationship) { + assert.Equal(t, len(expected), len(actual), "number of relationships should match") + for _, e := range expected { + found := false + for _, a := range actual { + if a.From.ID() == e.From.ID() && a.To.ID() == e.To.ID() && a.Type == e.Type { + found = true + break + } + } + assert.True(t, found, "expected relationship not found: %+v", e) + } +} + +func TestReplace_NoExistingRelations(t *testing.T) { + p1 := pkg.Package{Name: "pkg-1"} + p2 := pkg.Package{Name: "pkg-2"} + + p1.SetID() + p2.SetID() + + index := NewIndex() + + index.Replace(p1.ID(), &p2) + + allRels := index.All() + assert.Len(t, allRels, 0) +} diff --git a/internal/task/package_task_factory.go b/internal/task/package_task_factory.go index 8a31c0483..4a86aed12 100644 --- a/internal/task/package_task_factory.go +++ b/internal/task/package_task_factory.go @@ -11,6 +11,7 @@ import ( "github.com/anchore/syft/internal/bus" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/relationship" "github.com/anchore/syft/internal/sbomsync" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/cataloging" @@ -27,6 +28,7 @@ type packageTaskFactory func(cfg CatalogingFactoryConfig) Task type PackageTaskFactories []packageTaskFactory type CatalogingFactoryConfig struct { + ComplianceConfig cataloging.ComplianceConfig SearchConfig cataloging.SearchConfig RelationshipsConfig cataloging.RelationshipsConfig DataGenerationConfig cataloging.DataGenerationConfig @@ -35,6 +37,7 @@ type CatalogingFactoryConfig struct { func DefaultCatalogingFactoryConfig() CatalogingFactoryConfig { return CatalogingFactoryConfig{ + ComplianceConfig: cataloging.DefaultComplianceConfig(), SearchConfig: cataloging.DefaultSearchConfig(), RelationshipsConfig: cataloging.DefaultRelationshipsConfig(), DataGenerationConfig: cataloging.DefaultDataGenerationConfig(), @@ -82,7 +85,7 @@ func (f PackageTaskFactories) Tasks(cfg CatalogingFactoryConfig) ([]Task, error) } // NewPackageTask creates a Task function for a generic pkg.Cataloger, honoring the common configuration options. -func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string) Task { //nolint: funlen +func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string) Task { fn := func(ctx context.Context, resolver file.Resolver, sbom sbomsync.Builder) error { catalogerName := c.Name() log.WithFields("name", catalogerName).Trace("starting package cataloger") @@ -106,42 +109,9 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string log.WithFields("cataloger", catalogerName).Debugf("discovered %d packages", len(pkgs)) - for i, p := range pkgs { - if p.FoundBy == "" { - p.FoundBy = catalogerName - } - - if cfg.DataGenerationConfig.GenerateCPEs && !hasAuthoritativeCPE(p.CPEs) { - // generate CPEs (note: this is excluded from package ID, so is safe to mutate) - // we might have binary classified CPE already with the package so we want to append here - dictionaryCPEs, ok := cpeutils.DictionaryFind(p) - if ok { - log.Tracef("used CPE dictionary to find CPEs for %s package %q: %s", p.Type, p.Name, dictionaryCPEs) - p.CPEs = append(p.CPEs, dictionaryCPEs...) - } else { - p.CPEs = append(p.CPEs, cpeutils.Generate(p)...) - } - } - - // if we were not able to identify the language we have an opportunity - // to try and get this value from the PURL. Worst case we assert that - // we could not identify the language at either stage and set UnknownLanguage - if p.Language == "" { - p.Language = pkg.LanguageFromPURL(p.PURL) - } - - if cfg.RelationshipsConfig.PackageFileOwnership { - // create file-to-package relationships for files owned by the package - owningRelationships, err := packageFileOwnershipRelationships(p, resolver) - if err != nil { - log.Warnf("unable to create any package-file relationships for package name=%q type=%q: %w", p.Name, p.Type, err) - } else { - relationships = append(relationships, owningRelationships...) - } - } + pkgs, relationships = finalizePkgCatalogerResults(cfg, resolver, catalogerName, pkgs, relationships) - pkgs[i] = p - } + pkgs, relationships = applyCompliance(cfg.ComplianceConfig, pkgs, relationships) sbom.AddPackages(pkgs...) sbom.AddRelationships(relationships...) @@ -157,6 +127,136 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string return NewTask(c.Name(), fn, tags...) } +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 == "" { + p.FoundBy = catalogerName + } + + if cfg.DataGenerationConfig.GenerateCPEs && !hasAuthoritativeCPE(p.CPEs) { + // generate CPEs (note: this is excluded from package ID, so is safe to mutate) + // we might have binary classified CPE already with the package so we want to append here + dictionaryCPEs, ok := cpeutils.DictionaryFind(p) + if ok { + log.Tracef("used CPE dictionary to find CPEs for %s package %q: %s", p.Type, p.Name, dictionaryCPEs) + p.CPEs = append(p.CPEs, dictionaryCPEs...) + } else { + p.CPEs = append(p.CPEs, cpeutils.Generate(p)...) + } + } + + // if we were not able to identify the language we have an opportunity + // to try and get this value from the PURL. Worst case we assert that + // we could not identify the language at either stage and set UnknownLanguage + if p.Language == "" { + p.Language = pkg.LanguageFromPURL(p.PURL) + } + + if cfg.RelationshipsConfig.PackageFileOwnership { + // create file-to-package relationships for files owned by the package + owningRelationships, err := packageFileOwnershipRelationships(p, resolver) + if err != nil { + log.Warnf("unable to create any package-file relationships for package name=%q type=%q: %v", p.Name, p.Type, err) + } else { + relationships = append(relationships, owningRelationships...) + } + } + + pkgs[i] = p + } + return pkgs, relationships +} + +type packageReplacement struct { + original artifact.ID + pkg pkg.Package +} + +func applyCompliance(cfg cataloging.ComplianceConfig, pkgs []pkg.Package, relationships []artifact.Relationship) ([]pkg.Package, []artifact.Relationship) { + remainingPkgs, droppedPkgs, replacements := filterNonCompliantPackages(pkgs, cfg) + + relIdx := relationship.NewIndex(relationships...) + for _, p := range droppedPkgs { + relIdx.Remove(p.ID()) + } + + for _, replacement := range replacements { + relIdx.Replace(replacement.original, replacement.pkg) + } + + return remainingPkgs, relIdx.All() +} + +func filterNonCompliantPackages(pkgs []pkg.Package, cfg cataloging.ComplianceConfig) ([]pkg.Package, []pkg.Package, []packageReplacement) { + var remainingPkgs, droppedPkgs []pkg.Package + var replacements []packageReplacement + for _, p := range pkgs { + keep, replacement := applyComplianceRules(&p, cfg) + if keep { + remainingPkgs = append(remainingPkgs, p) + } else { + droppedPkgs = append(droppedPkgs, p) + } + if replacement != nil { + replacements = append(replacements, *replacement) + } + } + + return remainingPkgs, droppedPkgs, replacements +} + +func applyComplianceRules(p *pkg.Package, cfg cataloging.ComplianceConfig) (bool, *packageReplacement) { + var drop bool + var replacement *packageReplacement + + applyComplianceRule := func(value, fieldName string, action cataloging.ComplianceAction) bool { + if strings.TrimSpace(value) != "" { + return false + } + + loc := "unknown" + locs := p.Locations.ToSlice() + if len(locs) > 0 { + loc = locs[0].Path() + } + switch action { + case cataloging.ComplianceActionDrop: + log.WithFields("pkg", p.String(), "location", loc).Debugf("package with missing %s, dropping", fieldName) + drop = true + + case cataloging.ComplianceActionStub: + log.WithFields("pkg", p.String(), "location", loc).Debugf("package with missing %s, stubbing with default value", fieldName) + return true + + case cataloging.ComplianceActionKeep: + log.WithFields("pkg", p.String(), "location", loc).Tracef("package with missing %s, taking no action", fieldName) + } + return false + } + + ogID := p.ID() + + if applyComplianceRule(p.Name, "name", cfg.MissingName) { + p.Name = cataloging.UnknownStubValue + p.SetID() + } + + if applyComplianceRule(p.Version, "version", cfg.MissingVersion) { + p.Version = cataloging.UnknownStubValue + p.SetID() + } + + newID := p.ID() + if newID != ogID { + replacement = &packageReplacement{ + original: ogID, + pkg: *p, + } + } + + return !drop, replacement +} + func hasAuthoritativeCPE(cpes []cpe.CPE) bool { for _, c := range cpes { if c.Source != cpe.GeneratedSource { diff --git a/internal/task/package_task_factory_test.go b/internal/task/package_task_factory_test.go index 2876afb56..592da3c94 100644 --- a/internal/task/package_task_factory_test.go +++ b/internal/task/package_task_factory_test.go @@ -4,8 +4,13 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/cataloging" "github.com/anchore/syft/syft/cpe" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" ) func Test_hasAuthoritativeCPE(t *testing.T) { @@ -53,3 +58,83 @@ func Test_hasAuthoritativeCPE(t *testing.T) { }) } } + +func TestApplyCompliance(t *testing.T) { + p1 := pkg.Package{Name: "pkg-1", Version: "1.0"} + p2 := pkg.Package{Name: "", Version: "1.0"} // missing name + p3 := pkg.Package{Name: "pkg-3", Version: ""} // missing version + p4 := pkg.Package{Name: "pkg-4", Version: ""} // missing version + c1 := file.Coordinates{RealPath: "/coords/1"} + c2 := file.Coordinates{RealPath: "/coords/2"} + + for _, p := range []*pkg.Package{&p1, &p2, &p3, &p4} { + p.SetID() + } + + r1 := artifact.Relationship{ + From: p1, + To: c1, + Type: artifact.ContainsRelationship, + } + r2 := artifact.Relationship{ + From: p2, + To: c2, + Type: artifact.ContainsRelationship, + } + + cfg := cataloging.ComplianceConfig{ + MissingName: cataloging.ComplianceActionDrop, + MissingVersion: cataloging.ComplianceActionStub, + } + + remainingPkgs, remainingRels := applyCompliance(cfg, []pkg.Package{p1, p2, p3, p4}, []artifact.Relationship{r1, r2}) + + // p2 should be dropped because it has a missing name, p3 and p4 should pass with a warning for the missing version + assert.Len(t, remainingPkgs, 3) // p1, p3, p4 should remain + assert.Len(t, remainingRels, 1) // only r1 should remain (relationship involving p1) +} + +func TestFilterNonCompliantPackages(t *testing.T) { + p1 := pkg.Package{Name: "pkg-1", Version: "1.0"} + p2 := pkg.Package{Name: "", Version: "1.0"} // missing name + p3 := pkg.Package{Name: "pkg-3", Version: ""} // missing version + + for _, p := range []*pkg.Package{&p1, &p2, &p3} { + p.SetID() + } + + cfg := cataloging.ComplianceConfig{ + MissingName: cataloging.ComplianceActionDrop, + MissingVersion: cataloging.ComplianceActionKeep, + } + + remainingPkgs, droppedPkgs, replacement := filterNonCompliantPackages([]pkg.Package{p1, p2, p3}, cfg) + require.Nil(t, replacement) + + // p2 should be dropped because it has a missing name + assert.Len(t, remainingPkgs, 2) + assert.Len(t, droppedPkgs, 1) + assert.Equal(t, p2, droppedPkgs[0]) +} + +func TestApplyComplianceRules_DropAndStub(t *testing.T) { + p := pkg.Package{Name: "", Version: ""} + p.SetID() + ogID := p.ID() + + cfg := cataloging.ComplianceConfig{ + MissingName: cataloging.ComplianceActionDrop, + MissingVersion: cataloging.ComplianceActionStub, + } + + isCompliant, replacement := applyComplianceRules(&p, cfg) + require.NotNil(t, replacement) + assert.Equal(t, packageReplacement{ + original: ogID, + pkg: p, + }, *replacement) + + // the package should be dropped due to missing name (drop action) and its version should be stubbed + assert.False(t, isCompliant) + assert.Equal(t, cataloging.UnknownStubValue, p.Version) +} diff --git a/syft/cataloging/compliance.go b/syft/cataloging/compliance.go new file mode 100644 index 000000000..180c49d15 --- /dev/null +++ b/syft/cataloging/compliance.go @@ -0,0 +1,47 @@ +package cataloging + +import ( + "strings" +) + +const ( + ComplianceActionKeep ComplianceAction = "keep" + ComplianceActionDrop ComplianceAction = "drop" + ComplianceActionStub ComplianceAction = "stub" +) + +const UnknownStubValue = "UNKNOWN" + +type ComplianceAction string + +type ComplianceConfig struct { + MissingName ComplianceAction `yaml:"missing-name" json:"missing-name" mapstructure:"missing-name"` + MissingVersion ComplianceAction `yaml:"missing-version" json:"missing-version" mapstructure:"missing-version"` +} + +func DefaultComplianceConfig() ComplianceConfig { + // Note: name and version are required minimum SBOM elements by NTIA, thus should be the API default + return ComplianceConfig{ + MissingName: ComplianceActionDrop, + MissingVersion: ComplianceActionStub, + } +} + +func (c ComplianceConfig) Parse() ComplianceConfig { + return ComplianceConfig{ + MissingName: c.MissingName.Parse(), + MissingVersion: c.MissingVersion.Parse(), + } +} + +func (c ComplianceAction) Parse() ComplianceAction { + switch strings.ToLower(string(c)) { + case string(ComplianceActionKeep), "include": + return ComplianceActionKeep + case string(ComplianceActionDrop), "exclude": + return ComplianceActionDrop + case string(ComplianceActionStub), "replace": + return ComplianceActionStub + } + return ComplianceActionKeep +} diff --git a/syft/create_sbom_config.go b/syft/create_sbom_config.go index 1f7deb18d..66c1bb339 100644 --- a/syft/create_sbom_config.go +++ b/syft/create_sbom_config.go @@ -19,6 +19,7 @@ import ( // CreateSBOMConfig specifies all parameters needed for creating an SBOM. type CreateSBOMConfig struct { // required configuration input to specify how cataloging should be performed + Compliance cataloging.ComplianceConfig Search cataloging.SearchConfig Relationships cataloging.RelationshipsConfig DataGeneration cataloging.DataGenerationConfig @@ -38,6 +39,7 @@ type CreateSBOMConfig struct { func DefaultCreateSBOMConfig() *CreateSBOMConfig { return &CreateSBOMConfig{ + Compliance: cataloging.DefaultComplianceConfig(), Search: cataloging.DefaultSearchConfig(), Relationships: cataloging.DefaultRelationshipsConfig(), DataGeneration: cataloging.DefaultDataGenerationConfig(), @@ -93,6 +95,12 @@ func (c *CreateSBOMConfig) WithParallelism(p int) *CreateSBOMConfig { return c } +// WithComplianceConfig allows for setting the specific compliance configuration for cataloging. +func (c *CreateSBOMConfig) WithComplianceConfig(cfg cataloging.ComplianceConfig) *CreateSBOMConfig { + c.Compliance = cfg + return c +} + // WithSearchConfig allows for setting the specific search configuration for cataloging. func (c *CreateSBOMConfig) WithSearchConfig(cfg cataloging.SearchConfig) *CreateSBOMConfig { c.Search = cfg @@ -225,6 +233,7 @@ func (c *CreateSBOMConfig) packageTasks(src source.Description) ([]task.Task, *t RelationshipsConfig: c.Relationships, DataGenerationConfig: c.DataGeneration, PackagesConfig: c.Packages, + ComplianceConfig: c.Compliance, } persistentTasks, selectableTasks, err := c.allPackageTasks(cfg) diff --git a/syft/pkg/cataloger/ocaml/parse_opam_test.go b/syft/pkg/cataloger/ocaml/parse_opam_test.go index f25563be4..63b5fc9d3 100644 --- a/syft/pkg/cataloger/ocaml/parse_opam_test.go +++ b/syft/pkg/cataloger/ocaml/parse_opam_test.go @@ -3,11 +3,12 @@ package ocaml import ( "testing" + "github.com/stretchr/testify/assert" + "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" - "github.com/stretchr/testify/assert" ) func TestParseOpamPackage(t *testing.T) { From 7815d8e4d990c9a4d3a23fbb1beaae66ee2429f8 Mon Sep 17 00:00:00 2001 From: Laurent Goderre Date: Mon, 23 Sep 2024 14:21:31 -0400 Subject: [PATCH 220/284] feat: classifier for Dart lang binaries (#3265) Signed-off-by: Laurent Goderre --- .../binary/classifier_cataloger_test.go | 22 ++++++++++++++++++ syft/pkg/cataloger/binary/classifiers.go | 10 ++++++++ .../snippets/dart/3.5.2/linux-amd64/dart | Bin 0 -> 348 bytes .../dart/3.6.0-216.1.beta/linux-amd64/dart | Bin 0 -> 348 bytes .../binary/test-fixtures/config.yaml | 14 +++++++++++ 5 files changed, 46 insertions(+) create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/dart/3.5.2/linux-amd64/dart create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/dart/3.6.0-216.1.beta/linux-amd64/dart diff --git a/syft/pkg/cataloger/binary/classifier_cataloger_test.go b/syft/pkg/cataloger/binary/classifier_cataloger_test.go index 22f59b1b3..48744a612 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger_test.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger_test.go @@ -961,6 +961,28 @@ func Test_Cataloger_PositiveCases(t *testing.T) { Metadata: metadata("swipl-binary"), }, }, + { + logicalFixture: "dart/3.5.2/linux-amd64", + expected: pkg.Package{ + Name: "dart", + Version: "3.5.2", + Type: "binary", + PURL: "pkg:generic/dart@3.5.2", + Locations: locations("dart"), + Metadata: metadata("dart-binary"), + }, + }, + { + logicalFixture: "dart/3.6.0-216.1.beta/linux-amd64", + expected: pkg.Package{ + Name: "dart", + Version: "3.6.0-216.1.beta", + Type: "binary", + PURL: "pkg:generic/dart@3.6.0-216.1.beta", + Locations: locations("dart"), + Metadata: metadata("dart-binary"), + }, + }, { logicalFixture: "haskell-ghc/9.6.5/linux-amd64", expected: pkg.Package{ diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index 0a2a1a9b8..52dc1549a 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -447,6 +447,16 @@ func DefaultClassifiers() []Classifier { PURL: mustPURL("pkg:generic/swipl@version"), CPEs: singleCPE("cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, + { + Class: "dart-binary", + FileGlob: "**/dart", + EvidenceMatcher: FileContentsVersionMatcher( + `(?m)Dart,GC"\x00(?P[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+(\.[0-9]+)?\.beta)?) `, + ), + Package: "dart", + PURL: mustPURL("pkg:generic/dart@version"), + CPEs: singleCPE("cpe:2.3:a:dart:dart_software_development_kit:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, { Class: "haskell-ghc-binary", FileGlob: "**/ghc*", diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/dart/3.5.2/linux-amd64/dart b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/dart/3.5.2/linux-amd64/dart new file mode 100644 index 0000000000000000000000000000000000000000..226f7c3c4b3868323382f4611f5847c99bb49349 GIT binary patch literal 348 zcmXv}L2AP=5X{-H*f^Jjh9Ipi%QEy(QYgI@dg!sNq?KcEEE6kf^84!0&TV#>nVpHw z+<~V{Dq;u=rw*h>ql_*_p89mk97VBA!#s2PJQ1oUpS&SiV?eH}z?QV2##NO-(~?u9 zr6J>t#fH3*t#1QWZDmz$5ZmC4FTybLe^@|4(i&r#vm3P%h#XWS8|SUYVA(70Or^ES z=FkMCRUKNP9itSrD2mNy1NM;^{@#QXA;fWvKai#3xje@6oEtCu*F1Fpb}U!bK^+jb zOCme+4z^$H;pN%`wjf0(WQPJ!U=2?qV+V19avY}X{rle3(^b literal 0 HcmV?d00001 diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/dart/3.6.0-216.1.beta/linux-amd64/dart b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/dart/3.6.0-216.1.beta/linux-amd64/dart new file mode 100644 index 0000000000000000000000000000000000000000..7a4f9a5d0b33308922b7454eb1002111cd036dbe GIT binary patch literal 348 zcmXw!y=uci5QJUpDK>HwgDvi7btel_IS|qXT%-(pce}PgmV|Xl?6;2sNi#4E%zQJ@ zgQVhNzQtuwUXK>Ur5*Uf0<1+i74_Cy;WqK!AKMu>r!k8T@n$;PHRk! z>@kY>Y|S2dffP!yDAwyWgnMTA!-PD7jD0_T!x9xw Date: Mon, 23 Sep 2024 17:21:38 -0400 Subject: [PATCH 221/284] Add JVM cataloger (#3217) * add jvm cataloger Signed-off-by: Alex Goodman * simplify version selection Signed-off-by: Alex Goodman * CPEs from JVM cataloger should be declared Signed-off-by: Alex Goodman * ensure package overlap is enabled for sensitive use cases Signed-off-by: Alex Goodman * more permissive glob Signed-off-by: Alex Goodman --------- Signed-off-by: Alex Goodman --- cmd/syft/internal/options/catalog.go | 5 + cmd/syft/internal/options/catalog_test.go | 8 + internal/constants.go | 2 +- ...lude_binaries_by_file_ownership_overlap.go | 91 +- ...binaries_by_file_ownership_overlap_test.go | 184 +- internal/task/package_tasks.go | 1 + schema/json/schema-16.0.17.json | 2721 +++++++++++++++++ schema/json/schema-latest.json | 94 +- .../spdxutil/helpers/originator_supplier.go | 4 + .../helpers/originator_supplier_test.go | 12 + syft/internal/fileresolver/chroot_context.go | 34 + .../fileresolver/chroot_context_test.go | 95 + syft/internal/fileresolver/directory.go | 10 +- syft/internal/packagemetadata/generated.go | 1 + syft/internal/packagemetadata/names.go | 1 + syft/pkg/cataloger/java/cataloger.go | 6 + syft/pkg/cataloger/java/cataloger_test.go | 113 + syft/pkg/cataloger/java/parse_jvm_release.go | 423 +++ .../cataloger/java/parse_jvm_release_test.go | 438 +++ .../oracle-jdk-se-8/usr/lib/jvm/.gitignore | 1 + .../usr/lib/jvm/jdk-1.8-oracle-x64/bin/javac | 1 + .../usr/lib/jvm/jdk-1.8-oracle-x64/release | 7 + .../valid-post-jep223/jvm/openjdk/release | 19 + .../jvm/openjdk/sibling/child/file1.txt | 1 + syft/pkg/java.go | 74 + 25 files changed, 4268 insertions(+), 78 deletions(-) create mode 100644 schema/json/schema-16.0.17.json create mode 100644 syft/pkg/cataloger/java/parse_jvm_release.go create mode 100644 syft/pkg/cataloger/java/parse_jvm_release_test.go create mode 100644 syft/pkg/cataloger/java/test-fixtures/jvm-installs/oracle-jdk-se-8/usr/lib/jvm/.gitignore create mode 100644 syft/pkg/cataloger/java/test-fixtures/jvm-installs/oracle-jdk-se-8/usr/lib/jvm/jdk-1.8-oracle-x64/bin/javac create mode 100644 syft/pkg/cataloger/java/test-fixtures/jvm-installs/oracle-jdk-se-8/usr/lib/jvm/jdk-1.8-oracle-x64/release create mode 100644 syft/pkg/cataloger/java/test-fixtures/jvm-installs/valid-post-jep223/jvm/openjdk/release create mode 100644 syft/pkg/cataloger/java/test-fixtures/jvm-installs/valid-post-jep223/jvm/openjdk/sibling/child/file1.txt diff --git a/cmd/syft/internal/options/catalog.go b/cmd/syft/internal/options/catalog.go index ec75d392f..e692f546c 100644 --- a/cmd/syft/internal/options/catalog.go +++ b/cmd/syft/internal/options/catalog.go @@ -249,6 +249,11 @@ func (cfg *Catalog) PostLoad() error { return fmt.Errorf("bad scope value %q", cfg.Scope) } + // the binary package exclusion code depends on the file overlap relationships being created upstream in processing + if !cfg.Relationships.PackageFileOwnershipOverlap && cfg.Package.ExcludeBinaryOverlapByOwnership { + return fmt.Errorf("cannot enable exclude-binary-overlap-by-ownership without enabling package-file-ownership-overlap") + } + return nil } diff --git a/cmd/syft/internal/options/catalog_test.go b/cmd/syft/internal/options/catalog_test.go index cf02630bf..89527cb3f 100644 --- a/cmd/syft/internal/options/catalog_test.go +++ b/cmd/syft/internal/options/catalog_test.go @@ -57,6 +57,14 @@ func TestCatalog_PostLoad(t *testing.T) { assert.Empty(t, options.Catalogers) }, }, + { + name: "must have package overlap flag when pruning binaries by overlap", + options: Catalog{ + Package: packageConfig{ExcludeBinaryOverlapByOwnership: true}, + Relationships: relationshipsConfig{PackageFileOwnershipOverlap: false}, + }, + wantErr: assert.Error, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/constants.go b/internal/constants.go index 93b0093ab..e21291830 100644 --- a/internal/constants.go +++ b/internal/constants.go @@ -3,5 +3,5 @@ package internal const ( // JSONSchemaVersion is the current schema version output by the JSON encoder // This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment. - JSONSchemaVersion = "16.0.16" + JSONSchemaVersion = "16.0.17" ) diff --git a/internal/relationship/exclude_binaries_by_file_ownership_overlap.go b/internal/relationship/exclude_binaries_by_file_ownership_overlap.go index 9733c00e7..648646657 100644 --- a/internal/relationship/exclude_binaries_by_file_ownership_overlap.go +++ b/internal/relationship/exclude_binaries_by_file_ownership_overlap.go @@ -25,55 +25,102 @@ var ( binaryMetadataTypes = []string{ reflect.TypeOf(pkg.ELFBinaryPackageNoteJSONPayload{}).Name(), reflect.TypeOf(pkg.BinarySignature{}).Name(), + reflect.TypeOf(pkg.JavaVMInstallation{}).Name(), } ) func ExcludeBinariesByFileOwnershipOverlap(accessor sbomsync.Accessor) { accessor.WriteToSBOM(func(s *sbom.SBOM) { for _, r := range s.Relationships { - if excludeBinaryByFileOwnershipOverlap(r, s.Artifacts.Packages) { - s.Artifacts.Packages.Delete(r.To.ID()) - s.Relationships = RemoveRelationshipsByID(s.Relationships, r.To.ID()) + if idToRemove := excludeByFileOwnershipOverlap(r, s.Artifacts.Packages); idToRemove != "" { + s.Artifacts.Packages.Delete(idToRemove) + s.Relationships = RemoveRelationshipsByID(s.Relationships, idToRemove) } } }) } -// excludeBinaryByFileOwnershipOverlap will remove packages from a collection given the following properties are true -// 1) the relationship between packages is OwnershipByFileOverlap -// 2) the parent is an "os" package -// 3) the child is a synthetic package generated by the binary cataloger -// 4) the package names are identical -// This was implemented as a way to help resolve: https://github.com/anchore/syft/issues/931 -func excludeBinaryByFileOwnershipOverlap(r artifact.Relationship, c *pkg.Collection) bool { +// excludeByFileOwnershipOverlap will remove packages that should be overridden by a more authoritative package, +// such as an OS package or a package from a cataloger with more specific information being raised up. +func excludeByFileOwnershipOverlap(r artifact.Relationship, c *pkg.Collection) artifact.ID { if artifact.OwnershipByFileOverlapRelationship != r.Type { - return false + return "" } parent := c.Package(r.From.ID()) if parent == nil { - return false - } - - parentInExclusion := slices.Contains(osCatalogerTypes, parent.Type) - if !parentInExclusion { - return false + return "" } child := c.Package(r.To.ID()) if child == nil { - return false + return "" + } + + if idToRemove := identifyOverlappingOSRelationship(parent, child); idToRemove != "" { + return idToRemove + } + + if idToRemove := identifyOverlappingJVMRelationship(parent, child); idToRemove != "" { + return idToRemove + } + + return "" +} + +// identifyOverlappingJVMRelationship indicates the package to remove if this is a binary -> binary pkg relationship +// with a java binary signature package and a more authoritative JVM release package. +func identifyOverlappingJVMRelationship(parent *pkg.Package, child *pkg.Package) artifact.ID { + if !slices.Contains(binaryCatalogerTypes, parent.Type) { + return "" + } + + if !slices.Contains(binaryCatalogerTypes, child.Type) { + return "" + } + + if child.Metadata == nil { + return "" + } + + var ( + foundJVM bool + idToRemove artifact.ID + ) + for _, p := range []*pkg.Package{parent, child} { + switch p.Metadata.(type) { + case pkg.JavaVMInstallation: + foundJVM = true + default: + idToRemove = p.ID() + } + } + + if foundJVM { + return idToRemove + } + + return "" +} + +// identifyOverlappingOSRelationship indicates the package ID to remove if this is an OS pkg -> bin pkg relationship. +// This was implemented as a way to help resolve: https://github.com/anchore/syft/issues/931 +func identifyOverlappingOSRelationship(parent *pkg.Package, child *pkg.Package) artifact.ID { + if !slices.Contains(osCatalogerTypes, parent.Type) { + return "" } if slices.Contains(binaryCatalogerTypes, child.Type) { - return true + return child.ID() } if child.Metadata == nil { - return false + return "" } - childMetadataType := reflect.TypeOf(child.Metadata) + if !slices.Contains(binaryMetadataTypes, reflect.TypeOf(child.Metadata).Name()) { + return "" + } - return slices.Contains(binaryMetadataTypes, childMetadataType.Name()) + return child.ID() } diff --git a/internal/relationship/exclude_binaries_by_file_ownership_overlap_test.go b/internal/relationship/exclude_binaries_by_file_ownership_overlap_test.go index e8347937b..c0b9865ef 100644 --- a/internal/relationship/exclude_binaries_by_file_ownership_overlap_test.go +++ b/internal/relationship/exclude_binaries_by_file_ownership_overlap_test.go @@ -3,18 +3,17 @@ package relationship import ( "testing" + "github.com/stretchr/testify/assert" + "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/pkg" ) -func TestExclude(t *testing.T) { +func TestExcludeByFileOwnershipOverlap(t *testing.T) { packageA := pkg.Package{Name: "package-a", Type: pkg.ApkPkg} - packageB := pkg.Package{Name: "package-a", Type: pkg.PythonPkg} - packageC := pkg.Package{Name: "package-a", Type: pkg.BinaryPkg} - packageD := pkg.Package{Name: "package-d", Type: pkg.BinaryPkg} - packageE := pkg.Package{Name: "package-e", Type: pkg.RpmPkg, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{Type: "rpm"}} - packageF := pkg.Package{Name: "package-f", Type: pkg.RpmPkg, Metadata: pkg.BinarySignature{}} - for _, p := range []*pkg.Package{&packageA, &packageB, &packageC, &packageD, &packageE, &packageF} { + packageB := pkg.Package{Name: "package-b", Type: pkg.BinaryPkg, Metadata: pkg.JavaVMInstallation{}} + packageC := pkg.Package{Name: "package-c", Type: pkg.BinaryPkg, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{Type: "rpm"}} + for _, p := range []*pkg.Package{&packageA, &packageB, &packageC} { p := p p.SetID() } @@ -26,73 +25,152 @@ func TestExclude(t *testing.T) { shouldExclude bool }{ { - name: "no exclusions from os -> python", - relationship: artifact.Relationship{ - Type: artifact.OwnershipByFileOverlapRelationship, - From: packageA, - To: packageB, - }, - packages: pkg.NewCollection(packageA, packageB), - shouldExclude: false, - }, - { - name: "exclusions from os -> binary", + // prove that OS -> bin exclusions are wired + name: "exclusions from os -> elf binary (as RPM)", relationship: artifact.Relationship{ Type: artifact.OwnershipByFileOverlapRelationship, - From: packageA, - To: packageC, + From: packageA, // OS + To: packageC, // ELF binary }, packages: pkg.NewCollection(packageA, packageC), shouldExclude: true, }, { - name: "exclusions from os -> elf binary (as RPM)", + // prove that bin -> JVM exclusions are wired + name: "exclusions from binary -> binary with JVM metadata", relationship: artifact.Relationship{ Type: artifact.OwnershipByFileOverlapRelationship, - From: packageA, - To: packageE, + From: packageB, // binary with JVM metadata + To: packageC, // binary }, - packages: pkg.NewCollection(packageA, packageE), + packages: pkg.NewCollection(packageC, packageB), shouldExclude: true, }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + actualExclude := excludeByFileOwnershipOverlap(test.relationship, test.packages) + didExclude := actualExclude != "" + if !didExclude && test.shouldExclude { + t.Errorf("expected to exclude relationship %+v", test.relationship) + } + }) + + } +} + +func TestIdentifyOverlappingOSRelationship(t *testing.T) { + packageA := pkg.Package{Name: "package-a", Type: pkg.ApkPkg} // OS package + packageB := pkg.Package{Name: "package-b", Type: pkg.BinaryPkg} + packageC := pkg.Package{Name: "package-c", Type: pkg.BinaryPkg, Metadata: pkg.BinarySignature{}} + packageD := pkg.Package{Name: "package-d", Type: pkg.PythonPkg} // Language package + packageE := pkg.Package{Name: "package-e", Type: pkg.BinaryPkg, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{}} + + for _, p := range []*pkg.Package{&packageA, &packageB, &packageC, &packageD, &packageE} { + p.SetID() + } + + tests := []struct { + name string + parent *pkg.Package + child *pkg.Package + expectedID artifact.ID + }{ { - name: "exclusions from os -> binary (masquerading as RPM)", - relationship: artifact.Relationship{ - Type: artifact.OwnershipByFileOverlapRelationship, - From: packageA, - To: packageF, - }, - packages: pkg.NewCollection(packageA, packageF), - shouldExclude: true, + name: "OS -> binary without metadata", + parent: &packageA, + child: &packageB, + expectedID: packageB.ID(), // OS package to binary package, should return child ID }, { - name: "no exclusions from python -> binary", - relationship: artifact.Relationship{ - Type: artifact.OwnershipByFileOverlapRelationship, - From: packageB, - To: packageC, - }, - packages: pkg.NewCollection(packageB, packageC), - shouldExclude: false, + name: "OS -> binary with binary metadata", + parent: &packageA, + child: &packageC, + expectedID: packageC.ID(), // OS package to binary package with binary metadata, should return child ID }, { - name: "no exclusions for different package names", - relationship: artifact.Relationship{ - Type: artifact.OwnershipByFileOverlapRelationship, - From: packageA, - To: packageD, - }, - packages: pkg.NewCollection(packageA, packageD), - shouldExclude: false, + name: "OS -> non-binary package", + parent: &packageA, + child: &packageD, + expectedID: "", // OS package to non-binary package, no exclusion + }, + { + name: "OS -> binary with ELF metadata", + parent: &packageA, + child: &packageE, + expectedID: packageE.ID(), // OS package to binary package with ELF metadata, should return child ID + }, + { + name: "non-OS parent", + parent: &packageD, // non-OS package + child: &packageC, + expectedID: "", // non-OS parent, no exclusion }, } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - if !excludeBinaryByFileOwnershipOverlap(test.relationship, test.packages) && test.shouldExclude { - t.Errorf("expected to exclude relationship %+v", test.relationship) - } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + resultID := identifyOverlappingOSRelationship(tt.parent, tt.child) + assert.Equal(t, tt.expectedID, resultID) }) + } +} + +func TestIdentifyOverlappingJVMRelationship(t *testing.T) { + + packageA := pkg.Package{Name: "package-a", Type: pkg.BinaryPkg} + packageB := pkg.Package{Name: "package-b", Type: pkg.BinaryPkg, Metadata: pkg.BinarySignature{}} + packageC := pkg.Package{Name: "package-c", Type: pkg.BinaryPkg, Metadata: pkg.JavaVMInstallation{}} + packageD := pkg.Package{Name: "package-d", Type: pkg.PythonPkg} + packageE := pkg.Package{Name: "package-e", Type: pkg.BinaryPkg} + + for _, p := range []*pkg.Package{&packageA, &packageB, &packageC, &packageD, &packageE} { + p.SetID() + } + + tests := []struct { + name string + parent *pkg.Package + child *pkg.Package + expectedID artifact.ID + }{ + { + name: "binary -> binary with JVM installation", + parent: &packageA, + child: &packageC, + expectedID: packageA.ID(), // JVM found, return BinaryPkg ID + }, + { + name: "binary -> binary with binary signature", + parent: &packageA, + child: &packageB, + expectedID: "", // binary signatures only found, no exclusion + }, + { + name: "binary -> python (non-binary child)", + parent: &packageA, + child: &packageD, + expectedID: "", // non-binary child, no exclusion + }, + { + name: "no JVM or signature in binary -> binary", + parent: &packageA, + child: &packageE, + expectedID: "", // no JVM or binary signature, no exclusion + }, + { + name: "non-binary parent", + parent: &packageD, + child: &packageC, + expectedID: "", // non-binary parent, no exclusion + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + resultID := identifyOverlappingJVMRelationship(tt.parent, tt.child) + assert.Equal(t, tt.expectedID, resultID) + }) } } diff --git a/internal/task/package_tasks.go b/internal/task/package_tasks.go index c38299f4d..ff7f622fb 100644 --- a/internal/task/package_tasks.go +++ b/internal/task/package_tasks.go @@ -142,6 +142,7 @@ func DefaultPackageTaskFactories() PackageTaskFactories { newSimplePackageTaskFactory(binary.NewELFPackageCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, "binary", "elf-package"), newSimplePackageTaskFactory(githubactions.NewActionUsageCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, "github", "github-actions"), newSimplePackageTaskFactory(githubactions.NewWorkflowUsageCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, "github", "github-actions"), + newSimplePackageTaskFactory(java.NewJvmDistributionCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, "java", "jvm", "jdk", "jre"), newPackageTaskFactory( func(cfg CatalogingFactoryConfig) pkg.Cataloger { return kernel.NewLinuxKernelCataloger(cfg.PackagesConfig.LinuxKernel) diff --git a/schema/json/schema-16.0.17.json b/schema/json/schema-16.0.17.json new file mode 100644 index 000000000..015c9003b --- /dev/null +++ b/schema/json/schema-16.0.17.json @@ -0,0 +1,2721 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "anchore.io/schema/syft/json/16.0.17/document", + "$ref": "#/$defs/Document", + "$defs": { + "AlpmDbEntry": { + "properties": { + "basepackage": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "packager": { + "type": "string" + }, + "url": { + "type": "string" + }, + "validation": { + "type": "string" + }, + "reason": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "backup": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "basepackage", + "package", + "version", + "description", + "architecture", + "size", + "packager", + "url", + "validation", + "reason", + "files", + "backup" + ] + }, + "AlpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "type": { + "type": "string" + }, + "uid": { + "type": "string" + }, + "gid": { + "type": "string" + }, + "time": { + "type": "string", + "format": "date-time" + }, + "size": { + "type": "string" + }, + "link": { + "type": "string" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object" + }, + "ApkDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "originPackage": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "version": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "url": { + "type": "string" + }, + "description": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "installedSize": { + "type": "integer" + }, + "pullDependencies": { + "items": { + "type": "string" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "pullChecksum": { + "type": "string" + }, + "gitCommitOfApkPort": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/ApkFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "originPackage", + "maintainer", + "version", + "architecture", + "url", + "description", + "size", + "installedSize", + "pullDependencies", + "provides", + "pullChecksum", + "gitCommitOfApkPort", + "files" + ] + }, + "ApkFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "ownerUid": { + "type": "string" + }, + "ownerGid": { + "type": "string" + }, + "permissions": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "BinarySignature": { + "properties": { + "matches": { + "items": { + "$ref": "#/$defs/ClassifierMatch" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "matches" + ] + }, + "CConanFileEntry": { + "properties": { + "ref": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanInfoEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "build_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "py_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "options": { + "$ref": "#/$defs/KeyValues" + }, + "path": { + "type": "string" + }, + "context": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockV2Entry": { + "properties": { + "ref": { + "type": "string" + }, + "packageID": { + "type": "string" + }, + "username": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "recipeRevision": { + "type": "string" + }, + "packageRevision": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CPE": { + "properties": { + "cpe": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "cpe" + ] + }, + "ClassifierMatch": { + "properties": { + "classifier": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Location" + } + }, + "type": "object", + "required": [ + "classifier", + "location" + ] + }, + "CocoaPodfileLockEntry": { + "properties": { + "checksum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "checksum" + ] + }, + "Coordinates": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "DartPubspecLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hosted_url": { + "type": "string" + }, + "vcs_url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Descriptor": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "configuration": true + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Digest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "Document": { + "properties": { + "artifacts": { + "items": { + "$ref": "#/$defs/Package" + }, + "type": "array" + }, + "artifactRelationships": { + "items": { + "$ref": "#/$defs/Relationship" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/File" + }, + "type": "array" + }, + "source": { + "$ref": "#/$defs/Source" + }, + "distro": { + "$ref": "#/$defs/LinuxRelease" + }, + "descriptor": { + "$ref": "#/$defs/Descriptor" + }, + "schema": { + "$ref": "#/$defs/Schema" + } + }, + "type": "object", + "required": [ + "artifacts", + "artifactRelationships", + "source", + "distro", + "descriptor", + "schema" + ] + }, + "DotnetDepsEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "path": { + "type": "string" + }, + "sha512": { + "type": "string" + }, + "hashPath": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "path", + "sha512", + "hashPath" + ] + }, + "DotnetPortableExecutableEntry": { + "properties": { + "assemblyVersion": { + "type": "string" + }, + "legalCopyright": { + "type": "string" + }, + "comments": { + "type": "string" + }, + "internalName": { + "type": "string" + }, + "companyName": { + "type": "string" + }, + "productName": { + "type": "string" + }, + "productVersion": { + "type": "string" + } + }, + "type": "object", + "required": [ + "assemblyVersion", + "legalCopyright", + "companyName", + "productName", + "productVersion" + ] + }, + "DpkgDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ] + }, + "DpkgFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "isConfigFile": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "path", + "isConfigFile" + ] + }, + "ELFSecurityFeatures": { + "properties": { + "symbolTableStripped": { + "type": "boolean" + }, + "stackCanary": { + "type": "boolean" + }, + "nx": { + "type": "boolean" + }, + "relRO": { + "type": "string" + }, + "pie": { + "type": "boolean" + }, + "dso": { + "type": "boolean" + }, + "safeStack": { + "type": "boolean" + }, + "cfi": { + "type": "boolean" + }, + "fortify": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "symbolTableStripped", + "nx", + "relRO", + "pie", + "dso" + ] + }, + "ElfBinaryPackageNoteJsonPayload": { + "properties": { + "type": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "osCPE": { + "type": "string" + }, + "os": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "system": { + "type": "string" + }, + "vendor": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "commit": { + "type": "string" + } + }, + "type": "object" + }, + "ElixirMixLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "ErlangRebarLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "Executable": { + "properties": { + "format": { + "type": "string" + }, + "hasExports": { + "type": "boolean" + }, + "hasEntrypoint": { + "type": "boolean" + }, + "importedLibraries": { + "items": { + "type": "string" + }, + "type": "array" + }, + "elfSecurityFeatures": { + "$ref": "#/$defs/ELFSecurityFeatures" + } + }, + "type": "object", + "required": [ + "format", + "hasExports", + "hasEntrypoint", + "importedLibraries" + ] + }, + "File": { + "properties": { + "id": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Coordinates" + }, + "metadata": { + "$ref": "#/$defs/FileMetadataEntry" + }, + "contents": { + "type": "string" + }, + "digests": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/FileLicense" + }, + "type": "array" + }, + "executable": { + "$ref": "#/$defs/Executable" + } + }, + "type": "object", + "required": [ + "id", + "location" + ] + }, + "FileLicense": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "evidence": { + "$ref": "#/$defs/FileLicenseEvidence" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type" + ] + }, + "FileLicenseEvidence": { + "properties": { + "confidence": { + "type": "integer" + }, + "offset": { + "type": "integer" + }, + "extent": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "confidence", + "offset", + "extent" + ] + }, + "FileMetadataEntry": { + "properties": { + "mode": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "linkDestination": { + "type": "string" + }, + "userID": { + "type": "integer" + }, + "groupID": { + "type": "integer" + }, + "mimeType": { + "type": "string" + }, + "size": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "mode", + "type", + "userID", + "groupID", + "mimeType", + "size" + ] + }, + "GoModuleBuildinfoEntry": { + "properties": { + "goBuildSettings": { + "$ref": "#/$defs/KeyValues" + }, + "goCompiledVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "h1Digest": { + "type": "string" + }, + "mainModule": { + "type": "string" + }, + "goCryptoSettings": { + "items": { + "type": "string" + }, + "type": "array" + }, + "goExperiments": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "goCompiledVersion", + "architecture" + ] + }, + "GoModuleEntry": { + "properties": { + "h1Digest": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackEntry": { + "properties": { + "pkgHash": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackLockEntry": { + "properties": { + "pkgHash": { + "type": "string" + }, + "snapshotURL": { + "type": "string" + } + }, + "type": "object" + }, + "IDLikes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "JavaArchive": { + "properties": { + "virtualPath": { + "type": "string" + }, + "manifest": { + "$ref": "#/$defs/JavaManifest" + }, + "pomProperties": { + "$ref": "#/$defs/JavaPomProperties" + }, + "pomProject": { + "$ref": "#/$defs/JavaPomProject" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "virtualPath" + ] + }, + "JavaJvmInstallation": { + "properties": { + "release": { + "$ref": "#/$defs/JavaVMRelease" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "release", + "files" + ] + }, + "JavaManifest": { + "properties": { + "main": { + "$ref": "#/$defs/KeyValues" + }, + "sections": { + "items": { + "$ref": "#/$defs/KeyValues" + }, + "type": "array" + } + }, + "type": "object" + }, + "JavaPomParent": { + "properties": { + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object", + "required": [ + "groupId", + "artifactId", + "version" + ] + }, + "JavaPomProject": { + "properties": { + "path": { + "type": "string" + }, + "parent": { + "$ref": "#/$defs/JavaPomParent" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "groupId", + "artifactId", + "version", + "name" + ] + }, + "JavaPomProperties": { + "properties": { + "path": { + "type": "string" + }, + "name": { + "type": "string" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "extraFields": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "name", + "groupId", + "artifactId", + "version" + ] + }, + "JavaVMRelease": { + "properties": { + "implementor": { + "type": "string" + }, + "implementorVersion": { + "type": "string" + }, + "javaRuntimeVersion": { + "type": "string" + }, + "javaVersion": { + "type": "string" + }, + "javaVersionDate": { + "type": "string" + }, + "libc": { + "type": "string" + }, + "modules": { + "items": { + "type": "string" + }, + "type": "array" + }, + "osArch": { + "type": "string" + }, + "osName": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "source": { + "type": "string" + }, + "buildSource": { + "type": "string" + }, + "buildSourceRepo": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "fullVersion": { + "type": "string" + }, + "semanticVersion": { + "type": "string" + }, + "buildInfo": { + "type": "string" + }, + "jvmVariant": { + "type": "string" + }, + "jvmVersion": { + "type": "string" + }, + "imageType": { + "type": "string" + }, + "buildType": { + "type": "string" + } + }, + "type": "object" + }, + "JavascriptNpmPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "private": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "homepage", + "description", + "url", + "private" + ] + }, + "JavascriptNpmPackageLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "JavascriptYarnLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "KeyValue": { + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "key", + "value" + ] + }, + "KeyValues": { + "items": { + "$ref": "#/$defs/KeyValue" + }, + "type": "array" + }, + "License": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "urls": { + "items": { + "type": "string" + }, + "type": "array" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type", + "urls", + "locations" + ] + }, + "LinuxKernelArchive": { + "properties": { + "name": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "version": { + "type": "string" + }, + "extendedVersion": { + "type": "string" + }, + "buildTime": { + "type": "string" + }, + "author": { + "type": "string" + }, + "format": { + "type": "string" + }, + "rwRootFS": { + "type": "boolean" + }, + "swapDevice": { + "type": "integer" + }, + "rootDevice": { + "type": "integer" + }, + "videoMode": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "architecture", + "version" + ] + }, + "LinuxKernelModule": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "path": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "license": { + "type": "string" + }, + "kernelVersion": { + "type": "string" + }, + "versionMagic": { + "type": "string" + }, + "parameters": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/LinuxKernelModuleParameter" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "LinuxKernelModuleParameter": { + "properties": { + "type": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "type": "object" + }, + "LinuxRelease": { + "properties": { + "prettyName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" + }, + "idLike": { + "$ref": "#/$defs/IDLikes" + }, + "version": { + "type": "string" + }, + "versionID": { + "type": "string" + }, + "versionCodename": { + "type": "string" + }, + "buildID": { + "type": "string" + }, + "imageID": { + "type": "string" + }, + "imageVersion": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "variantID": { + "type": "string" + }, + "homeURL": { + "type": "string" + }, + "supportURL": { + "type": "string" + }, + "bugReportURL": { + "type": "string" + }, + "privacyPolicyURL": { + "type": "string" + }, + "cpeName": { + "type": "string" + }, + "supportEnd": { + "type": "string" + } + }, + "type": "object" + }, + "Location": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + }, + "accessPath": { + "type": "string" + }, + "annotations": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "accessPath" + ] + }, + "LuarocksPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "dependencies": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "name", + "version", + "license", + "homepage", + "description", + "url", + "dependencies" + ] + }, + "MicrosoftKbPatch": { + "properties": { + "product_id": { + "type": "string" + }, + "kb": { + "type": "string" + } + }, + "type": "object", + "required": [ + "product_id", + "kb" + ] + }, + "NixStoreEntry": { + "properties": { + "outputHash": { + "type": "string" + }, + "output": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "outputHash", + "files" + ] + }, + "OpamPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "licenses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "url": { + "type": "string" + }, + "checksum": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "licenses", + "url", + "checksum", + "homepage", + "dependencies" + ] + }, + "Package": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "foundBy": { + "type": "string" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "licenses": { + "$ref": "#/$defs/licenses" + }, + "language": { + "type": "string" + }, + "cpes": { + "$ref": "#/$defs/cpes" + }, + "purl": { + "type": "string" + }, + "metadataType": { + "type": "string" + }, + "metadata": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/AlpmDbEntry" + }, + { + "$ref": "#/$defs/ApkDbEntry" + }, + { + "$ref": "#/$defs/BinarySignature" + }, + { + "$ref": "#/$defs/CConanFileEntry" + }, + { + "$ref": "#/$defs/CConanInfoEntry" + }, + { + "$ref": "#/$defs/CConanLockEntry" + }, + { + "$ref": "#/$defs/CConanLockV2Entry" + }, + { + "$ref": "#/$defs/CocoaPodfileLockEntry" + }, + { + "$ref": "#/$defs/DartPubspecLockEntry" + }, + { + "$ref": "#/$defs/DotnetDepsEntry" + }, + { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + }, + { + "$ref": "#/$defs/DpkgDbEntry" + }, + { + "$ref": "#/$defs/ElfBinaryPackageNoteJsonPayload" + }, + { + "$ref": "#/$defs/ElixirMixLockEntry" + }, + { + "$ref": "#/$defs/ErlangRebarLockEntry" + }, + { + "$ref": "#/$defs/GoModuleBuildinfoEntry" + }, + { + "$ref": "#/$defs/GoModuleEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackLockEntry" + }, + { + "$ref": "#/$defs/JavaArchive" + }, + { + "$ref": "#/$defs/JavaJvmInstallation" + }, + { + "$ref": "#/$defs/JavascriptNpmPackage" + }, + { + "$ref": "#/$defs/JavascriptNpmPackageLockEntry" + }, + { + "$ref": "#/$defs/JavascriptYarnLockEntry" + }, + { + "$ref": "#/$defs/LinuxKernelArchive" + }, + { + "$ref": "#/$defs/LinuxKernelModule" + }, + { + "$ref": "#/$defs/LuarocksPackage" + }, + { + "$ref": "#/$defs/MicrosoftKbPatch" + }, + { + "$ref": "#/$defs/NixStoreEntry" + }, + { + "$ref": "#/$defs/OpamPackage" + }, + { + "$ref": "#/$defs/PhpComposerInstalledEntry" + }, + { + "$ref": "#/$defs/PhpComposerLockEntry" + }, + { + "$ref": "#/$defs/PhpPeclEntry" + }, + { + "$ref": "#/$defs/PortageDbEntry" + }, + { + "$ref": "#/$defs/PythonPackage" + }, + { + "$ref": "#/$defs/PythonPipRequirementsEntry" + }, + { + "$ref": "#/$defs/PythonPipfileLockEntry" + }, + { + "$ref": "#/$defs/PythonPoetryLockEntry" + }, + { + "$ref": "#/$defs/RDescription" + }, + { + "$ref": "#/$defs/RpmArchive" + }, + { + "$ref": "#/$defs/RpmDbEntry" + }, + { + "$ref": "#/$defs/RubyGemspec" + }, + { + "$ref": "#/$defs/RustCargoAuditEntry" + }, + { + "$ref": "#/$defs/RustCargoLockEntry" + }, + { + "$ref": "#/$defs/SwiftPackageManagerLockEntry" + }, + { + "$ref": "#/$defs/SwiplpackPackage" + }, + { + "$ref": "#/$defs/WordpressPluginEntry" + } + ] + } + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "foundBy", + "locations", + "licenses", + "language", + "cpes", + "purl" + ] + }, + "PhpComposerAuthors": { + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name" + ] + }, + "PhpComposerExternalReference": { + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "shasum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "type", + "url", + "reference" + ] + }, + "PhpComposerInstalledEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpComposerLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpPeclEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "PortageDbEntry": { + "properties": { + "installedSize": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/PortageFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "installedSize", + "files" + ] + }, + "PortageFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonDirectURLOriginInfo": { + "properties": { + "url": { + "type": "string" + }, + "commitId": { + "type": "string" + }, + "vcs": { + "type": "string" + } + }, + "type": "object", + "required": [ + "url" + ] + }, + "PythonFileDigest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "PythonFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/PythonFileDigest" + }, + "size": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/PythonFileRecord" + }, + "type": "array" + }, + "sitePackagesRootPath": { + "type": "string" + }, + "topLevelPackages": { + "items": { + "type": "string" + }, + "type": "array" + }, + "directUrlOrigin": { + "$ref": "#/$defs/PythonDirectURLOriginInfo" + }, + "requiresPython": { + "type": "string" + }, + "requiresDist": { + "items": { + "type": "string" + }, + "type": "array" + }, + "providesExtra": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "platform", + "sitePackagesRootPath" + ] + }, + "PythonPipRequirementsEntry": { + "properties": { + "name": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + }, + "versionConstraint": { + "type": "string" + }, + "url": { + "type": "string" + }, + "markers": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "versionConstraint" + ] + }, + "PythonPipfileLockEntry": { + "properties": { + "hashes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "index": { + "type": "string" + } + }, + "type": "object", + "required": [ + "hashes", + "index" + ] + }, + "PythonPoetryLockDependencyEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "optional": { + "type": "boolean" + }, + "markers": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "optional" + ] + }, + "PythonPoetryLockEntry": { + "properties": { + "index": { + "type": "string" + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonPoetryLockDependencyEntry" + }, + "type": "array" + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonPoetryLockExtraEntry" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ] + }, + "PythonPoetryLockExtraEntry": { + "properties": { + "name": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ] + }, + "RDescription": { + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "url": { + "items": { + "type": "string" + }, + "type": "array" + }, + "repository": { + "type": "string" + }, + "built": { + "type": "string" + }, + "needsCompilation": { + "type": "boolean" + }, + "imports": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "suggests": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "Relationship": { + "properties": { + "parent": { + "type": "string" + }, + "child": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "parent", + "child", + "type" + ] + }, + "RpmArchive": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmDbEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "mode": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "userName": { + "type": "string" + }, + "groupName": { + "type": "string" + }, + "flags": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "mode", + "size", + "digest", + "userName", + "groupName", + "flags" + ] + }, + "RubyGemspec": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "RustCargoAuditEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source" + ] + }, + "RustCargoLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + }, + "checksum": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "checksum", + "dependencies" + ] + }, + "Schema": { + "properties": { + "version": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "version", + "url" + ] + }, + "Source": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "metadata" + ] + }, + "SwiftPackageManagerLockEntry": { + "properties": { + "revision": { + "type": "string" + } + }, + "type": "object", + "required": [ + "revision" + ] + }, + "SwiplpackPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "packager": { + "type": "string" + }, + "packagerEmail": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "packager", + "packagerEmail", + "homepage", + "dependencies" + ] + }, + "WordpressPluginEntry": { + "properties": { + "pluginInstallDirectory": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorUri": { + "type": "string" + } + }, + "type": "object", + "required": [ + "pluginInstallDirectory" + ] + }, + "cpes": { + "items": { + "$ref": "#/$defs/CPE" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/License" + }, + "type": "array" + } + } +} diff --git a/schema/json/schema-latest.json b/schema/json/schema-latest.json index a88197859..015c9003b 100644 --- a/schema/json/schema-latest.json +++ b/schema/json/schema-latest.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "anchore.io/schema/syft/json/16.0.16/document", + "$id": "anchore.io/schema/syft/json/16.0.17/document", "$ref": "#/$defs/Document", "$defs": { "AlpmDbEntry": { @@ -955,6 +955,24 @@ "virtualPath" ] }, + "JavaJvmInstallation": { + "properties": { + "release": { + "$ref": "#/$defs/JavaVMRelease" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "release", + "files" + ] + }, "JavaManifest": { "properties": { "main": { @@ -1062,6 +1080,77 @@ "version" ] }, + "JavaVMRelease": { + "properties": { + "implementor": { + "type": "string" + }, + "implementorVersion": { + "type": "string" + }, + "javaRuntimeVersion": { + "type": "string" + }, + "javaVersion": { + "type": "string" + }, + "javaVersionDate": { + "type": "string" + }, + "libc": { + "type": "string" + }, + "modules": { + "items": { + "type": "string" + }, + "type": "array" + }, + "osArch": { + "type": "string" + }, + "osName": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "source": { + "type": "string" + }, + "buildSource": { + "type": "string" + }, + "buildSourceRepo": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "fullVersion": { + "type": "string" + }, + "semanticVersion": { + "type": "string" + }, + "buildInfo": { + "type": "string" + }, + "jvmVariant": { + "type": "string" + }, + "jvmVersion": { + "type": "string" + }, + "imageType": { + "type": "string" + }, + "buildType": { + "type": "string" + } + }, + "type": "object" + }, "JavascriptNpmPackage": { "properties": { "name": { @@ -1583,6 +1672,9 @@ { "$ref": "#/$defs/JavaArchive" }, + { + "$ref": "#/$defs/JavaJvmInstallation" + }, { "$ref": "#/$defs/JavascriptNpmPackage" }, diff --git a/syft/format/internal/spdxutil/helpers/originator_supplier.go b/syft/format/internal/spdxutil/helpers/originator_supplier.go index 478cef377..18fc7f798 100644 --- a/syft/format/internal/spdxutil/helpers/originator_supplier.go +++ b/syft/format/internal/spdxutil/helpers/originator_supplier.go @@ -62,6 +62,10 @@ func Originator(p pkg.Package) (typ string, author string) { //nolint: funlen } } + case pkg.JavaVMInstallation: + typ = orgType + author = metadata.Release.Implementor + case pkg.LinuxKernelModule: author = metadata.Author diff --git a/syft/format/internal/spdxutil/helpers/originator_supplier_test.go b/syft/format/internal/spdxutil/helpers/originator_supplier_test.go index 67abf1dc5..4ed8fc2ca 100644 --- a/syft/format/internal/spdxutil/helpers/originator_supplier_test.go +++ b/syft/format/internal/spdxutil/helpers/originator_supplier_test.go @@ -178,6 +178,18 @@ func Test_OriginatorSupplier(t *testing.T) { }, // note: empty! }, + { + name: "from java -- jvm installation", + input: pkg.Package{ + Metadata: pkg.JavaVMInstallation{ + Release: pkg.JavaVMRelease{ + Implementor: "Oracle", + }, + }, + }, + originator: "Organization: Oracle", + supplier: "Organization: Oracle", + }, { name: "from linux kernel module", input: pkg.Package{ diff --git a/syft/internal/fileresolver/chroot_context.go b/syft/internal/fileresolver/chroot_context.go index a5245952b..f643411a8 100644 --- a/syft/internal/fileresolver/chroot_context.go +++ b/syft/internal/fileresolver/chroot_context.go @@ -140,6 +140,40 @@ func (r ChrootContext) ToNativePath(chrootPath string) (string, error) { return responsePath, nil } +func (r ChrootContext) ToNativeGlob(chrootPath string) (string, error) { + // split on any * + parts := strings.Split(chrootPath, "*") + if len(parts) == 0 || parts[0] == "" { + // either this is an empty string or a path that starts with * so there is nothing we can do + return chrootPath, nil + } + + if len(parts) == 1 { + // this has no glob, treat it like a path + return r.ToNativePath(chrootPath) + } + + responsePath := parts[0] + + if filepath.IsAbs(responsePath) { + // don't allow input to potentially hop above root path + responsePath = path.Join(r.root, responsePath) + } else { + // ensure we take into account any relative difference between the root path and the CWD for relative requests + responsePath = path.Join(r.cwdRelativeToRoot, responsePath) + } + + var err error + responsePath, err = filepath.Abs(responsePath) + if err != nil { + return "", err + } + + parts[0] = strings.TrimRight(responsePath, "/") + "/" + + return strings.Join(parts, "*"), nil +} + // ToChrootPath takes a path from the underlying fs domain and converts it to a path that is relative to the current root context. func (r ChrootContext) ToChrootPath(nativePath string) string { responsePath := nativePath diff --git a/syft/internal/fileresolver/chroot_context_test.go b/syft/internal/fileresolver/chroot_context_test.go index 2cd8befe1..245e08b63 100644 --- a/syft/internal/fileresolver/chroot_context_test.go +++ b/syft/internal/fileresolver/chroot_context_test.go @@ -479,3 +479,98 @@ func Test_ChrootContext_RequestResponse(t *testing.T) { }) } } + +func TestToNativeGlob(t *testing.T) { + tests := []struct { + name string + chrootContext ChrootContext + chrootPath string + expectedResult string + expectedError error + }{ + { + name: "ignore empty path", + chrootContext: ChrootContext{ + root: "/root", + cwdRelativeToRoot: "/cwd", + }, + chrootPath: "", + expectedResult: "", + expectedError: nil, + }, + { + name: "ignore if just a path", + chrootContext: ChrootContext{ + root: "/root", + cwdRelativeToRoot: "/cwd", + }, + chrootPath: "/some/path/file.txt", + expectedResult: "/root/some/path/file.txt", + expectedError: nil, + }, + { + name: "ignore starting with glob", + chrootContext: ChrootContext{ + root: "/root", + cwdRelativeToRoot: "/cwd", + }, + chrootPath: "*/relative/path/*", + expectedResult: "*/relative/path/*", + expectedError: nil, + }, + { + name: "absolute path with glob", + chrootContext: ChrootContext{ + root: "/root", + cwdRelativeToRoot: "/cwd", + }, + chrootPath: "/some/path/*", + expectedResult: "/root/some/path/*", + expectedError: nil, + }, + { + name: "relative path with glob", + chrootContext: ChrootContext{ + root: "/root", + cwdRelativeToRoot: "/cwd", + }, + chrootPath: "relative/path/*", + expectedResult: "/cwd/relative/path/*", + expectedError: nil, + }, + { + name: "relative path with no root", + chrootContext: ChrootContext{ + root: "", + cwdRelativeToRoot: "/cwd", + }, + chrootPath: "relative/path/*", + expectedResult: "/cwd/relative/path/*", + expectedError: nil, + }, + { + name: "globs everywhere", + chrootContext: ChrootContext{ + root: "/root", + cwdRelativeToRoot: "/cwd", + }, + chrootPath: "relative/path/**/file*.txt", + expectedResult: "/cwd/relative/path/**/file*.txt", + expectedError: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, err := tt.chrootContext.ToNativeGlob(tt.chrootPath) + + if tt.expectedError != nil { + assert.Error(t, err) + assert.Equal(t, tt.expectedError, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.expectedResult, result) + } + }) + } +} diff --git a/syft/internal/fileresolver/directory.go b/syft/internal/fileresolver/directory.go index fe1a55a7f..a86092f67 100644 --- a/syft/internal/fileresolver/directory.go +++ b/syft/internal/fileresolver/directory.go @@ -145,13 +145,21 @@ func (r Directory) FilesByPath(userPaths ...string) ([]file.Location, error) { return references, nil } +func (r Directory) requestGlob(pattern string) (string, error) { + return r.chroot.ToNativeGlob(pattern) +} + // FilesByGlob returns all file.References that match the given path glob pattern from any layer in the image. func (r Directory) FilesByGlob(patterns ...string) ([]file.Location, error) { uniqueFileIDs := stereoscopeFile.NewFileReferenceSet() uniqueLocations := make([]file.Location, 0) for _, pattern := range patterns { - refVias, err := r.searchContext.SearchByGlob(pattern, filetree.FollowBasenameLinks) + requestGlob, err := r.requestGlob(pattern) + if err != nil { + return nil, err + } + refVias, err := r.searchContext.SearchByGlob(requestGlob, filetree.FollowBasenameLinks) if err != nil { return nil, err } diff --git a/syft/internal/packagemetadata/generated.go b/syft/internal/packagemetadata/generated.go index 24b961753..d22cfcd77 100644 --- a/syft/internal/packagemetadata/generated.go +++ b/syft/internal/packagemetadata/generated.go @@ -27,6 +27,7 @@ func AllTypes() []any { pkg.HackageStackYamlEntry{}, pkg.HackageStackYamlLockEntry{}, pkg.JavaArchive{}, + pkg.JavaVMInstallation{}, pkg.LinuxKernel{}, pkg.LinuxKernelModule{}, pkg.LuaRocksPackage{}, diff --git a/syft/internal/packagemetadata/names.go b/syft/internal/packagemetadata/names.go index 8f8390c29..b382dceeb 100644 --- a/syft/internal/packagemetadata/names.go +++ b/syft/internal/packagemetadata/names.go @@ -81,6 +81,7 @@ var jsonTypes = makeJSONTypes( jsonNames(pkg.HackageStackYamlLockEntry{}, "haskell-hackage-stack-lock-entry", "HackageMetadataType"), jsonNamesWithoutLookup(pkg.HackageStackYamlEntry{}, "haskell-hackage-stack-entry", "HackageMetadataType"), // the legacy value is split into two types, where the other is preferred jsonNames(pkg.JavaArchive{}, "java-archive", "JavaMetadata"), + jsonNames(pkg.JavaVMInstallation{}, "java-jvm-installation"), jsonNames(pkg.MicrosoftKbPatch{}, "microsoft-kb-patch", "KbPatchMetadata"), jsonNames(pkg.LinuxKernel{}, "linux-kernel-archive", "LinuxKernel"), jsonNames(pkg.LinuxKernelModule{}, "linux-kernel-module", "LinuxKernelModule"), diff --git a/syft/pkg/cataloger/java/cataloger.go b/syft/pkg/cataloger/java/cataloger.go index 11e48b7f5..2affb83fd 100644 --- a/syft/pkg/cataloger/java/cataloger.go +++ b/syft/pkg/cataloger/java/cataloger.go @@ -43,3 +43,9 @@ func NewGradleLockfileCataloger() pkg.Cataloger { return generic.NewCataloger("java-gradle-lockfile-cataloger"). WithParserByGlobs(parseGradleLockfile, gradleLockfileGlob) } + +// NewJvmDistributionCataloger returns packages representing JDK/JRE installations (of multiple distribution types). +func NewJvmDistributionCataloger() pkg.Cataloger { + return generic.NewCataloger("java-jvm-cataloger"). + WithParserByGlobs(parseJVMRelease, jvmReleaseGlob) +} diff --git a/syft/pkg/cataloger/java/cataloger_test.go b/syft/pkg/cataloger/java/cataloger_test.go index 84ba1ea91..9df9825df 100644 --- a/syft/pkg/cataloger/java/cataloger_test.go +++ b/syft/pkg/cataloger/java/cataloger_test.go @@ -4,6 +4,9 @@ import ( "testing" "github.com/anchore/syft/syft/cataloging" + "github.com/anchore/syft/syft/cpe" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" ) @@ -102,3 +105,113 @@ func Test_POMCataloger_Globs(t *testing.T) { }) } } + +func TestJvmDistributionCataloger(t *testing.T) { + + cases := []struct { + name string + fixture string + expected pkg.Package + }{ + { + name: "valid 1.8.0", + fixture: "test-fixtures/jvm-installs/oracle-jdk-se-8", + expected: pkg.Package{ + Name: "jdk", + Version: "1.8.0_411-b25", + FoundBy: "java-jvm-cataloger", + Locations: file.NewLocationSet(file.NewLocation("usr/lib/jvm/jdk-1.8-oracle-x64/release")), + Licenses: pkg.NewLicenseSet(), + Type: pkg.BinaryPkg, + CPEs: []cpe.CPE{ + cpe.Must("cpe:2.3:a:oracle:java_se:1.8.0:update411:*:*:*:*:*:*", cpe.DeclaredSource), + 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", + Metadata: pkg.JavaVMInstallation{ + Release: pkg.JavaVMRelease{ + JavaRuntimeVersion: "1.8.0_411-b25", + JavaVersion: "1.8.0_411", + OsArch: "amd64", + OsName: "Linux", + OsVersion: "2.6", + Source: ".:git:71ec2089cf8c+", + BuildType: "commercial", + }, + Files: []string{ + "usr/lib/jvm/jdk-1.8-oracle-x64/bin/javac", + "usr/lib/jvm/jdk-1.8-oracle-x64/release", + }, + }, + }, + }, + { + 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", + Metadata: pkg.JavaVMInstallation{ + Release: pkg.JavaVMRelease{ + Implementor: "Eclipse Adoptium", + ImplementorVersion: "Temurin-21.0.4+7", + JavaRuntimeVersion: "21.0.4+7-LTS", + JavaVersion: "21.0.4", + JavaVersionDate: "2024-07-16", + Libc: "gnu", + Modules: []string{ + "java.base", "java.compiler", "java.datatransfer", "java.xml", "java.prefs", + "java.desktop", "java.instrument", "java.logging", "java.management", + "java.security.sasl", "java.naming", "java.rmi", "java.management.rmi", + "java.net.http", "java.scripting", "java.security.jgss", + "java.transaction.xa", "java.sql", "java.sql.rowset", "java.xml.crypto", "java.se", + "java.smartcardio", "jdk.accessibility", "jdk.internal.jvmstat", "jdk.attach", + "jdk.charsets", "jdk.internal.opt", "jdk.zipfs", "jdk.compiler", "jdk.crypto.ec", + "jdk.crypto.cryptoki", "jdk.dynalink", "jdk.internal.ed", "jdk.editpad", "jdk.hotspot.agent", + "jdk.httpserver", "jdk.incubator.vector", "jdk.internal.le", "jdk.internal.vm.ci", + "jdk.internal.vm.compiler", "jdk.internal.vm.compiler.management", "jdk.jartool", + "jdk.javadoc", "jdk.jcmd", "jdk.management", "jdk.management.agent", "jdk.jconsole", + "jdk.jdeps", "jdk.jdwp.agent", "jdk.jdi", "jdk.jfr", "jdk.jlink", "jdk.jpackage", "jdk.jshell", + "jdk.jsobject", "jdk.jstatd", "jdk.localedata", "jdk.management.jfr", "jdk.naming.dns", + "jdk.naming.rmi", "jdk.net", "jdk.nio.mapmode", "jdk.random", "jdk.sctp", "jdk.security.auth", + "jdk.security.jgss", "jdk.unsupported", "jdk.unsupported.desktop", "jdk.xml.dom", + }, + OsArch: "aarch64", + OsName: "Linux", + Source: ".:git:13710926b798", + BuildSource: "git:1271f10a26c47e1489a814dd2731f936a588d621", + BuildSourceRepo: "https://github.com/adoptium/temurin-build.git", + SourceRepo: "https://github.com/adoptium/jdk21u.git", + FullVersion: "21.0.4+7-LTS", + SemanticVersion: "21.0.4+7", + BuildInfo: "OS: Linux Version: 5.4.0-150-generic", + JvmVariant: "Hotspot", + JvmVersion: "21.0.4+7-LTS", + ImageType: "JDK", + }, + Files: []string{ + "jvm/openjdk/release", + "jvm/openjdk/sibling/child/file1.txt", + }, + }, + }, + }, + } + + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + p := tt.expected + p.SetID() + + pkgtest.TestCataloger(t, tt.fixture, NewJvmDistributionCataloger(), []pkg.Package{p}, nil) + }) + } + +} diff --git a/syft/pkg/cataloger/java/parse_jvm_release.go b/syft/pkg/cataloger/java/parse_jvm_release.go new file mode 100644 index 000000000..e39be4779 --- /dev/null +++ b/syft/pkg/cataloger/java/parse_jvm_release.go @@ -0,0 +1,423 @@ +package java + +import ( + "bufio" + "context" + "fmt" + "io" + "path" + "sort" + "strings" + + "github.com/mitchellh/mapstructure" + + "github.com/anchore/packageurl-go" + stereoFile "github.com/anchore/stereoscope/pkg/file" + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/cpe" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/generic" +) + +const ( + // this is a very permissive glob that will match more than just the JVM release file. + // we started with "**/{java,jvm}/*/release", but this prevents scanning JVM archive contents (e.g. jdk8u402.zip). + // this approach lets us check more files for JVM release info, but be rather silent about errors. + jvmReleaseGlob = "**/release" + oracleVendor = "oracle" + openJdkProduct = "openjdk" + jre = "jre" + jdk = "jdk" +) + +// the /opt/java/openjdk/release file (and similar paths) is a file that is present in the multiple OpenJDK distributions +// here's an example of the contents of the file: +// +// IMPLEMENTOR="Eclipse Adoptium" +// IMPLEMENTOR_VERSION="Temurin-21.0.4+7" +// JAVA_RUNTIME_VERSION="21.0.4+7-LTS" +// JAVA_VERSION="21.0.4" +// JAVA_VERSION_DATE="2024-07-16" +// LIBC="gnu" +// MODULES="java.base java.compiler java.datatransfer java.xml java.prefs java.desktop java.instrument java.logging java.management java.security.sasl java.naming java.rmi java.management.rmi java.net.http java.scripting java.security.jgss java.transaction.xa java.sql java.sql.rowset java.xml.crypto java.se java.smartcardio jdk.accessibility jdk.internal.jvmstat jdk.attach jdk.charsets jdk.internal.opt jdk.zipfs jdk.compiler jdk.crypto.ec jdk.crypto.cryptoki jdk.dynalink jdk.internal.ed jdk.editpad jdk.hotspot.agent jdk.httpserver jdk.incubator.vector jdk.internal.le jdk.internal.vm.ci jdk.internal.vm.compiler jdk.internal.vm.compiler.management jdk.jartool jdk.javadoc jdk.jcmd jdk.management jdk.management.agent jdk.jconsole jdk.jdeps jdk.jdwp.agent jdk.jdi jdk.jfr jdk.jlink jdk.jpackage jdk.jshell jdk.jsobject jdk.jstatd jdk.localedata jdk.management.jfr jdk.naming.dns jdk.naming.rmi jdk.net jdk.nio.mapmode jdk.random jdk.sctp jdk.security.auth jdk.security.jgss jdk.unsupported jdk.unsupported.desktop jdk.xml.dom" +// OS_ARCH="aarch64" +// OS_NAME="Linux" +// SOURCE=".:git:13710926b798" +// BUILD_SOURCE="git:1271f10a26c47e1489a814dd2731f936a588d621" +// BUILD_SOURCE_REPO="https://github.com/adoptium/temurin-build.git" +// SOURCE_REPO="https://github.com/adoptium/jdk21u.git" +// FULL_VERSION="21.0.4+7-LTS" +// SEMANTIC_VERSION="21.0.4+7" +// BUILD_INFO="OS: Linux Version: 5.4.0-150-generic" +// JVM_VARIANT="Hotspot" +// JVM_VERSION="21.0.4+7-LTS" +// IMAGE_TYPE="JDK" +// +// In terms of the temurin flavor, these are controlled by: +// - config: https://github.com/adoptium/temurin-build/blob/v2023.01.03/sbin/common/config_init.sh +// - build script: https://github.com/adoptium/temurin-build/blob/v2023.01.03/sbin/build.sh#L1584-L1796 + +type jvmCpeInfo struct { + vendor, product, version string +} + +func parseJVMRelease(_ context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { + ri, err := parseJvmReleaseInfo(reader) + if err != nil { + return nil, nil, fmt.Errorf("unable to parse JVM release info %q: %w", reader.Path(), err) + } + + if ri == nil { + // TODO: known-unknown: expected JDK installation package + return nil, nil, nil + } + + version := jvmPackageVersion(ri) + // TODO: detect old and new version format from multiple fields + + licenses := jvmLicenses(resolver, ri) + + locations := file.NewLocationSet(reader.Location) + + for _, lic := range licenses.ToSlice() { + locations.Add(lic.Locations.ToSlice()...) + } + + installDir := path.Dir(reader.Path()) + files, hasJdk := findJvmFiles(resolver, installDir) + + vendor, product := jvmPrimaryVendorProduct(ri.Implementor, reader.Path(), ri.ImageType, hasJdk) + + p := pkg.Package{ + Name: product, + Locations: locations, + Version: version, + CPEs: jvmCpes(version, vendor, product, ri.ImageType, hasJdk), + PURL: jvmPurl(*ri, version, vendor, product), + Licenses: licenses, + Type: pkg.BinaryPkg, + Metadata: pkg.JavaVMInstallation{ + Release: *ri, + Files: files, + }, + } + p.SetID() + + return []pkg.Package{p}, nil, nil +} + +func jvmLicenses(_ file.Resolver, _ *pkg.JavaVMRelease) pkg.LicenseSet { + // TODO: get this from the dir()/legal/**/LICENSE files when we start cataloging license content + // see https://github.com/anchore/syft/issues/656 + return pkg.NewLicenseSet() +} + +func findJvmFiles(resolver file.Resolver, installDir string) ([]string, bool) { + ownedLocations, err := resolver.FilesByGlob(installDir + "/**") + if err != nil { + // TODO: known-unknowns + log.WithFields("path", installDir, "error", err).Trace("unable to find installed JVM files") + } + + var results []string + var hasJdk bool + for _, loc := range ownedLocations { + p := loc.Path() + results = append(results, p) + if !hasJdk && strings.HasSuffix(p, "bin/javac") { + hasJdk = true + } + } + + sort.Strings(results) + + return results, hasJdk +} + +func jvmPurl(ri pkg.JavaVMRelease, version, vendor, product string) string { + var qualifiers []packageurl.Qualifier + if ri.SourceRepo != "" { + qualifiers = append(qualifiers, packageurl.Qualifier{ + Key: "repository_url", + Value: ri.SourceRepo, + }) + } else if ri.BuildSourceRepo != "" { + qualifiers = append(qualifiers, packageurl.Qualifier{ + Key: "repository_url", + Value: ri.BuildSourceRepo, + }) + } + + pURL := packageurl.NewPackageURL( + packageurl.TypeGeneric, + vendor, + product, + version, + qualifiers, + "") + return pURL.ToString() +} + +func jvmPrimaryVendorProduct(implementor, path, imageType string, hasJdk bool) (string, string) { + implementor = strings.ReplaceAll(strings.ToLower(implementor), " ", "") + + pickProduct := func() string { + if hasJdk || jvmProjectByType(imageType) == jdk { + return jdk + } + return jre + } + + switch { + case strings.Contains(implementor, "azul") || strings.Contains(path, "zulu"): + return "azul", "zulu" + + case strings.Contains(implementor, "sun"): + return "sun", pickProduct() + + case strings.Contains(implementor, "oracle") || strings.Contains(path, "oracle"): + return oracleVendor, pickProduct() + } + return oracleVendor, openJdkProduct +} + +func jvmCpes(version, primaryVendor, primaryProduct, imageType string, hasJdk bool) []cpe.CPE { + // see https://github.com/anchore/syft/issues/2422 for more context + + var candidates []jvmCpeInfo + + newCandidate := func(ven, prod, ver string) { + candidates = append(candidates, jvmCpeInfo{ + vendor: ven, + product: prod, + version: ver, + }) + } + + newEnterpriseCandidate := func(ven, ver string) { + newCandidate(ven, jre, ver) + if hasJdk || jvmProjectByType(imageType) == jdk { + newCandidate(ven, jdk, ver) + } + } + + switch { + case primaryVendor == "azul": + newCandidate(primaryVendor, "zulu", version) + newCandidate(oracleVendor, openJdkProduct, version) + + case primaryVendor == "sun": + newEnterpriseCandidate(primaryVendor, version) + + case primaryVendor == oracleVendor && primaryProduct != openJdkProduct: + newCandidate(primaryVendor, "java_se", version) + newEnterpriseCandidate(primaryVendor, version) + default: + newCandidate(primaryVendor, primaryProduct, version) + } + + var cpes []cpe.CPE + for _, candidate := range candidates { + c := newJvmCpe(candidate) + if c == nil { + continue + } + cpes = append(cpes, *c) + } + + return cpes +} + +func getJVMVersionAndUpdate(version string) (string, string) { + hasPlus := strings.Contains(version, "+") + hasUnderscore := strings.Contains(version, "_") + + switch { + case hasUnderscore: + // assume legacy version strings are provided + // example: 1.8.0_302-b08 + fields := strings.Split(version, "_") + if len(fields) == 2 { + shortVer := fields[0] + fields = strings.Split(fields[1], "-") + return shortVer, fields[0] + } + case hasPlus: + // assume JEP 223 version strings are provided + // example: 9.0.1+20 + fields := strings.Split(version, "+") + return fields[0], "" + } + + // this could be a legacy or modern string that does not have an update + return version, "" +} + +func newJvmCpe(candidate jvmCpeInfo) *cpe.CPE { + if candidate.vendor == "" || candidate.product == "" || candidate.version == "" { + return nil + } + + shortVer, update := getJVMVersionAndUpdate(candidate.version) + + if shortVer == "" { + return nil + } + + if update != "" && !strings.Contains(strings.ToLower(update), "update") { + update = "update" + trim0sFromLeft(update) + } + + return &cpe.CPE{ + Attributes: cpe.Attributes{ + Part: "a", + Vendor: candidate.vendor, + Product: candidate.product, + Version: shortVer, + Update: update, + }, + // note: we must use a declared source here. Though we are not directly raising up raw CPEs from cataloged material, + // these are vastly more reliable and accurate than what would be generated from the cpe generator logic. + // We want these CPEs to override any generated CPEs (and in fact prevent the generation of CPEs for these packages altogether). + Source: cpe.DeclaredSource, + } +} + +func jvmProjectByType(ty string) string { + if strings.Contains(strings.ToLower(ty), jre) { + return jre + } + return jdk +} + +// jvmPackageVersion attempts to extract the correct version value for the JVM given a platter of version strings to choose +// from, and makes special consideration to what a valid version is relative to JEP 223. +// +// example version values (openjdk >8): +// +// IMPLEMENTOR_VERSION "Temurin-21.0.4+7" +// JAVA_RUNTIME_VERSION "21.0.4+7-LTS" +// FULL_VERSION "21.0.4+7-LTS" +// SEMANTIC_VERSION "21.0.4+7" +// JAVA_VERSION "21.0.4" +// +// example version values (openjdk 8): +// +// JAVA_VERSION "1.8.0_422" +// FULL_VERSION "1.8.0_422-b05" +// SEMANTIC_VERSION "8.0.422+5" +// +// example version values (openjdk 8, but older): +// +// JAVA_VERSION "1.8.0_302" +// FULL_VERSION "1.8.0_302-b08" +// SEMANTIC_VERSION "8.0.302+8" +// +// example version values (oracle): +// +// IMPLEMENTOR_VERSION (missing) +// JAVA_RUNTIME_VERSION "22.0.2+9-70" +// JAVA_VERSION "22.0.2" +// +// example version values (mariner): +// +// IMPLEMENTOR_VERSION "Microsoft-9889599" +// JAVA_RUNTIME_VERSION "17.0.12+7-LTS" +// JAVA_VERSION "17.0.12" +// +// example version values (amazon): +// +// IMPLEMENTOR_VERSION "Corretto-17.0.12.7.1" +// JAVA_RUNTIME_VERSION "17.0.12+7-LTS" +// JAVA_VERSION "17.0.12" +// +// JEP 223 changes to JVM version string in the following way: +// +// Pre JEP 223 Post JEP 223 +// Release Type long short long short +// ------------ -------------------- -------------------- +// Early Access 1.9.0-ea-b19 9-ea 9-ea+19 9-ea +// Major 1.9.0-b100 9 9+100 9 +// Security #1 1.9.0_5-b20 9u5 9.0.1+20 9.0.1 +// Security #2 1.9.0_11-b12 9u11 9.0.2+12 9.0.2 +// Minor #1 1.9.0_20-b62 9u20 9.1.2+62 9.1.2 +// Security #3 1.9.0_25-b15 9u25 9.1.3+15 9.1.3 +// Security #4 1.9.0_31-b08 9u31 9.1.4+8 9.1.4 +// Minor #2 1.9.0_40-b45 9u40 9.2.4+45 9.2.4 +// +// What does this mean for us? In terms of the version selected, use semver-compliant strings when available. +// +// In terms of where to get the version: +// +// SEMANTIC_VERSION Reasonably prevalent, but most accurate in terms of comparable versions +// JAVA_RUNTIME_VERSION Reasonable prevalent, but difficult to distinguish pre-release info vs aux info (jep 223 sensitive) +// FULL_VERSION Reasonable prevalent, but difficult to distinguish pre-release info vs aux info (jep 223 sensitive) +// JAVA_VERSION Most prevalent, but least specific (jep 223 sensitive) +// IMPLEMENTOR_VERSION Unusable or missing in some cases +func jvmPackageVersion(ri *pkg.JavaVMRelease) string { + var version string + switch { + case ri.JavaRuntimeVersion != "": + return ri.JavaRuntimeVersion + case ri.FullVersion != "": + // if the full version major version matches the java version major version, then use the full version + fullMajor := strings.Split(ri.FullVersion, ".")[0] + javaMajor := strings.Split(ri.JavaVersion, ".")[0] + if fullMajor == javaMajor { + return ri.FullVersion + } + fallthrough + case ri.JavaVersion != "": + return ri.JavaVersion + } + + return version +} + +func trim0sFromLeft(v string) string { + if v == "0" { + return v + } + return strings.TrimLeft(v, "0") +} + +func parseJvmReleaseInfo(r io.ReadCloser) (*pkg.JavaVMRelease, error) { + defer r.Close() + + data := make(map[string]any) + scanner := bufio.NewScanner(io.LimitReader(r, 500*stereoFile.KB)) + + for scanner.Scan() { + line := scanner.Text() + parts := strings.SplitN(line, "=", 2) + if len(parts) != 2 { + continue + } + key := parts[0] + value := strings.Trim(parts[1], `"`) + + if key == "MODULES" { + data[key] = strings.Split(value, " ") + } else { + data[key] = value + } + } + + if err := scanner.Err(); err != nil { + return nil, err + } + + // if we're missing key fields, then we don't have a JVM release file + if data["JAVA_VERSION"] == nil && data["JAVA_RUNTIME_VERSION"] == nil { + return nil, nil + } + + var ri pkg.JavaVMRelease + if err := mapstructure.Decode(data, &ri); err != nil { + return nil, err + } + + return &ri, nil +} diff --git a/syft/pkg/cataloger/java/parse_jvm_release_test.go b/syft/pkg/cataloger/java/parse_jvm_release_test.go new file mode 100644 index 000000000..5102ed2e9 --- /dev/null +++ b/syft/pkg/cataloger/java/parse_jvm_release_test.go @@ -0,0 +1,438 @@ +package java + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/anchore/syft/syft/cpe" + "github.com/anchore/syft/syft/pkg" +) + +func TestJvmCpes(t *testing.T) { + tests := []struct { + name string + pkgVersion string + primaryVendor string + primaryProduct string + imageType string + hasJdk bool + expected []cpe.CPE + }{ + { + name: "zulu release", + pkgVersion: "9.0.1+20", + primaryVendor: "azul", + primaryProduct: "zulu", + imageType: "jdk", + expected: []cpe.CPE{ + { + Attributes: cpe.Attributes{ + Part: "a", + Vendor: "azul", + Product: "zulu", + Version: "9.0.1", + Update: "", + }, + Source: cpe.DeclaredSource, + }, + { + Attributes: cpe.Attributes{ + Part: "a", + Vendor: "oracle", + Product: "openjdk", + Version: "9.0.1", + Update: "", + }, + Source: cpe.DeclaredSource, + }, + }, + }, + { + name: "sun release", + pkgVersion: "1.6.0_322-b002", + primaryVendor: "sun", + primaryProduct: "jre", + imageType: "jre", + hasJdk: true, + expected: []cpe.CPE{ + { + Attributes: cpe.Attributes{ + Part: "a", + Vendor: "sun", + Product: "jre", + Version: "1.6.0", + Update: "update322", + }, + Source: cpe.DeclaredSource, + }, + { + Attributes: cpe.Attributes{ + Part: "a", + Vendor: "sun", + Product: "jdk", + Version: "1.6.0", + Update: "update322", + }, + Source: cpe.DeclaredSource, + }, + }, + }, + { + name: "oracle se release", + pkgVersion: "1.8.0_322-b02", + primaryVendor: "oracle", + primaryProduct: "java_se", + imageType: "jdk", + hasJdk: true, + expected: []cpe.CPE{ + { + Attributes: cpe.Attributes{ + Part: "a", + Vendor: "oracle", + Product: "java_se", + Version: "1.8.0", + Update: "update322", + }, + Source: cpe.DeclaredSource, + }, + { + Attributes: cpe.Attributes{ + Part: "a", + Vendor: "oracle", + Product: "jre", + Version: "1.8.0", + Update: "update322", + }, + Source: cpe.DeclaredSource, + }, + { + Attributes: cpe.Attributes{ + Part: "a", + Vendor: "oracle", + Product: "jdk", + Version: "1.8.0", + Update: "update322", + }, + Source: cpe.DeclaredSource, + }, + }, + }, + { + name: "JEP 223 version with build info", + pkgVersion: "9.0.1+20", + primaryVendor: "oracle", + primaryProduct: "openjdk", + imageType: "openjdk", + expected: []cpe.CPE{ + { + Attributes: cpe.Attributes{ + Part: "a", + Vendor: "oracle", + Product: "openjdk", + Version: "9.0.1", + Update: "", + }, + Source: cpe.DeclaredSource, + }, + }, + }, + { + name: "JEP 223 version without build info", + pkgVersion: "11.0.9", + primaryVendor: "oracle", + primaryProduct: "openjdk", + imageType: "openjdk", + expected: []cpe.CPE{ + { + Attributes: cpe.Attributes{ + Part: "a", + Vendor: "oracle", + Product: "openjdk", + Version: "11.0.9", + Update: "", + }, + Source: cpe.DeclaredSource, + }, + }, + }, + { + name: "no plus sign in version string", + pkgVersion: "1.8.0", + primaryVendor: "oracle", + primaryProduct: "openjdk", + imageType: "openjdk", + expected: []cpe.CPE{ + { + Attributes: cpe.Attributes{ + Part: "a", + Vendor: "oracle", + Product: "openjdk", + Version: "1.8.0", + Update: "", + }, + Source: cpe.DeclaredSource, + }, + }, + }, + { + name: "empty version string", + pkgVersion: "", + primaryVendor: "oracle", + primaryProduct: "", + imageType: "", + expected: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := jvmCpes(tt.pkgVersion, tt.primaryVendor, tt.primaryProduct, tt.imageType, tt.hasJdk) + assert.Equal(t, tt.expected, result) + }) + } +} + +func TestJvmVersion(t *testing.T) { + tests := []struct { + name string + input *pkg.JavaVMRelease + expected string + }{ + + { + name: "JavaRuntimeVersion fallback", + input: &pkg.JavaVMRelease{ + JavaRuntimeVersion: "21.0.4+7-LTS", + JavaVersion: "bogus", + FullVersion: "bogus", + SemanticVersion: "bogus", + }, + expected: "21.0.4+7-LTS", + }, + { + name: "JavaVersion fallback", + input: &pkg.JavaVMRelease{ + JavaVersion: "21.0.4", + FullVersion: "bogus", + SemanticVersion: "bogus", + }, + expected: "21.0.4", + }, + { + // there is an example of this in eclipse-temurin:8u312-b07-jdk + name: "FullVersion is more accurate", + input: &pkg.JavaVMRelease{ + JavaVersion: "1.8.0_131", + FullVersion: "1.8.0_131+b08", + }, + expected: "1.8.0_131+b08", + }, + { + name: "empty input fields", + input: &pkg.JavaVMRelease{}, + expected: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := jvmPackageVersion(tt.input) + assert.Equal(t, tt.expected, result) + }) + } +} + +func TestGetJVMVersionAndUpdate(t *testing.T) { + tests := []struct { + name string + version string + expectedVer string + expectedUpdate string + }{ + { + name: "legacy version with underscore and build", + version: "1.8.0_302-b08", + expectedVer: "1.8.0", + expectedUpdate: "302", + }, + { + name: "legacy version with underscore but no build", + version: "1.8.0_302", + expectedVer: "1.8.0", + expectedUpdate: "302", + }, + { + name: "JEP 223 version with plus sign", + version: "9.0.1+20", + expectedVer: "9.0.1", + expectedUpdate: "", + }, + { + name: "JEP 223 version with plus but no update", + version: "11.0.9+", + expectedVer: "11.0.9", + expectedUpdate: "", + }, + { + name: "modern version without plus or underscore", + version: "11.0.9", + expectedVer: "11.0.9", + expectedUpdate: "", + }, + { + name: "legacy version without underscore or plus", + version: "1.7.0", + expectedVer: "1.7.0", + expectedUpdate: "", + }, + { + name: "empty version string", + version: "", + expectedVer: "", + expectedUpdate: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ver, update := getJVMVersionAndUpdate(tt.version) + assert.Equal(t, tt.expectedVer, ver) + assert.Equal(t, tt.expectedUpdate, update) + }) + } +} + +func TestJvmPrimaryVendorProduct(t *testing.T) { + tests := []struct { + name string + implementor string + path string + imageType string + hasJdk bool + expectedVendor string + expectedProduct string + }{ + { + name: "Azul implementor with Zulu in path", + implementor: "Azul Systems", + path: "/usr/lib/jvm/zulu-11-amd64/release", + imageType: "JDK", + hasJdk: true, + expectedVendor: "azul", + expectedProduct: "zulu", + }, + { + name: "Sun implementor with JDK", + implementor: "Sun Microsystems", + path: "/usr/lib/jvm/jdk-1.8-sun-amd64/release", + imageType: "JDK", + hasJdk: true, + expectedVendor: "sun", + expectedProduct: "jdk", + }, + { + name: "Oracle implementor with JRE", + implementor: "Oracle Corporation", + path: "/usr/lib/jvm/jdk-1.8-oracle-x64/release", + imageType: "JRE", + hasJdk: false, + expectedVendor: "oracle", + expectedProduct: "jre", + }, + { + name: "Oracle vendor with JDK in path", + implementor: "", + path: "/usr/lib/jvm/jdk-1.8-oracle-x64/release", + imageType: "JDK", + hasJdk: true, + expectedVendor: "oracle", + expectedProduct: "jdk", + }, + { + name: "OpenJDK with JDK", + implementor: "OpenJDK", + path: "/opt/java/openjdk/release", + imageType: "JDK", + hasJdk: true, + expectedVendor: "oracle", // like temurin + expectedProduct: "openjdk", + }, + { + name: "Amazon Corretto with JDK", + implementor: "Amazon Corretto", + path: "/usr/lib/jvm/java-17-amazon-corretto/release", + imageType: "JDK", + hasJdk: true, + expectedVendor: "oracle", // corretto upstream is oracle openjdk + expectedProduct: "openjdk", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + vendor, product := jvmPrimaryVendorProduct(tt.implementor, tt.path, tt.imageType, tt.hasJdk) + assert.Equal(t, tt.expectedVendor, vendor) + assert.Equal(t, tt.expectedProduct, product) + }) + } +} + +func TestJvmPurl(t *testing.T) { + tests := []struct { + name string + ri pkg.JavaVMRelease + version string + vendor string + product string + expectedPURL string + }{ + { + name: "build source repo provided", + ri: pkg.JavaVMRelease{ + BuildSourceRepo: "https://github.com/adoptium/temurin-build.git", + }, + version: "21.0.4", + vendor: "oracle", + product: "jdk", + expectedPURL: "pkg:generic/oracle/jdk@21.0.4?repository_url=https://github.com/adoptium/temurin-build.git", + }, + { + name: "source repo provided, no build source repo", + ri: pkg.JavaVMRelease{ + SourceRepo: "https://github.com/adoptium/jdk21u.git", + }, + version: "21.0.4", + vendor: "azul", + product: "zulu", + expectedPURL: "pkg:generic/azul/zulu@21.0.4?repository_url=https://github.com/adoptium/jdk21u.git", + }, + { + name: "no repository URLs provided", + ri: pkg.JavaVMRelease{ + // No repository URLs provided + }, + version: "17.0.2", + vendor: "oracle", + product: "jdk", + expectedPURL: "pkg:generic/oracle/jdk@17.0.2", + }, + { + name: "JRE with source repo", + ri: pkg.JavaVMRelease{ + SourceRepo: "https://github.com/adoptium/jre-repo.git", + }, + version: "1.8.0_302", + vendor: "oracle", + product: "jre", + expectedPURL: "pkg:generic/oracle/jre@1.8.0_302?repository_url=https://github.com/adoptium/jre-repo.git", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actualPURL := jvmPurl(tt.ri, tt.version, tt.vendor, tt.product) + assert.Equal(t, tt.expectedPURL, actualPURL) + }) + } +} diff --git a/syft/pkg/cataloger/java/test-fixtures/jvm-installs/oracle-jdk-se-8/usr/lib/jvm/.gitignore b/syft/pkg/cataloger/java/test-fixtures/jvm-installs/oracle-jdk-se-8/usr/lib/jvm/.gitignore new file mode 100644 index 000000000..b1265def4 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/jvm-installs/oracle-jdk-se-8/usr/lib/jvm/.gitignore @@ -0,0 +1 @@ +!/jdk-1.8-oracle-x64/bin \ No newline at end of file diff --git a/syft/pkg/cataloger/java/test-fixtures/jvm-installs/oracle-jdk-se-8/usr/lib/jvm/jdk-1.8-oracle-x64/bin/javac b/syft/pkg/cataloger/java/test-fixtures/jvm-installs/oracle-jdk-se-8/usr/lib/jvm/jdk-1.8-oracle-x64/bin/javac new file mode 100644 index 000000000..50a7dd611 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/jvm-installs/oracle-jdk-se-8/usr/lib/jvm/jdk-1.8-oracle-x64/bin/javac @@ -0,0 +1 @@ +compiler! \ No newline at end of file diff --git a/syft/pkg/cataloger/java/test-fixtures/jvm-installs/oracle-jdk-se-8/usr/lib/jvm/jdk-1.8-oracle-x64/release b/syft/pkg/cataloger/java/test-fixtures/jvm-installs/oracle-jdk-se-8/usr/lib/jvm/jdk-1.8-oracle-x64/release new file mode 100644 index 000000000..d80ca9cb6 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/jvm-installs/oracle-jdk-se-8/usr/lib/jvm/jdk-1.8-oracle-x64/release @@ -0,0 +1,7 @@ +JAVA_VERSION="1.8.0_411" +JAVA_RUNTIME_VERSION="1.8.0_411-b25" +OS_NAME="Linux" +OS_VERSION="2.6" +OS_ARCH="amd64" +SOURCE=".:git:71ec2089cf8c+" +BUILD_TYPE="commercial" diff --git a/syft/pkg/cataloger/java/test-fixtures/jvm-installs/valid-post-jep223/jvm/openjdk/release b/syft/pkg/cataloger/java/test-fixtures/jvm-installs/valid-post-jep223/jvm/openjdk/release new file mode 100644 index 000000000..13cf5f6a5 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/jvm-installs/valid-post-jep223/jvm/openjdk/release @@ -0,0 +1,19 @@ +IMPLEMENTOR="Eclipse Adoptium" +IMPLEMENTOR_VERSION="Temurin-21.0.4+7" +JAVA_RUNTIME_VERSION="21.0.4+7-LTS" +JAVA_VERSION="21.0.4" +JAVA_VERSION_DATE="2024-07-16" +LIBC="gnu" +MODULES="java.base java.compiler java.datatransfer java.xml java.prefs java.desktop java.instrument java.logging java.management java.security.sasl java.naming java.rmi java.management.rmi java.net.http java.scripting java.security.jgss java.transaction.xa java.sql java.sql.rowset java.xml.crypto java.se java.smartcardio jdk.accessibility jdk.internal.jvmstat jdk.attach jdk.charsets jdk.internal.opt jdk.zipfs jdk.compiler jdk.crypto.ec jdk.crypto.cryptoki jdk.dynalink jdk.internal.ed jdk.editpad jdk.hotspot.agent jdk.httpserver jdk.incubator.vector jdk.internal.le jdk.internal.vm.ci jdk.internal.vm.compiler jdk.internal.vm.compiler.management jdk.jartool jdk.javadoc jdk.jcmd jdk.management jdk.management.agent jdk.jconsole jdk.jdeps jdk.jdwp.agent jdk.jdi jdk.jfr jdk.jlink jdk.jpackage jdk.jshell jdk.jsobject jdk.jstatd jdk.localedata jdk.management.jfr jdk.naming.dns jdk.naming.rmi jdk.net jdk.nio.mapmode jdk.random jdk.sctp jdk.security.auth jdk.security.jgss jdk.unsupported jdk.unsupported.desktop jdk.xml.dom" +OS_ARCH="aarch64" +OS_NAME="Linux" +SOURCE=".:git:13710926b798" +BUILD_SOURCE="git:1271f10a26c47e1489a814dd2731f936a588d621" +BUILD_SOURCE_REPO="https://github.com/adoptium/temurin-build.git" +SOURCE_REPO="https://github.com/adoptium/jdk21u.git" +FULL_VERSION="21.0.4+7-LTS" +SEMANTIC_VERSION="21.0.4+7" +BUILD_INFO="OS: Linux Version: 5.4.0-150-generic" +JVM_VARIANT="Hotspot" +JVM_VERSION="21.0.4+7-LTS" +IMAGE_TYPE="JDK" diff --git a/syft/pkg/cataloger/java/test-fixtures/jvm-installs/valid-post-jep223/jvm/openjdk/sibling/child/file1.txt b/syft/pkg/cataloger/java/test-fixtures/jvm-installs/valid-post-jep223/jvm/openjdk/sibling/child/file1.txt new file mode 100644 index 000000000..ff15cec30 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/jvm-installs/valid-post-jep223/jvm/openjdk/sibling/child/file1.txt @@ -0,0 +1 @@ +content! \ No newline at end of file diff --git a/syft/pkg/java.go b/syft/pkg/java.go index 2a990b5d4..3bba12d19 100644 --- a/syft/pkg/java.go +++ b/syft/pkg/java.go @@ -18,6 +18,80 @@ var jenkinsPluginPomPropertiesGroupIDs = []string{ "com.cloudbees.jenkins.plugins", } +type JavaVMInstallation struct { + Release JavaVMRelease `json:"release"` + Files []string `json:"files"` +} + +func (m JavaVMInstallation) OwnedFiles() []string { + return m.Files +} + +type JavaVMRelease struct { + // Implementor is extracted with the `java.vendor` JVM property + Implementor string `mapstructure:"IMPLEMENTOR,omitempty" json:"implementor,omitempty"` + + // ImplementorVersion is extracted with the `java.vendor.version` JVM property + ImplementorVersion string `mapstructure:"IMPLEMENTOR_VERSION,omitempty" json:"implementorVersion,omitempty"` + + // JavaRuntimeVersion is extracted from the 'java.runtime.version' JVM property + JavaRuntimeVersion string `mapstructure:"JAVA_RUNTIME_VERSION,omitempty" json:"javaRuntimeVersion,omitempty"` + + // JavaVersion matches that from `java -version` command output + JavaVersion string `mapstructure:"JAVA_VERSION,omitempty" json:"javaVersion,omitempty"` + + // JavaVersionDate is extracted from the 'java.version.date' JVM property + JavaVersionDate string `mapstructure:"JAVA_VERSION_DATE,omitempty" json:"javaVersionDate,omitempty"` + + // Libc can either be 'glibc' or 'musl' + Libc string `mapstructure:"LIBC,omitempty" json:"libc,omitempty"` + + // Modules is a list of JVM modules that are packaged + Modules []string `mapstructure:"MODULES,omitempty" json:"modules,omitempty"` + + // OsArch is the target CPU architecture + OsArch string `mapstructure:"OS_ARCH,omitempty" json:"osArch,omitempty"` + + // OsName is the name of the target runtime operating system environment + OsName string `mapstructure:"OS_NAME,omitempty" json:"osName,omitempty"` + + // OsVersion is the version of the target runtime operating system environment + OsVersion string `mapstructure:"OS_VERSION,omitempty" json:"osVersion,omitempty"` + + // Source refers to the origin repository of OpenJDK source + Source string `mapstructure:"SOURCE,omitempty" json:"source,omitempty"` + + // BuildSource Git SHA of the build repository + BuildSource string `mapstructure:"BUILD_SOURCE,omitempty" json:"buildSource,omitempty"` + + // BuildSourceRepo refers to rhe repository URL for the build source + BuildSourceRepo string `mapstructure:"BUILD_SOURCE_REPO,omitempty" json:"buildSourceRepo,omitempty"` + + // SourceRepo refers to the OpenJDK repository URL + SourceRepo string `mapstructure:"SOURCE_REPO,omitempty" json:"sourceRepo,omitempty"` + + // FullVersion is extracted from the 'java.runtime.version' JVM property + FullVersion string `mapstructure:"FULL_VERSION,omitempty" json:"fullVersion,omitempty"` + + // SemanticVersion is derived from the OpenJDK version + SemanticVersion string `mapstructure:"SEMANTIC_VERSION,omitempty" json:"semanticVersion,omitempty"` + + // BuildInfo contains additional build information + BuildInfo string `mapstructure:"BUILD_INFO,omitempty" json:"buildInfo,omitempty"` + + // JvmVariant specifies the JVM variant (e.g., Hotspot or OpenJ9) + JvmVariant string `mapstructure:"JVM_VARIANT,omitempty" json:"jvmVariant,omitempty"` + + // JvmVersion is extracted from the 'java.vm.version' JVM property + JvmVersion string `mapstructure:"JVM_VERSION,omitempty" json:"jvmVersion,omitempty"` + + // ImageType can be 'JDK' or 'JRE' + ImageType string `mapstructure:"IMAGE_TYPE,omitempty" json:"imageType,omitempty"` + + // BuildType can be 'commercial' (used in some older oracle JDK distributions) + BuildType string `mapstructure:"BUILD_TYPE,omitempty" json:"buildType,omitempty"` +} + // JavaArchive encapsulates all Java ecosystem metadata for a package as well as an (optional) parent relationship. type JavaArchive struct { VirtualPath string `json:"virtualPath" cyclonedx:"virtualPath"` // we need to include the virtual path in cyclonedx documents to prevent deduplication of jars within jars From 92c1ddec5a84bb0e109c6ca02b216a5dcf0fd1a6 Mon Sep 17 00:00:00 2001 From: Christian Dupuis Date: Tue, 24 Sep 2024 23:05:16 +0200 Subject: [PATCH 222/284] fix: correct excluded mount point comparison to file paths (#3269) Signed-off-by: Christian Dupuis --- syft/internal/fileresolver/path_skipper.go | 13 ++++--- .../fileresolver/path_skipper_test.go | 37 +++++++++++++++++++ 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/syft/internal/fileresolver/path_skipper.go b/syft/internal/fileresolver/path_skipper.go index 4ae9bb361..496aaa017 100644 --- a/syft/internal/fileresolver/path_skipper.go +++ b/syft/internal/fileresolver/path_skipper.go @@ -93,12 +93,13 @@ func (ps pathSkipper) pathIndexVisitor(_ string, givenPath string, _ os.FileInfo for _, mi := range ps.mounts { conditionalPaths, ignorable := ps.ignorableMountTypes[mi.FSType] - if len(conditionalPaths) == 0 { - // Rule 1: ignore any path within a mount point that is of the given filesystem type unconditionally - if !containsPath(givenPath, mi.Mountpoint) { - continue - } + // Rule 0: Make sure the given path is within the mount point; if not let the scan continue + if !containsPath(givenPath, mi.Mountpoint) { + continue + } + // Rule 1: ignore any path within a mount point that is of the given filesystem type unconditionally + if len(conditionalPaths) == 0 { if !ignorable { // we've matched on the most specific path at this point, which means we should stop searching // mount points for this path @@ -151,7 +152,7 @@ func simpleClean(p string) string { return "." } if p == "/" { - return "/" + return "" } return strings.TrimSuffix(p, "/") } diff --git a/syft/internal/fileresolver/path_skipper_test.go b/syft/internal/fileresolver/path_skipper_test.go index d4e501eca..14b6b3b00 100644 --- a/syft/internal/fileresolver/path_skipper_test.go +++ b/syft/internal/fileresolver/path_skipper_test.go @@ -358,6 +358,43 @@ func Test_newPathSkipper(t *testing.T) { }, }, }, + { + name: "buildkit github ubuntu 22.04", + root: "/run/src/core/sbom", + mounts: []*mountinfo.Info{ + {Mountpoint: "/", FSType: "overlay"}, + {Mountpoint: "/proc", FSType: "proc"}, + {Mountpoint: "/dev", FSType: "tmpfs"}, + {Mountpoint: "/dev/pts", FSType: "devpts"}, + {Mountpoint: "/dev/shm", FSType: "tmpfs"}, + {Mountpoint: "/dev/mqueue", FSType: "mqueue"}, + {Mountpoint: "/sys", FSType: "sysfs"}, + {Mountpoint: "/etc/resolv.conf", FSType: "ext4"}, + {Mountpoint: "/etc/hosts", FSType: "ext4"}, + {Mountpoint: "/sys/fs/cgroup", FSType: "cgroup2"}, + {Mountpoint: "/run/out", FSType: "ext4"}, + {Mountpoint: "/run/src/core/sbom", FSType: "overlay"}, + {Mountpoint: "/tmp", FSType: "tmpfs"}, + {Mountpoint: "/dev/otel-grpc.sock", FSType: "overlay"}, + {Mountpoint: "/proc/bus", FSType: "proc"}, + {Mountpoint: "/proc/fs", FSType: "proc"}, + {Mountpoint: "/proc/irq", FSType: "proc"}, + {Mountpoint: "/proc/sys", FSType: "proc"}, + {Mountpoint: "/proc/sysrq-trigger", FSType: "proc"}, + {Mountpoint: "/proc/acpi", FSType: "tmpfs"}, + {Mountpoint: "/proc/kcore", FSType: "tmpfs"}, + {Mountpoint: "/proc/keys", FSType: "tmpfs"}, + {Mountpoint: "/proc/latency_stats", FSType: "tmpfs"}, + {Mountpoint: "/proc/timer_list", FSType: "tmpfs"}, + {Mountpoint: "/sys/firmware", FSType: "tmpfs"}, + {Mountpoint: "/proc/scsi", FSType: "tmpfs"}, + }, + want: []expect{ + { + path: "/run/src/core/sbom", + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { From d7005d7d8ca6d05f594f7bc1a140ae1e85bc0328 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 25 Sep 2024 08:56:21 -0400 Subject: [PATCH 223/284] add awaiting response management (#3272) Signed-off-by: Alex Goodman --- .github/workflows/remove-awaiting-response-label.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/workflows/remove-awaiting-response-label.yaml diff --git a/.github/workflows/remove-awaiting-response-label.yaml b/.github/workflows/remove-awaiting-response-label.yaml new file mode 100644 index 000000000..0f3b50c4f --- /dev/null +++ b/.github/workflows/remove-awaiting-response-label.yaml @@ -0,0 +1,11 @@ +name: "Manage Awaiting Response Label" + +on: + issue_comment: + types: [created] + +jobs: + run: + uses: "anchore/workflows/.github/workflows/remove-awaiting-response-label.yaml@main" + secrets: + token: ${{ secrets.OSS_PROJECT_GH_TOKEN }} From 39b2bf5518f6a0a985c512c2d58e9888afb60da9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Sep 2024 13:48:12 -0400 Subject: [PATCH 224/284] chore(deps): bump actions/checkout from 4.1.7 to 4.2.0 (#3283) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 4.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...d632683dd7b4114ad314bca15554477dd762a938) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/benchmark-testing.yaml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/detect-schema-changes.yaml | 2 +- .github/workflows/release-version-file.yaml | 2 +- .github/workflows/release.yaml | 4 ++-- .../workflows/test-fixture-cache-publish.yaml | 2 +- .github/workflows/update-bootstrap-tools.yml | 2 +- .../workflows/update-cpe-dictionary-index.yml | 2 +- .github/workflows/update-stereoscope-release.yml | 2 +- .github/workflows/validations.yaml | 16 ++++++++-------- 10 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/benchmark-testing.yaml b/.github/workflows/benchmark-testing.yaml index 9fff8c76a..c749bdcbe 100644 --- a/.github/workflows/benchmark-testing.yaml +++ b/.github/workflows/benchmark-testing.yaml @@ -17,7 +17,7 @@ jobs: # the job by event. steps: - name: Checkout code - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - name: Bootstrap environment uses: ./.github/actions/bootstrap diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index b02e5a3b0..51c80c4fd 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -36,7 +36,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 - name: Install Go uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 #v5.0.2 diff --git a/.github/workflows/detect-schema-changes.yaml b/.github/workflows/detect-schema-changes.yaml index 1241d687b..77e211a56 100644 --- a/.github/workflows/detect-schema-changes.yaml +++ b/.github/workflows/detect-schema-changes.yaml @@ -30,7 +30,7 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 - run: python .github/scripts/labeler.py env: diff --git a/.github/workflows/release-version-file.yaml b/.github/workflows/release-version-file.yaml index 6635a053f..cc18ef418 100644 --- a/.github/workflows/release-version-file.yaml +++ b/.github/workflows/release-version-file.yaml @@ -20,7 +20,7 @@ jobs: release: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 - name: Update version file run: make ci-release-version-file diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index bf3e7db49..b581dc147 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -15,7 +15,7 @@ jobs: environment: release runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 - name: Check if running on main if: github.ref != 'refs/heads/main' @@ -105,7 +105,7 @@ jobs: # required for goreleaser signs section with cosign id-token: write steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/test-fixture-cache-publish.yaml b/.github/workflows/test-fixture-cache-publish.yaml index 3144a0b6b..bd23cf1ce 100644 --- a/.github/workflows/test-fixture-cache-publish.yaml +++ b/.github/workflows/test-fixture-cache-publish.yaml @@ -18,7 +18,7 @@ jobs: permissions: packages: write steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 - name: Bootstrap environment uses: ./.github/actions/bootstrap diff --git a/.github/workflows/update-bootstrap-tools.yml b/.github/workflows/update-bootstrap-tools.yml index 5ae63dd08..04bbeb261 100644 --- a/.github/workflows/update-bootstrap-tools.yml +++ b/.github/workflows/update-bootstrap-tools.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'anchore/syft' # only run for main repo steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 - name: Bootstrap environment uses: ./.github/actions/bootstrap diff --git a/.github/workflows/update-cpe-dictionary-index.yml b/.github/workflows/update-cpe-dictionary-index.yml index 2bc9ff5db..5f7de622c 100644 --- a/.github/workflows/update-cpe-dictionary-index.yml +++ b/.github/workflows/update-cpe-dictionary-index.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'anchore/syft' # only run for main repo steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 - name: Bootstrap environment uses: ./.github/actions/bootstrap diff --git a/.github/workflows/update-stereoscope-release.yml b/.github/workflows/update-stereoscope-release.yml index 2c136b23d..6ea3bb6fa 100644 --- a/.github/workflows/update-stereoscope-release.yml +++ b/.github/workflows/update-stereoscope-release.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'anchore/syft' # only run for main repo steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 #v5.0.2 with: diff --git a/.github/workflows/validations.yaml b/.github/workflows/validations.yaml index 0413e1637..c028492c7 100644 --- a/.github/workflows/validations.yaml +++ b/.github/workflows/validations.yaml @@ -17,7 +17,7 @@ jobs: name: "Static analysis" runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -31,7 +31,7 @@ jobs: name: "Unit tests" runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -47,7 +47,7 @@ jobs: name: "Integration tests" runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -65,7 +65,7 @@ jobs: name: "Build snapshot artifacts" runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -95,7 +95,7 @@ jobs: needs: [Build-Snapshot-Artifacts] runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -141,7 +141,7 @@ jobs: - name: Install Cosign uses: sigstore/cosign-installer@v3.6.0 - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -178,7 +178,7 @@ jobs: needs: [Build-Snapshot-Artifacts] runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -215,7 +215,7 @@ jobs: - Acceptance-Mac - Cli-Linux steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 - name: Delete snapshot cache run: gh cache delete "snapshot-build-${{ github.run_id }}" From 16122eb32d9b05e2b3b4a93d10cd39b7b45504c2 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Thu, 26 Sep 2024 13:48:33 -0400 Subject: [PATCH 225/284] chore(deps): update stereoscope to dc10ea61fd18efa45b516eda4de8bc19d8322429 (#3280) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: kzantow <3009477+kzantow@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8cd36e216..6c0aef02a 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f - github.com/anchore/stereoscope v0.0.3 + github.com/anchore/stereoscope v0.0.4-0.20240925150116-dc10ea61fd18 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // we are hinting brotli to latest due to warning when installing archiver v3: // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption diff --git a/go.sum b/go.sum index 16e38c986..767fa2170 100644 --- a/go.sum +++ b/go.sum @@ -115,8 +115,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f h1:B/E9ixKNCasntpoch61NDaQyGPDXLEJlL+B9B/PbdbA= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.3 h1:JRPHySy8S6P+Ff3IDiQ29ap1i8/laUQxDk9K1eFh/2U= -github.com/anchore/stereoscope v0.0.3/go.mod h1:5DJheGPjVRsSqegTB24Zi6SCHnYQnA519yeIG+RG+I4= +github.com/anchore/stereoscope v0.0.4-0.20240925150116-dc10ea61fd18 h1:JfE3paLL87dDBHHHdTfnkpyPR72ua8jUbIDs3U/KEBs= +github.com/anchore/stereoscope v0.0.4-0.20240925150116-dc10ea61fd18/go.mod h1:5DJheGPjVRsSqegTB24Zi6SCHnYQnA519yeIG+RG+I4= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= From f9ef9cf1dc4fd09f04a5dfd8ef5db4ab389ef07b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Sep 2024 13:48:45 -0400 Subject: [PATCH 226/284] chore(deps): bump github/codeql-action from 3.26.8 to 3.26.9 (#3275) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.8 to 3.26.9. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/294a9d92911152fe08befb9ec03e240add280cb3...461ef6c76dfe95d5c364de2f431ddbd31a417628) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 51c80c4fd..222d2e970 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@294a9d92911152fe08befb9ec03e240add280cb3 #v3.26.8 + uses: github/codeql-action/init@461ef6c76dfe95d5c364de2f431ddbd31a417628 #v3.26.9 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@294a9d92911152fe08befb9ec03e240add280cb3 #v3.26.8 + uses: github/codeql-action/autobuild@461ef6c76dfe95d5c364de2f431ddbd31a417628 #v3.26.9 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@294a9d92911152fe08befb9ec03e240add280cb3 #v3.26.8 + uses: github/codeql-action/analyze@461ef6c76dfe95d5c364de2f431ddbd31a417628 #v3.26.9 From 5393cd5dec2afaa24a14334e19b662f86520b71c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Sep 2024 13:49:02 -0400 Subject: [PATCH 227/284] chore(deps): bump github.com/docker/docker (#3264) Bumps [github.com/docker/docker](https://github.com/docker/docker) from 27.3.0+incompatible to 27.3.1+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.3.0...v27.3.1) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6c0aef02a..6d2257889 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/dave/jennifer v1.7.1 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da github.com/distribution/reference v0.6.0 - github.com/docker/docker v27.3.0+incompatible + github.com/docker/docker v27.3.1+incompatible github.com/dustin/go-humanize v1.0.1 github.com/elliotchance/phpserialize v1.4.0 github.com/facebookincubator/nvdtools v0.1.5 diff --git a/go.sum b/go.sum index 767fa2170..0ad9797b7 100644 --- a/go.sum +++ b/go.sum @@ -229,8 +229,8 @@ github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2 github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.3.0+incompatible h1:BNb1QY6o4JdKpqwi9IB+HUYcRRrVN4aGFUTvDmWYK1A= -github.com/docker/docker v27.3.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= +github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= From e37c4686c2fb46f00a9edb86cfc8977598f50c41 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Thu, 26 Sep 2024 13:49:18 -0400 Subject: [PATCH 228/284] chore(deps): update CPE dictionary index (#3262) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: wagoodman <590471+wagoodman@users.noreply.github.com> --- .../cpegenerate/dictionary/data/cpe-index.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index 90f50b878..d2e69dbd2 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -2047,6 +2047,9 @@ "@antfu/utils": [ "cpe:2.3:a:antfu:utils:*:*:*:*:*:node.js:*:*" ], + "@apollo/gateway": [ + "cpe:2.3:a:apollographql:apollo_gateway:*:*:*:*:*:node.js:*:*" + ], "@apollosproject/data-connector-rock": [ "cpe:2.3:a:apollosapp:data-connector-rock:*:*:*:*:*:node.js:*:*" ], @@ -6206,6 +6209,9 @@ "omniauth-oauth2": [ "cpe:2.3:a:omniauth-oauth2_project:omniauth-oauth2:*:*:*:*:*:ruby:*:*" ], + "omniauth-saml": [ + "cpe:2.3:a:omniauth:omniauth_saml:*:*:*:*:*:ruby:*:*" + ], "open-uri-cached": [ "cpe:2.3:a:open-uri-cached_project:open-uri-cached:*:*:*:*:*:ruby:*:*" ], @@ -15468,6 +15474,9 @@ "sprout-invoices": [ "cpe:2.3:a:webventures:client_invoicing_by_sprout_invoices:*:*:*:*:*:wordpress:*:*" ], + "squeeze": [ + "cpe:2.3:a:squeeze_project:squeeze:*:*:*:*:*:wordpress:*:*" + ], "squirrly-seo": [ "cpe:2.3:a:squirrly:seo_plugin_by_squirrly_seo:*:*:*:*:*:wordpress:*:*" ], @@ -17727,6 +17736,9 @@ "wp-invoice": [ "cpe:2.3:a:usabilitydynamics:wp-invoice:*:*:*:*:*:wordpress:*:*" ], + "wp-jitsi-shortcodes": [ + "cpe:2.3:a:andrewabarber:wordpress_jitsi_shortcode:*:*:*:*:*:wordpress:*:*" + ], "wp-job-openings": [ "cpe:2.3:a:awsm:wp_job_openings:*:*:*:*:*:wordpress:*:*" ], From 1a746b2c0542ac4fab65c76b54dfcbcdc83de59d Mon Sep 17 00:00:00 2001 From: witchcraze <67056980+witchcraze@users.noreply.github.com> Date: Fri, 27 Sep 2024 21:51:50 +0900 Subject: [PATCH 229/284] fix: update ruby classifier for -rc, -dev, etc. versions (#3285) Signed-off-by: witchcraze --- .../binary/classifier_cataloger_test.go | 54 +++++++++++++++++++ syft/pkg/cataloger/binary/classifiers.go | 5 +- .../binary/test-fixtures/config.yaml | 30 +++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) diff --git a/syft/pkg/cataloger/binary/classifier_cataloger_test.go b/syft/pkg/cataloger/binary/classifier_cataloger_test.go index 48744a612..b9c28a51f 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger_test.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger_test.go @@ -850,6 +850,60 @@ func Test_Cataloger_PositiveCases(t *testing.T) { }, }, }, + { + // note: dynamic (non-snippet) test case + name: "positive-ruby-3.4.0-dev", + logicalFixture: "ruby-shared-libs/3.4.0-dev/linux-amd64", + expected: pkg.Package{ + Name: "ruby", + Version: "3.4.0dev", + Type: "binary", + PURL: "pkg:generic/ruby@3.4.0dev", + Locations: locations("ruby", "libruby.so.3.4.0"), + Metadata: pkg.BinarySignature{ + Matches: []pkg.ClassifierMatch{ + match("ruby-binary", "ruby"), + match("ruby-binary", "libruby.so.3.4.0"), + }, + }, + }, + }, + { + // note: dynamic (non-snippet) test case + name: "positive-ruby-3.4.0-preview1", + logicalFixture: "ruby-shared-libs/3.4.0-preview1/linux-amd64", + expected: pkg.Package{ + Name: "ruby", + Version: "3.4.0preview1", + Type: "binary", + PURL: "pkg:generic/ruby@3.4.0preview1", + Locations: locations("ruby", "libruby.so.3.4.0"), + Metadata: pkg.BinarySignature{ + Matches: []pkg.ClassifierMatch{ + match("ruby-binary", "ruby"), + match("ruby-binary", "libruby.so.3.4.0"), + }, + }, + }, + }, + { + // note: dynamic (non-snippet) test case + name: "positive-ruby-3.3.0-rc1", + logicalFixture: "ruby-shared-libs/3.3.0-rc1/linux-amd64", + expected: pkg.Package{ + Name: "ruby", + Version: "3.3.0rc1", + Type: "binary", + PURL: "pkg:generic/ruby@3.3.0rc1", + Locations: locations("ruby", "libruby.so.3.3.0"), + Metadata: pkg.BinarySignature{ + Matches: []pkg.ClassifierMatch{ + match("ruby-binary", "ruby"), + match("ruby-binary", "libruby.so.3.3.0"), + }, + }, + }, + }, { // note: dynamic (non-snippet) test case logicalFixture: "ruby-bullseye-shared-libs/2.7.7/linux-amd64", diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index 52dc1549a..f12998069 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -666,6 +666,9 @@ var libpythonMatcher = fileNameTemplateVersionMatcher( ) var rubyMatcher = FileContentsVersionMatcher( + // ruby 3.4.0dev (2024-09-15T01:06:11Z master 532af89e3b) [x86_64-linux] + // ruby 3.4.0preview1 (2024-05-16 master 9d69619623) [x86_64-linux] + // ruby 3.3.0rc1 (2023-12-11 master a49643340e) [x86_64-linux] // ruby 3.2.1 (2023-02-08 revision 31819e82c8) [x86_64-linux] // ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5) [x86_64-linux] - `(?m)ruby (?P[0-9]+\.[0-9]+\.[0-9]+(p[0-9]+)?) `) + `(?m)ruby (?P[0-9]+\.[0-9]+\.[0-9]+((p|preview|rc|dev)[0-9]*)?) `) diff --git a/syft/pkg/cataloger/binary/test-fixtures/config.yaml b/syft/pkg/cataloger/binary/test-fixtures/config.yaml index f32705f2a..36c1c0425 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/config.yaml +++ b/syft/pkg/cataloger/binary/test-fixtures/config.yaml @@ -563,6 +563,36 @@ from-images: - /usr/local/lib/libruby.so.2.7.7 - /usr/local/lib/libruby.so.2.7 + - name: ruby-shared-libs + version: 3.4.0-dev + images: + - ref: rubylang/ruby:master-dev-nightly-20240804-focal@sha256:b5fe8b9ac1e9638a4b08bda6a6343082a07623d1c01926e637eb4bbbbf159409 + platform: linux/amd64 + paths: + - /usr/local/bin/ruby + - /usr/local/lib/libruby.so.3.4.0 + - /usr/local/lib/libruby.so.3.4 + + - name: ruby-shared-libs + version: 3.4.0-preview1 + images: + - ref: ruby:3.4.0-preview1@sha256:88cad31539e1a4ab987ac4b00c45b86d8346c25e3b08ac647ccccfb21cee5890 + platform: linux/amd64 + paths: + - /usr/local/bin/ruby + - /usr/local/lib/libruby.so.3.4.0 + - /usr/local/lib/libruby.so.3.4 + + - name: ruby-shared-libs + version: 3.3.0-rc1 + images: + - ref: ruby:3.3.0-rc1@sha256:453c8bbb9b4e3b04b94ba58db77b648222f3c92936dc12b5ae96df48076c106b + platform: linux/amd64 + paths: + - /usr/local/bin/ruby + - /usr/local/lib/libruby.so.3.3.0 + - /usr/local/lib/libruby.so.3.3 + - name: ruby-shared-libs version: 2.6.10 images: From 2a3d171c1014ce09dc28c87c52e8b10815b5b96f Mon Sep 17 00:00:00 2001 From: witchcraze <67056980+witchcraze@users.noreply.github.com> Date: Fri, 27 Sep 2024 21:53:35 +0900 Subject: [PATCH 230/284] fix: improve node classifier version matching (#3284) Signed-off-by: witchcraze --- .../binary/classifier_cataloger_test.go | 30 ++++++++++++++++++ syft/pkg/cataloger/binary/classifiers.go | 10 ++++-- .../snippets/node/0.10.48/linux-amd64/node | Bin 0 -> 348 bytes .../snippets/node/0.12.18/linux-amd64/node | Bin 0 -> 349 bytes .../snippets/node/4.9.1/linux-amd64/node | Bin 0 -> 349 bytes .../binary/test-fixtures/config.yaml | 21 ++++++++++++ 6 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/node/0.10.48/linux-amd64/node create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/node/0.12.18/linux-amd64/node create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/node/4.9.1/linux-amd64/node diff --git a/syft/pkg/cataloger/binary/classifier_cataloger_test.go b/syft/pkg/cataloger/binary/classifier_cataloger_test.go index b9c28a51f..fab2acce7 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger_test.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger_test.go @@ -625,6 +625,36 @@ func Test_Cataloger_PositiveCases(t *testing.T) { Metadata: metadata("go-binary"), }, }, + { + logicalFixture: "node/0.10.48/linux-amd64", + expected: pkg.Package{ + Name: "node", + Version: "0.10.48", + PURL: "pkg:generic/node@0.10.48", + Locations: locations("node"), + Metadata: metadata("nodejs-binary"), + }, + }, + { + logicalFixture: "node/0.12.18/linux-amd64", + expected: pkg.Package{ + Name: "node", + Version: "0.12.18", + PURL: "pkg:generic/node@0.12.18", + Locations: locations("node"), + Metadata: metadata("nodejs-binary"), + }, + }, + { + logicalFixture: "node/4.9.1/linux-amd64", + expected: pkg.Package{ + Name: "node", + Version: "4.9.1", + PURL: "pkg:generic/node@4.9.1", + Locations: locations("node"), + Metadata: metadata("nodejs-binary"), + }, + }, { logicalFixture: "node/19.2.0/linux-amd64", expected: pkg.Package{ diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index f12998069..fa4fcd870 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -153,8 +153,14 @@ func DefaultClassifiers() []Classifier { { Class: "nodejs-binary", FileGlob: "**/node", - EvidenceMatcher: FileContentsVersionMatcher( - `(?m)node\.js\/v(?P[0-9]+\.[0-9]+\.[0-9]+)`), + EvidenceMatcher: evidenceMatchers( + // [NUL]node v0.10.48[NUL] + // [NUL]v0.12.18[NUL] + // [NUL]v4.9.1[NUL] + // node.js/v22.9.0 + FileContentsVersionMatcher(`(?m)\x00(node )?v(?P(0|4|5)\.[0-9]+\.[0-9]+)\x00`), + FileContentsVersionMatcher(`(?m)node\.js\/v(?P[0-9]+\.[0-9]+\.[0-9]+)`), + ), Package: "node", PURL: mustPURL("pkg:generic/node@version"), CPEs: singleCPE("cpe:2.3:a:nodejs:node.js:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/node/0.10.48/linux-amd64/node b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/node/0.10.48/linux-amd64/node new file mode 100644 index 0000000000000000000000000000000000000000..c26292bbae83fb8a66a0e9b7e22b777d5f3f5c3d GIT binary patch literal 348 zcmZ9H!D<6B3`F-eO7N1hIp@c5BSZs7DAR`lXIwbS~B}?ax zh}Tq-HB_V}>q0iDwNi`40{FWM{Jsfwf-()m^aZz-y0=@U)XX*3%M9x^U~^}1#g)bt rbWAh5n+wI%7ho|`_^`EI`xy-_s-D58KeEjRzk8n3vInRe5-+g1j literal 0 HcmV?d00001 diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/node/0.12.18/linux-amd64/node b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/node/0.12.18/linux-amd64/node new file mode 100644 index 0000000000000000000000000000000000000000..24e280dcb88452873aee068066b35e5b42a66103 GIT binary patch literal 349 zcmY+8yKciU3`ITbD+B}?9q4V@K)<4E7t*3)ql)ZWN{aq{m7*QWg*fLD7tC;@iRUd4 z+hQzKCoYw6+IY(nSM0T(DZ1(V``-5N8|$`lfu4G!CFO z8ZyyoYexw-q6Ot0jfPlU6aAHeP%e(*Su-dj+DLFZfb}4}69$4*&Jcz<8Zmf895G5C z0*ye%&WxQ-Cyrm0`0ty%Zai)&ZJ)eF?ER(d`#^ZV_WO3!Mvv|xE>c~jZwY0RfkK0%?t;UHKGzma%mS$)81_dK%zR)_?TMMA)$C|f|>g&yev1btyxoB;Iq#gKZfdYB$1_z1Ij@S>z zDbzRwJw)vc48a65ShBq#ikhdq&_7H?6^sHGl~bcpXc|N|ppFz#CmRt5FfwSVRS$sP zJE@Y@O3HRv!};lS65*?o_?sze5veRo`4p|<>nxDMW1eXjex|i{oPFqS>?FGvd@OV= z9{jbGZGJy!XR?D%O7^|v(7fzB`Sg5wV}7TD8QXqyeEe!cU;Tu6XVbQqdp_ue J-YM40#}C3pXbS)U literal 0 HcmV?d00001 diff --git a/syft/pkg/cataloger/binary/test-fixtures/config.yaml b/syft/pkg/cataloger/binary/test-fixtures/config.yaml index 36c1c0425..61db2433d 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/config.yaml +++ b/syft/pkg/cataloger/binary/test-fixtures/config.yaml @@ -256,6 +256,27 @@ from-images: paths: - /usr/local/openresty/nginx/sbin/nginx + - version: 0.10.48 + images: + - ref: node:0.10.48@sha256:c32b4d56f05c69df6e87d06bf7d5f6a5c6a0e7bcdb8e5ffab0e7a1853a90008f + platform: linux/amd64 + paths: + - /usr/local/bin/node + + - version: 0.12.18 + images: + - ref: node:0.12.18@sha256:02e8e9903c8d974e8874d0144413d398a41d62f54bafec4d2cf3ac2a8501dd28 + platform: linux/amd64 + paths: + - /usr/local/bin/node + + - version: 4.9.1 + images: + - ref: node:4.9.1@sha256:41d0ad2557ea2a9e57e1a458c1d659e92f601586e07dcffef74c9cef542f6f6e + platform: linux/amd64 + paths: + - /usr/local/bin/node + - version: 19.2.0 images: - ref: node:19.2.0@sha256:9bf5846b28f63acab0ccb0a39a245fbc414e6b7ecd467282f58016537c06e159 From f5f8005fe087f74ceeb3aa1858f2ff40569632db Mon Sep 17 00:00:00 2001 From: witchcraze <67056980+witchcraze@users.noreply.github.com> Date: Tue, 1 Oct 2024 04:37:47 +0900 Subject: [PATCH 231/284] update redis classifier (#3281) * update redis classifier Signed-off-by: witchcraze * Remove snippets to pass Validation. In this case, 9000 byte was required... Signed-off-by: witchcraze --- .../pkg/cataloger/binary/classifier_cataloger_test.go | 11 +++++++++++ syft/pkg/cataloger/binary/classifiers.go | 2 +- syft/pkg/cataloger/binary/test-fixtures/config.yaml | 7 +++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/syft/pkg/cataloger/binary/classifier_cataloger_test.go b/syft/pkg/cataloger/binary/classifier_cataloger_test.go index fab2acce7..4c84efb94 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger_test.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger_test.go @@ -485,6 +485,17 @@ func Test_Cataloger_PositiveCases(t *testing.T) { Metadata: metadata("redis-binary"), }, }, + { + logicalFixture: "redis-server/7.2.5/linux-386", + expected: pkg.Package{ + Name: "redis", + Version: "7.2.5", + Type: "binary", + PURL: "pkg:generic/redis@7.2.5", + Locations: locations("redis-server"), + Metadata: metadata("redis-binary"), + }, + }, { logicalFixture: "python-shared-lib/3.7.4/linux-amd64", expected: pkg.Package{ diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index fa4fcd870..c3e730c98 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -78,7 +78,7 @@ func DefaultClassifiers() []Classifier { FileGlob: "**/redis-server", EvidenceMatcher: evidenceMatchers( FileContentsVersionMatcher(`(?s)payload %5.*?(?P\d.\d\.\d\d*)[a-z0-9]{12,15}-[0-9]{19}`), - FileContentsVersionMatcher(`(?s)\x00(?P\d.\d\.\d\d*)[a-z0-9]{12}-[0-9]{19}\x00.*?payload %5`), + FileContentsVersionMatcher(`(?s)\x00(?P\d.\d\.\d\d*)[a-z0-9]{12,15}-[0-9]{19}\x00.*?payload %5`), ), Package: "redis", PURL: mustPURL("pkg:generic/redis@version"), diff --git a/syft/pkg/cataloger/binary/test-fixtures/config.yaml b/syft/pkg/cataloger/binary/test-fixtures/config.yaml index 61db2433d..2476da49c 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/config.yaml +++ b/syft/pkg/cataloger/binary/test-fixtures/config.yaml @@ -461,6 +461,13 @@ from-images: paths: - /usr/local/bin/redis-server + - version: 7.2.5 + images: + - ref: redis:7.2.5@sha256:3b44455ef048b5f0a3a26d874c00c0f4ffe6a71a40834f2b038f816c6ad5ca4f + platform: linux/386 + paths: + - /usr/local/bin/redis-server + - version: 2.9.0 images: - ref: wordpress:cli-2.9.0-php8.3@sha256:3a008aafccc6a8d2d7ec2b069722cb43b3569b61cd833f9f2f13d74a9284746e From 9b242b03095c9de22382083944d73019923a127a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:48:46 -0400 Subject: [PATCH 232/284] chore(deps): bump github/codeql-action from 3.26.9 to 3.26.10 (#3289) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.9 to 3.26.10. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/461ef6c76dfe95d5c364de2f431ddbd31a417628...e2b3eafc8d227b0241d48be5f425d47c2d750a13) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 222d2e970..be784870c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@461ef6c76dfe95d5c364de2f431ddbd31a417628 #v3.26.9 + uses: github/codeql-action/init@e2b3eafc8d227b0241d48be5f425d47c2d750a13 #v3.26.10 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@461ef6c76dfe95d5c364de2f431ddbd31a417628 #v3.26.9 + uses: github/codeql-action/autobuild@e2b3eafc8d227b0241d48be5f425d47c2d750a13 #v3.26.10 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@461ef6c76dfe95d5c364de2f431ddbd31a417628 #v3.26.9 + uses: github/codeql-action/analyze@e2b3eafc8d227b0241d48be5f425d47c2d750a13 #v3.26.10 From 93beceb4a24a8bbcb153efc7d58729a377871583 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:50:15 -0400 Subject: [PATCH 233/284] chore(deps): update CPE dictionary index (#3288) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: wagoodman <590471+wagoodman@users.noreply.github.com> --- .../dictionary/data/cpe-index.json | 90 ++++++++++++++++++- 1 file changed, 86 insertions(+), 4 deletions(-) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index d2e69dbd2..a775fdfb0 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -25,6 +25,9 @@ "github.com/charmbracelet/soft-serve": [ "cpe:2.3:a:charm:soft_serve:*:*:*:*:*:go:*:*" ], + "github.com/containers/podman": [ + "cpe:2.3:a:podman_project:podman:*:*:*:*:*:*:*:*" + ], "github.com/containers/psgo": [ "cpe:2.3:a:psgo_project:psgo:*:*:*:*:*:go:*:*" ], @@ -2031,6 +2034,9 @@ "626": [ "cpe:2.3:a:626_project:626:*:*:*:*:*:node.js:*:*" ], + "@actions/artifact": [ + "cpe:2.3:a:github:actions\\/artifact:*:*:*:*:*:node.js:*:*" + ], "@actions/core": [ "cpe:2.3:a:github:toolkit:*:*:*:*:*:node.js:*:*", "cpe:2.3:a:toolkit_project:toolkit:*:*:*:*:*:node.js:*:*" @@ -2438,6 +2444,9 @@ "bmoor": [ "cpe:2.3:a:bmoor_project:bmoor:*:*:*:*:*:node.js:*:*" ], + "body-parser": [ + "cpe:2.3:a:openjsf:body-parser:*:*:*:*:*:node.js:*:*" + ], "bodymen": [ "cpe:2.3:a:bodymen_project:bodymen:*:*:*:*:*:node.js:*:*" ], @@ -7623,7 +7632,7 @@ "cpe:2.3:a:tarassych:anonymous_restricted_content:*:*:*:*:*:wordpress:*:*" ], "another-wordpress-classifieds-plugin": [ - "cpe:2.3:a:awpcp:another_wordpress_classifieds_plugin:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:strategy11:awp_classifieds:*:*:*:*:*:wordpress:*:*" ], "anspress-question-answer": [ "cpe:2.3:a:rahularyan:anspress:*:*:*:*:*:wordpress:*:*" @@ -8696,7 +8705,8 @@ "cpe:2.3:a:wpgrim:classic_editor_and_classic_widgets:*:*:*:*:*:wordpress:*:*" ], "classified-listing": [ - "cpe:2.3:a:radiustheme:classified_listing_-_classified_ads_\\\u0026_business_directory:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:radiustheme:classified_listing:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:radiustheme:classified_listing:*:*:*:*:-:wordpress:*:*" ], "classyfrieds": [ "cpe:2.3:a:classyfrieds_project:classyfrieds:*:*:*:*:*:wordpress:*:*" @@ -9426,6 +9436,9 @@ "custom-post-view-generator": [ "cpe:2.3:a:custom_post_view_generator_project:custom_post_view_generator:*:*:*:*:*:wordpress:*:*" ], + "custom-post-widget": [ + "cpe:2.3:a:vanderwijk:content_blocks:*:*:*:*:*:wordpress:*:*" + ], "custom-registration-form-builder-with-submission-manager": [ "cpe:2.3:a:metagauss:registrationmagic:*:*:*:*:*:wordpress:*:*" ], @@ -10790,6 +10803,9 @@ "front-end-pm": [ "cpe:2.3:a:shamimsplugins:front_end_pm:*:*:*:*:*:wordpress:*:*" ], + "frontend-dashboard": [ + "cpe:2.3:a:buffercode:frontend_dashboard:*:*:*:*:*:wordpress:*:*" + ], "frontend-uploader": [ "cpe:2.3:a:frontend_uploader_project:frontend_uploader:*:*:*:*:*:wordpress:*:*" ], @@ -10948,7 +10964,7 @@ "cpe:2.3:a:genki_pre-publish_reminder_project:genki_pre-publish_reminder:*:*:*:*:*:wordpress:*:*" ], "geo-mashup": [ - "cpe:2.3:a:geo_mashup_project:geo_mashup:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:cyberhobo:geo_mashup:*:*:*:*:*:wordpress:*:*" ], "geo-my-wp": [ "cpe:2.3:a:geomywp:geo_my_wordpress:*:*:*:*:*:wordpress:*:*" @@ -12527,6 +12543,9 @@ "media-list": [ "cpe:2.3:a:drelton:medialist:*:*:*:*:*:wordpress:*:*" ], + "media-slider": [ + "cpe:2.3:a:awplife:media_slider:*:*:*:*:*:wordpress:*:*" + ], "media-usage": [ "cpe:2.3:a:meowapps:media_usage:*:*:*:*:*:wordpress:*:*" ], @@ -13111,6 +13130,9 @@ "notificationx": [ "cpe:2.3:a:wpdeveloper:notificationx:*:*:*:*:*:wordpress:*:*" ], + "nova-blocks": [ + "cpe:2.3:a:pixelgrade:nova_blocks:*:*:*:*:*:wordpress:*:*" + ], "novelist": [ "cpe:2.3:a:nosegraze:novelist:*:*:*:*:*:wordpress:*:*" ], @@ -13579,6 +13601,9 @@ "pie-register": [ "cpe:2.3:a:genetechsolutions:pie_register:*:*:*:*:*:wordpress:*:*" ], + "pilotpress": [ + "cpe:2.3:a:ontraport:pilotpress:*:*:*:*:*:wordpress:*:*" + ], "pinterest-rss-widget": [ "cpe:2.3:a:bkmacdaddy:pinterest_rss_widget:*:*:*:*:*:wordpress:*:*" ], @@ -14139,6 +14164,9 @@ "qyrr-code": [ "cpe:2.3:a:patrickposner:qyrr:*:*:*:*:*:wordpress:*:*" ], + "rabbit-loader": [ + "cpe:2.3:a:yoginetwork:rabbitloader:*:*:*:*:*:wordpress:*:*" + ], "radio-buttons-for-taxonomies": [ "cpe:2.3:a:radio_buttons_for_taxonomies_project:radio_buttons_for_taxonomies:*:*:*:*:*:wordpress:*:*" ], @@ -14431,6 +14459,9 @@ "reviewx": [ "cpe:2.3:a:wpdeveloper:reviewx:*:*:*:*:*:wordpress:*:*" ], + "revision-manager-tmc": [ + "cpe:2.3:a:jetplugs:revision_manager_tmc:*:*:*:*:*:wordpress:*:*" + ], "rezgo": [ "cpe:2.3:a:rezgo:rezgo_online_booking:*:*:*:*:*:wordpress:*:*" ], @@ -15180,6 +15211,9 @@ "sketchfab-oembed": [ "cpe:2.3:a:generatewp:sketchfab_embed:*:*:*:*:*:wordpress:*:*" ], + "skt-templates": [ + "cpe:2.3:a:sktthemes:skt_templates:*:*:*:*:*:wordpress:*:*" + ], "skype-online-status": [ "cpe:2.3:a:ravanh:skype_legacy_buttons:*:*:*:*:*:wordpress:*:*" ], @@ -15665,6 +15699,9 @@ "surbma-gdpr-proof-google-analytics": [ "cpe:2.3:a:surbma:gdpr_proof_cookie_consent_\\\u0026_notice_bar:*:*:*:*:*:wordpress:*:*" ], + "surecart": [ + "cpe:2.3:a:surecart:surecart:*:*:*:*:*:wordpress:*:*" + ], "suretriggers": [ "cpe:2.3:a:suretriggers:suretriggers:*:*:*:*:*:wordpress:*:*" ], @@ -16075,6 +16112,9 @@ "tutor": [ "cpe:2.3:a:themeum:tutor_lms:*:*:*:*:*:wordpress:*:*" ], + "tutor-lms-migration-tool": [ + "cpe:2.3:a:themeum:tutor_lms_-_migration_tool:*:*:*:*:*:wordpress:*:*" + ], "tuxedo-big-file-uploads": [ "cpe:2.3:a:infiniteuploads:big_file_uploads:*:*:*:*:*:wordpress:*:*" ], @@ -16685,6 +16725,9 @@ "weblizar-pinterest-feeds": [ "cpe:2.3:a:weblizar:pinterest-feeds:*:*:*:*:*:wordpress:*:*" ], + "webo-facto-connector": [ + "cpe:2.3:a:medialibs:webo-facto:*:*:*:*:*:wordpress:*:*" + ], "webp-converter-for-media": [ "cpe:2.3:a:webp_converter_for_media_project:webp_converter_for_media:*:*:*:*:*:wordpress:*:*" ], @@ -17178,6 +17221,9 @@ "wp-academic-people": [ "cpe:2.3:a:wp_academic_people_list_project:wp_academic_people_list:*:*:*:*:*:wordpress:*:*" ], + "wp-accessibility-helper": [ + "cpe:2.3:a:volkov:wp_accessibility_helper:*:*:*:*:*:wordpress:*:*" + ], "wp-admin-logo-changer": [ "cpe:2.3:a:wp_admin_logo_changer_project:wp_admin_logo_changer:*:*:*:*:*:wordpress:*:*" ], @@ -17408,7 +17454,7 @@ "cpe:2.3:a:hamidrezasepehr:wp_custom_cursors_\\|_wordpress_cursor_plugin:*:*:*:*:*:wordpress:*:*" ], "wp-custom-fields-search": [ - "cpe:2.3:a:warhammer:wp_custom_fields_search:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:webhammer:wp_custom_fields_search:*:*:*:*:*:wordpress:*:*" ], "wp-custom-login-page": [ "cpe:2.3:a:custom_login_page_project:custom_login_page:*:*:*:*:*:wordpress:*:*" @@ -18657,6 +18703,9 @@ "xqueue-maileon": [ "cpe:2.3:a:maileon:maileon:*:*:*:*:*:wordpress:*:*" ], + "xt-woo-ajax-add-to-cart": [ + "cpe:2.3:a:xplodedthemes:xt_ajax_add_to_cart_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], "xtremelocator": [ "cpe:2.3:a:xtremelocator:xtremelocator:*:*:*:*:*:wordpress:*:*" ], @@ -18896,6 +18945,9 @@ "author": [ "cpe:2.3:a:sinatrateam:sinatra:*:*:*:*:*:wordpress:*:*" ], + "beauty": [ + "cpe:2.3:a:allprices:beauty:*:*:*:*:*:wordpress:*:*" + ], "big-store": [ "cpe:2.3:a:themehunk:big_store:*:*:*:*:*:wordpress:*:*" ], @@ -18970,6 +19022,9 @@ "flashy": [ "cpe:2.3:a:flashy_project:flashy:*:*:*:*:*:wordpress:*:*" ], + "fluida": [ + "cpe:2.3:a:cryoutcreations:fluida:*:*:*:*:*:wordpress:*:*" + ], "fullbase": [ "cpe:2.3:a:marchettidesign:fullbase:*:*:*:*:*:wordpress:*:*" ], @@ -18986,6 +19041,9 @@ "grey-opaque": [ "cpe:2.3:a:grey_opaque_project:grey_opaque:*:*:*:*:*:wordpress:*:*" ], + "hotel-galaxy": [ + "cpe:2.3:a:webdzier:hotel_galaxy:*:*:*:*:*:wordpress:*:*" + ], "hueman": [ "cpe:2.3:a:presscustomizr:hueman:*:*:*:*:*:wordpress:*:*" ], @@ -18995,11 +19053,17 @@ "interface": [ "cpe:2.3:a:themehorse:interface:*:*:*:*:*:wordpress:*:*" ], + "kahuna": [ + "cpe:2.3:a:cryoutcreations:kahuna:*:*:*:*:*:wordpress:*:*" + ], "kata": [ "cpe:2.3:a:climaxthemes:kata:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:climaxthemes:kata_apps:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:climaxthemes:kata_business:*:*:*:*:*:wordpress:*:*" ], + "mantra": [ + "cpe:2.3:a:cryoutcreations:mantra:*:*:*:*:*:wordpress:*:*" + ], "materialis": [ "cpe:2.3:a:extendthemes:materialis:*:*:*:*:*:wordpress:*:*" ], @@ -19018,6 +19082,9 @@ "mosaic": [ "cpe:2.3:a:wildweblab:mosaic:*:*:*:*:*:wordpress:*:*" ], + "mystique": [ + "cpe:2.3:a:digitalnature:mystique:*:*:*:*:*:wordpress:*:*" + ], "newsmag": [ "cpe:2.3:a:machothemes:newsmag:*:*:*:*:*:wordpress:*:*" ], @@ -19030,12 +19097,18 @@ "nexter": [ "cpe:2.3:a:posimyth:nexter:*:*:*:*:*:wordpress:*:*" ], + "nirvana": [ + "cpe:2.3:a:cryoutcreations:nirvana:*:*:*:*:*:wordpress:*:*" + ], "nova-lite": [ "cpe:2.3:a:themeinprogress:nova_lite:*:*:*:*:*:wordpress:*:*" ], "nsc": [ "cpe:2.3:a:saleswizard:nsc:*:*:*:*:*:wordpress:*:*" ], + "parabola": [ + "cpe:2.3:a:cryoutcreations:parabola:*:*:*:*:*:wordpress:*:*" + ], "pinzolo": [ "cpe:2.3:a:thriveweb:pinzolo:*:*:*:*:*:wordpress:*:*" ], @@ -19051,9 +19124,15 @@ "rife-free": [ "cpe:2.3:a:apollo13themes:rife_free:*:*:*:*:*:wordpress:*:*" ], + "roseta": [ + "cpe:2.3:a:cryoutcreations:roseta:*:*:*:*:*:wordpress:*:*" + ], "royal-elementor-kit": [ "cpe:2.3:a:royal-elementor-addons:royal_elementor_kit:*:*:*:*:*:wordpress:*:*" ], + "septera": [ + "cpe:2.3:a:cryoutcreations:septera:*:*:*:*:*:wordpress:*:*" + ], "shapely": [ "cpe:2.3:a:colorlib:shapely:*:*:*:*:*:wordpress:*:*" ], @@ -19072,6 +19151,9 @@ "upfrontwp": [ "cpe:2.3:a:wpazure:upfrontwp:*:*:*:*:*:wordpress:*:*" ], + "verbosa": [ + "cpe:2.3:a:cryoutcreations:verbosa:*:*:*:*:*:wordpress:*:*" + ], "viala": [ "cpe:2.3:a:davidgarlitz:viala:*:*:*:*:*:wordpress:*:*" ], From dbad17de9edb68f7b678daf1865ea6e9878cb4d7 Mon Sep 17 00:00:00 2001 From: Niv Govrin <138374496+govrin@users.noreply.github.com> Date: Tue, 1 Oct 2024 20:53:54 +0300 Subject: [PATCH 234/284] fix: don't use builtin scanner in licensecheck (#3290) Signed-off-by: Niv Govrin --- internal/licenses/parser.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/licenses/parser.go b/internal/licenses/parser.go index 58e4deb2d..c9f77d567 100644 --- a/internal/licenses/parser.go +++ b/internal/licenses/parser.go @@ -22,7 +22,13 @@ func Parse(reader io.Reader, l file.Location) (licenses []pkg.License, err error if err != nil { return nil, err } - cov := licensecheck.Scan(contents) + + scanner, err := licensecheck.NewScanner(licensecheck.BuiltinLicenses()) + if err != nil { + return nil, err + } + + cov := scanner.Scan(contents) if cov.Percent < coverageThreshold { // unknown or no licenses here? return licenses, nil From cc4f62b3d4e2d6bb742646df5ec71bd4a949d03f Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Wed, 2 Oct 2024 09:07:25 -0400 Subject: [PATCH 235/284] chore(deps): update tools to latest versions (#3291) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index 2857aa797..a70b574fb 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -111,7 +111,7 @@ tools: # used for triggering a release - name: gh version: - want: v2.57.0 + want: v2.58.0 method: github-release with: repo: cli/cli From 263ea6b1bb7a250fb7134de5722072d3ce5b1294 Mon Sep 17 00:00:00 2001 From: witchcraze <67056980+witchcraze@users.noreply.github.com> Date: Thu, 3 Oct 2024 04:10:39 +0900 Subject: [PATCH 236/284] feat: update haproxy classifier (#3277) Signed-off-by: witchcraze --- .../cataloger/binary/classifier_cataloger_test.go | 11 +++++++++++ syft/pkg/cataloger/binary/classifiers.go | 1 + .../snippets/haproxy/2.0.0/linux-amd64/haproxy | Bin 0 -> 351 bytes .../cataloger/binary/test-fixtures/config.yaml | 7 +++++++ 4 files changed, 19 insertions(+) create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/haproxy/2.0.0/linux-amd64/haproxy diff --git a/syft/pkg/cataloger/binary/classifier_cataloger_test.go b/syft/pkg/cataloger/binary/classifier_cataloger_test.go index 4c84efb94..1bba77b25 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger_test.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger_test.go @@ -348,6 +348,17 @@ func Test_Cataloger_PositiveCases(t *testing.T) { Metadata: metadata("haproxy-binary"), }, }, + { + logicalFixture: "haproxy/2.0.0/linux-amd64", + expected: pkg.Package{ + Name: "haproxy", + Version: "2.0.0", + Type: "binary", + PURL: "pkg:generic/haproxy@2.0.0", + Locations: locations("haproxy"), + Metadata: metadata("haproxy-binary"), + }, + }, { logicalFixture: "haproxy/2.7.3/linux-amd64", expected: pkg.Package{ diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index c3e730c98..eb936a93a 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -196,6 +196,7 @@ func DefaultClassifiers() []Classifier { Class: "haproxy-binary", FileGlob: "**/haproxy", EvidenceMatcher: evidenceMatchers( + FileContentsVersionMatcher(`(?m)version (?P[0-9]+\.[0-9]+(\.|-dev|-rc)[0-9]+)(-[a-z0-9]{7})?, released 20`), FileContentsVersionMatcher(`(?m)HA-Proxy version (?P[0-9]+\.[0-9]+(\.|-dev)[0-9]+)`), FileContentsVersionMatcher(`(?m)(?P[0-9]+\.[0-9]+(\.|-dev)[0-9]+)-[0-9a-zA-Z]{7}.+HAProxy version`), ), diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/haproxy/2.0.0/linux-amd64/haproxy b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/haproxy/2.0.0/linux-amd64/haproxy new file mode 100644 index 0000000000000000000000000000000000000000..12e68c56cf4b517ab6392f279ccd7d36a69b1c89 GIT binary patch literal 351 zcmYjL$!fze6wFy)@xYi|N+QYjljPs%vGgFzPl>^mjV0RTpS$mS>p}~i(+smP!JbeJ zTRTp}ZqEkqBc&RIR#+luJ%vr$&RTL7LpP3;4!2fTSc8(bp{h~Fdu1f~b{0aA5e_Sb z+#%@-D=!*Hg*RA~2HjzE`%v8*W_r)ZRs z=NFvP6uTjST=5k@fQfptky?;km^H_>z{P+1lUmHk<7nq%*uYU9>%2XN8kTun0_{d} NDS{2qg+v>g;2SmVak&5h literal 0 HcmV?d00001 diff --git a/syft/pkg/cataloger/binary/test-fixtures/config.yaml b/syft/pkg/cataloger/binary/test-fixtures/config.yaml index 2476da49c..22c9948c9 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/config.yaml +++ b/syft/pkg/cataloger/binary/test-fixtures/config.yaml @@ -130,6 +130,13 @@ from-images: paths: - /usr/local/sbin/haproxy + - version: 2.0.0 + images: + - ref: haproxy:2.0.0@sha256:f88bca67a2782e7bd88af168d5c11216c32104d12fe9240fac54a1d3196e3f9c + platform: linux/amd64 + paths: + - /usr/local/sbin/haproxy + - version: 2.7.3 images: - ref: haproxy:2.7.3@sha256:17d8aa6bf16882a294bdcccc757dd4002045f34b719e9f94dfd4801614801aea From 32c0d1e67329a5f1512074cc045652d90caa461a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Oct 2024 10:14:13 -0400 Subject: [PATCH 237/284] chore(deps): bump github.com/jedib0t/go-pretty/v6 from 6.5.9 to 6.6.0 (#3293) Bumps [github.com/jedib0t/go-pretty/v6](https://github.com/jedib0t/go-pretty) from 6.5.9 to 6.6.0. - [Release notes](https://github.com/jedib0t/go-pretty/releases) - [Commits](https://github.com/jedib0t/go-pretty/compare/v6.5.9...v6.6.0) --- updated-dependencies: - dependency-name: github.com/jedib0t/go-pretty/v6 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6d2257889..ece0947f9 100644 --- a/go.mod +++ b/go.mod @@ -46,7 +46,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 github.com/iancoleman/strcase v0.3.0 github.com/invopop/jsonschema v0.7.0 - github.com/jedib0t/go-pretty/v6 v6.5.9 + github.com/jedib0t/go-pretty/v6 v6.6.0 github.com/jinzhu/copier v0.4.0 github.com/kastenhq/goversion v0.0.0-20230811215019-93b2f8823953 github.com/knqyf263/go-rpmdb v0.1.1 diff --git a/go.sum b/go.sum index 0ad9797b7..a7223f4e1 100644 --- a/go.sum +++ b/go.sum @@ -477,8 +477,8 @@ github.com/invopop/jsonschema v0.7.0 h1:2vgQcBz1n256N+FpX3Jq7Y17AjYt46Ig3zIWyy77 github.com/invopop/jsonschema v0.7.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jedib0t/go-pretty/v6 v6.5.9 h1:ACteMBRrrmm1gMsXe9PSTOClQ63IXDUt03H5U+UV8OU= -github.com/jedib0t/go-pretty/v6 v6.5.9/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= +github.com/jedib0t/go-pretty/v6 v6.6.0 h1:wmZVuAcEkZRT+Aq1xXpE8IGat4vE5WXOMmBpbQqERXw= +github.com/jedib0t/go-pretty/v6 v6.6.0/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= From 770fdc53eafbed30829fb6b5a08f0e46748c47a4 Mon Sep 17 00:00:00 2001 From: William Murphy Date: Thu, 3 Oct 2024 16:42:57 -0400 Subject: [PATCH 238/284] Fix: make failed CPE validation correctly return error (#2762) * Test CPE attributes correctly returns error Previously, this method incorrectly return an empty Attributes object and a nil error, leading to callers attempting to use the empty attributes object. Signed-off-by: Will Murphy * chore: merge with main and refactor call that relied on old nil behavior Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> * test: add test to cover new OSCPE err pattern Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> --------- Signed-off-by: Will Murphy Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> Co-authored-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> --- syft/cpe/cpe.go | 2 +- syft/cpe/cpe_test.go | 12 ++++++++++-- syft/pkg/cataloger/binary/elf_package.go | 15 +++++++++------ syft/pkg/cataloger/binary/elf_package_test.go | 12 ++++++++++++ syft/pkg/collection_test.go | 2 +- 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/syft/cpe/cpe.go b/syft/cpe/cpe.go index fe678977d..c996d4ad9 100644 --- a/syft/cpe/cpe.go +++ b/syft/cpe/cpe.go @@ -95,7 +95,7 @@ func NewAttributes(cpeStr string) (Attributes, error) { } // ensure that this Attributes can be validated after being fully sanitized - if ValidateString(c.String()) != nil { + if err = ValidateString(c.String()); err != nil { return Attributes{}, err } diff --git a/syft/cpe/cpe_test.go b/syft/cpe/cpe_test.go index 4b3f60ae0..fd778c9a8 100644 --- a/syft/cpe/cpe_test.go +++ b/syft/cpe/cpe_test.go @@ -17,6 +17,7 @@ func Test_NewAttributes(t *testing.T) { name string input string expected Attributes + wantErr require.ErrorAssertionFunc }{ { name: "gocase", @@ -33,14 +34,21 @@ func Test_NewAttributes(t *testing.T) { input: `cpe:/a:%240.99_kindle_books_project:%240.99_kindle_books:6::~~~android~~`, expected: MustAttributes(`cpe:2.3:a:\$0.99_kindle_books_project:\$0.99_kindle_books:6:*:*:*:*:android:*:*`), }, + { + name: "null byte in version for some reason", + input: "cpe:2.3:a:oracle:openjdk:11.0.22+7\u0000-J-ms8m:*:*:*:*:*:*:*", + wantErr: require.Error, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { actual, err := NewAttributes(test.input) - if err != nil { - t.Fatalf("got an error while creating Attributes: %+v", err) + if test.wantErr != nil { + test.wantErr(t, err) + return } + require.NoError(t, err) if d := cmp.Diff(actual, test.expected); d != "" { t.Errorf("Attributes mismatch (-want +got):\n%s", d) diff --git a/syft/pkg/cataloger/binary/elf_package.go b/syft/pkg/cataloger/binary/elf_package.go index 9b13647a3..99a989752 100644 --- a/syft/pkg/cataloger/binary/elf_package.go +++ b/syft/pkg/cataloger/binary/elf_package.go @@ -2,6 +2,7 @@ package binary import ( "github.com/anchore/packageurl-go" + "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/cpe" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -29,13 +30,15 @@ func packageURL(metadata elfBinaryPackageNotes) string { os := metadata.OS osVersion := metadata.OSVersion + var atts cpe.Attributes atts, err := cpe.NewAttributes(metadata.OSCPE) - if err == nil { - // only "upgrade" the OS information if there is something more specific to use in it's place - if os == "" && osVersion == "" || os == "" && atts.Version != "" || atts.Product != "" && osVersion == "" { - os = atts.Product - osVersion = atts.Version - } + if err != nil { + log.WithFields("error", err).Warn("unable to parse cpe attributes for elf binary package") + } + // only "upgrade" the OS information if there is something more specific to use in it's place + if os == "" && osVersion == "" || os == "" && atts.Version != "" || atts.Product != "" && osVersion == "" { + os = atts.Product + osVersion = atts.Version } if os != "" { diff --git a/syft/pkg/cataloger/binary/elf_package_test.go b/syft/pkg/cataloger/binary/elf_package_test.go index 85fa42221..689e259d1 100644 --- a/syft/pkg/cataloger/binary/elf_package_test.go +++ b/syft/pkg/cataloger/binary/elf_package_test.go @@ -113,6 +113,18 @@ func Test_packageURL(t *testing.T) { }, want: "pkg:generic/system/test@1.0", }, + { + name: "bad or missing OSCPE data cannot be parsed allows for correct string", + metadata: elfBinaryPackageNotes{ + Name: "test", + Version: "1.0", + ELFBinaryPackageNoteJSONPayload: pkg.ELFBinaryPackageNoteJSONPayload{ + System: "system", + OSCPE: "%$#*(#*@&$(", + }, + }, + want: "pkg:generic/system/test@1.0", + }, } for _, test := range tests { diff --git a/syft/pkg/collection_test.go b/syft/pkg/collection_test.go index 65d74c33c..f22dc0b48 100644 --- a/syft/pkg/collection_test.go +++ b/syft/pkg/collection_test.go @@ -381,7 +381,7 @@ func TestCatalog_MergeRecords(t *testing.T) { Type: RpmPkg, }, { - CPEs: []cpe.CPE{cpe.Must("cpe:2.3:b:package:1:1:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource)}, + CPEs: []cpe.CPE{cpe.Must("cpe:2.3:a:package:2:2:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource)}, Locations: file.NewLocationSet( file.NewVirtualLocationFromCoordinates( file.Coordinates{ From 13c687690690f3a66553ea34a40902db1399ab0d Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Fri, 4 Oct 2024 11:07:29 -0400 Subject: [PATCH 239/284] Track supporting DPKG evidence (#3228) * add dpkg evidence support Signed-off-by: Alex Goodman * use path over filepath Signed-off-by: Alex Goodman --------- Signed-off-by: Alex Goodman --- internal/relationship/evident_by.go | 11 ++++--- internal/task/file_tasks.go | 16 +++++++--- syft/pkg/cataloger/debian/cataloger_test.go | 28 ++++++++-------- syft/pkg/cataloger/debian/package.go | 18 +++++++---- syft/pkg/cataloger/debian/parse_dpkg_db.go | 32 ++++++++++++++++++- .../lib/dpkg/status.d/libsqlite3-0.preinst | 1 + .../var/lib/dpkg/info/libpam-runtime.preinst | 1 + 7 files changed, 78 insertions(+), 29 deletions(-) create mode 100644 syft/pkg/cataloger/debian/test-fixtures/image-distroless-deb/var/lib/dpkg/status.d/libsqlite3-0.preinst create mode 100644 syft/pkg/cataloger/debian/test-fixtures/image-dpkg/var/lib/dpkg/info/libpam-runtime.preinst diff --git a/internal/relationship/evident_by.go b/internal/relationship/evident_by.go index 4050e96fd..ba4191325 100644 --- a/internal/relationship/evident_by.go +++ b/internal/relationship/evident_by.go @@ -9,15 +9,18 @@ func EvidentBy(catalog *pkg.Collection) []artifact.Relationship { var edges []artifact.Relationship for _, p := range catalog.Sorted() { for _, l := range p.Locations.ToSlice() { - if v, exists := l.Annotations[pkg.EvidenceAnnotationKey]; !exists || v != pkg.PrimaryEvidenceAnnotation { - // skip non-primary evidence from being expressed as a relationship. - // note: this may be configurable in the future. - continue + kind := pkg.SupportingEvidenceAnnotation + if v, exists := l.Annotations[pkg.EvidenceAnnotationKey]; exists { + kind = v } + edges = append(edges, artifact.Relationship{ From: p, To: l.Coordinates, Type: artifact.EvidentByRelationship, + Data: map[string]string{ + "kind": kind, + }, }) } } diff --git a/internal/task/file_tasks.go b/internal/task/file_tasks.go index 857f6e423..5369db327 100644 --- a/internal/task/file_tasks.go +++ b/internal/task/file_tasks.go @@ -134,9 +134,10 @@ func coordinatesForSelection(selection file.Selection, accessor sbomsync.Accesso } if selection == file.FilesOwnedByPackageSelection { - var coordinates []file.Coordinates + var coordinates file.CoordinateSet accessor.ReadFromSBOM(func(sbom *sbom.SBOM) { + // get any file coordinates that are owned by a package for _, r := range sbom.Relationships { if r.Type != artifact.ContainsRelationship { continue @@ -145,16 +146,23 @@ func coordinatesForSelection(selection file.Selection, accessor sbomsync.Accesso continue } if c, ok := r.To.(file.Coordinates); ok { - coordinates = append(coordinates, c) + coordinates.Add(c) } } + + // get any file coordinates referenced by a package directly + for p := range sbom.Artifacts.Packages.Enumerate() { + coordinates.Add(p.Locations.CoordinateSet().ToSlice()...) + } }) - if len(coordinates) == 0 { + coords := coordinates.ToSlice() + + if len(coords) == 0 { return nil, false } - return coordinates, true + return coords, true } return nil, false diff --git a/syft/pkg/cataloger/debian/cataloger_test.go b/syft/pkg/cataloger/debian/cataloger_test.go index 0f8a70a9a..629019954 100644 --- a/syft/pkg/cataloger/debian/cataloger_test.go +++ b/syft/pkg/cataloger/debian/cataloger_test.go @@ -25,15 +25,16 @@ func TestDpkgCataloger(t *testing.T) { Version: "1.1.8-3.6", FoundBy: "dpkg-db-cataloger", Licenses: pkg.NewLicenseSet( - pkg.NewLicenseFromLocations("GPL-1", file.NewVirtualLocation("/usr/share/doc/libpam-runtime/copyright", "/usr/share/doc/libpam-runtime/copyright")), - pkg.NewLicenseFromLocations("GPL-2", file.NewVirtualLocation("/usr/share/doc/libpam-runtime/copyright", "/usr/share/doc/libpam-runtime/copyright")), - pkg.NewLicenseFromLocations("LGPL-2.1", file.NewVirtualLocation("/usr/share/doc/libpam-runtime/copyright", "/usr/share/doc/libpam-runtime/copyright")), + pkg.NewLicenseFromLocations("GPL-1", file.NewLocation("/usr/share/doc/libpam-runtime/copyright")), + pkg.NewLicenseFromLocations("GPL-2", file.NewLocation("/usr/share/doc/libpam-runtime/copyright")), + pkg.NewLicenseFromLocations("LGPL-2.1", file.NewLocation("/usr/share/doc/libpam-runtime/copyright")), ), Locations: file.NewLocationSet( - file.NewVirtualLocation("/var/lib/dpkg/status", "/var/lib/dpkg/status"), - file.NewVirtualLocation("/var/lib/dpkg/info/libpam-runtime.md5sums", "/var/lib/dpkg/info/libpam-runtime.md5sums"), - file.NewVirtualLocation("/var/lib/dpkg/info/libpam-runtime.conffiles", "/var/lib/dpkg/info/libpam-runtime.conffiles"), - file.NewVirtualLocation("/usr/share/doc/libpam-runtime/copyright", "/usr/share/doc/libpam-runtime/copyright"), + file.NewLocation("/var/lib/dpkg/status"), + file.NewLocation("/var/lib/dpkg/info/libpam-runtime.preinst"), + file.NewLocation("/var/lib/dpkg/info/libpam-runtime.md5sums"), + file.NewLocation("/var/lib/dpkg/info/libpam-runtime.conffiles"), + file.NewLocation("/usr/share/doc/libpam-runtime/copyright"), ), Type: pkg.DebPkg, Metadata: pkg.DpkgDBEntry{ @@ -98,14 +99,15 @@ func TestDpkgCataloger(t *testing.T) { Version: "3.34.1-3", FoundBy: "dpkg-db-cataloger", Licenses: pkg.NewLicenseSet( - pkg.NewLicenseFromLocations("public-domain", file.NewVirtualLocation("/usr/share/doc/libsqlite3-0/copyright", "/usr/share/doc/libsqlite3-0/copyright")), - pkg.NewLicenseFromLocations("GPL-2+", file.NewVirtualLocation("/usr/share/doc/libsqlite3-0/copyright", "/usr/share/doc/libsqlite3-0/copyright")), - pkg.NewLicenseFromLocations("GPL-2", file.NewVirtualLocation("/usr/share/doc/libsqlite3-0/copyright", "/usr/share/doc/libsqlite3-0/copyright")), + pkg.NewLicenseFromLocations("public-domain", file.NewLocation("/usr/share/doc/libsqlite3-0/copyright")), + pkg.NewLicenseFromLocations("GPL-2+", file.NewLocation("/usr/share/doc/libsqlite3-0/copyright")), + pkg.NewLicenseFromLocations("GPL-2", file.NewLocation("/usr/share/doc/libsqlite3-0/copyright")), ), Locations: file.NewLocationSet( - file.NewVirtualLocation("/var/lib/dpkg/status.d/libsqlite3-0", "/var/lib/dpkg/status.d/libsqlite3-0"), - file.NewVirtualLocation("/var/lib/dpkg/status.d/libsqlite3-0.md5sums", "/var/lib/dpkg/status.d/libsqlite3-0.md5sums"), - file.NewVirtualLocation("/usr/share/doc/libsqlite3-0/copyright", "/usr/share/doc/libsqlite3-0/copyright"), + file.NewLocation("/var/lib/dpkg/status.d/libsqlite3-0"), + file.NewLocation("/var/lib/dpkg/status.d/libsqlite3-0.md5sums"), + file.NewLocation("/var/lib/dpkg/status.d/libsqlite3-0.preinst"), + file.NewLocation("/usr/share/doc/libsqlite3-0/copyright"), ), Type: pkg.DebPkg, Metadata: pkg.DpkgDBEntry{ diff --git a/syft/pkg/cataloger/debian/package.go b/syft/pkg/cataloger/debian/package.go index d31830e87..db93ba8eb 100644 --- a/syft/pkg/cataloger/debian/package.go +++ b/syft/pkg/cataloger/debian/package.go @@ -22,14 +22,18 @@ const ( docsPath = "/usr/share/doc" ) -func newDpkgPackage(d pkg.DpkgDBEntry, dbLocation file.Location, resolver file.Resolver, release *linux.Release) pkg.Package { +func newDpkgPackage(d pkg.DpkgDBEntry, dbLocation file.Location, resolver file.Resolver, release *linux.Release, evidence ...file.Location) pkg.Package { // TODO: separate pr to license refactor, but explore extracting dpkg-specific license parsing into a separate function licenses := make([]pkg.License, 0) + + locations := file.NewLocationSet(dbLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)) + locations.Add(evidence...) + p := pkg.Package{ Name: d.Package, Version: d.Version, Licenses: pkg.NewLicenseSet(licenses...), - Locations: file.NewLocationSet(dbLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + Locations: locations, PURL: packageURL(d, release), Type: pkg.DebPkg, Metadata: d, @@ -88,7 +92,7 @@ func packageURL(m pkg.DpkgDBEntry, distro *linux.Release) string { func addLicenses(resolver file.Resolver, dbLocation file.Location, p *pkg.Package) { metadata, ok := p.Metadata.(pkg.DpkgDBEntry) if !ok { - log.WithFields("package", p).Warn("unable to extract DPKG metadata to add licenses") + log.WithFields("package", p).Trace("unable to extract DPKG metadata to add licenses") return } @@ -110,7 +114,7 @@ func addLicenses(resolver file.Resolver, dbLocation file.Location, p *pkg.Packag func mergeFileListing(resolver file.Resolver, dbLocation file.Location, p *pkg.Package) { metadata, ok := p.Metadata.(pkg.DpkgDBEntry) if !ok { - log.WithFields("package", p).Warn("unable to extract DPKG metadata to file listing") + log.WithFields("package", p).Trace("unable to extract DPKG metadata to file listing") return } @@ -204,7 +208,7 @@ func fetchMd5Contents(resolver file.Resolver, dbLocation file.Location, m pkg.Dp // this is unexpected, but not a show-stopper md5Reader, err = resolver.FileContentsByLocation(*location) if err != nil { - log.Warnf("failed to fetch deb md5 contents (package=%s): %+v", m.Package, err) + log.Tracef("failed to fetch deb md5 contents (package=%s): %+v", m.Package, err) } l := location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) @@ -239,7 +243,7 @@ func fetchConffileContents(resolver file.Resolver, dbLocation file.Location, m p // this is unexpected, but not a show-stopper reader, err = resolver.FileContentsByLocation(*location) if err != nil { - log.Warnf("failed to fetch deb conffiles contents (package=%s): %+v", m.Package, err) + log.Tracef("failed to fetch deb conffiles contents (package=%s): %+v", m.Package, err) } l := location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) @@ -263,7 +267,7 @@ func fetchCopyrightContents(resolver file.Resolver, dbLocation file.Location, m reader, err := resolver.FileContentsByLocation(*location) if err != nil { - log.Warnf("failed to fetch deb copyright contents (package=%s): %s", m.Package, err) + log.Tracef("failed to fetch deb copyright contents (package=%s): %s", m.Package, err) } defer internal.CloseAndLogError(reader, location.RealPath) diff --git a/syft/pkg/cataloger/debian/parse_dpkg_db.go b/syft/pkg/cataloger/debian/parse_dpkg_db.go index 077e5bef9..8fc47eb49 100644 --- a/syft/pkg/cataloger/debian/parse_dpkg_db.go +++ b/syft/pkg/cataloger/debian/parse_dpkg_db.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "path" "regexp" "strings" @@ -34,12 +35,41 @@ func parseDpkgDB(_ context.Context, resolver file.Resolver, env *generic.Environ var pkgs []pkg.Package for _, m := range metadata { - pkgs = append(pkgs, newDpkgPackage(m, reader.Location, resolver, env.LinuxRelease)) + p := newDpkgPackage(m, reader.Location, resolver, env.LinuxRelease, findDpkgInfoFiles(m.Package, resolver, reader.Location)...) + pkgs = append(pkgs, p) } return pkgs, nil, nil } +func findDpkgInfoFiles(name string, resolver file.Resolver, dbLocation file.Location) []file.Location { + if resolver == nil { + return nil + } + if strings.TrimSpace(name) == "" { + return nil + } + + // for typical debian-base distributions, the installed package info is at /var/lib/dpkg/status + // and the md5sum information is under /var/lib/dpkg/info/; however, for distroless the installed + // package info is across multiple files under /var/lib/dpkg/status.d/ and the md5sums are contained in + // the same directory + searchPath := path.Dir(dbLocation.RealPath) + + if !strings.HasSuffix(searchPath, "status.d") { + searchPath = path.Join(searchPath, "info") + } + + // look for /var/lib/dpkg/info/NAME.* + locations, err := resolver.FilesByGlob(path.Join(searchPath, name+".*")) + if err != nil { + log.WithFields("error", err, "pkg", name).Trace("failed to fetch related dpkg info files") + return nil + } + + return locations +} + // parseDpkgStatus is a parser function for Debian DB status contents, returning all Debian packages listed. func parseDpkgStatus(reader io.Reader) ([]pkg.DpkgDBEntry, error) { buffedReader := bufio.NewReader(reader) diff --git a/syft/pkg/cataloger/debian/test-fixtures/image-distroless-deb/var/lib/dpkg/status.d/libsqlite3-0.preinst b/syft/pkg/cataloger/debian/test-fixtures/image-distroless-deb/var/lib/dpkg/status.d/libsqlite3-0.preinst new file mode 100644 index 000000000..52b07edd8 --- /dev/null +++ b/syft/pkg/cataloger/debian/test-fixtures/image-distroless-deb/var/lib/dpkg/status.d/libsqlite3-0.preinst @@ -0,0 +1 @@ +# some shell script... \ No newline at end of file diff --git a/syft/pkg/cataloger/debian/test-fixtures/image-dpkg/var/lib/dpkg/info/libpam-runtime.preinst b/syft/pkg/cataloger/debian/test-fixtures/image-dpkg/var/lib/dpkg/info/libpam-runtime.preinst new file mode 100644 index 000000000..52b07edd8 --- /dev/null +++ b/syft/pkg/cataloger/debian/test-fixtures/image-dpkg/var/lib/dpkg/info/libpam-runtime.preinst @@ -0,0 +1 @@ +# some shell script... \ No newline at end of file From fc8457418a7d2ba014c7e9c0cc2b4a11106c3dd4 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Sat, 5 Oct 2024 07:32:32 -0400 Subject: [PATCH 240/284] chore(deps): update tools to latest versions (#3296) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index a70b574fb..9f13016b0 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -42,7 +42,7 @@ tools: # used for signing the checksums file at release - name: cosign version: - want: v2.4.0 + want: v2.4.1 method: github-release with: repo: sigstore/cosign From 0d457142cca1a6c1c18430870ca0629dba6fb802 Mon Sep 17 00:00:00 2001 From: William Murphy Date: Sat, 5 Oct 2024 09:05:11 -0400 Subject: [PATCH 241/284] chore: add pull request template (#3294) Signed-off-by: Will Murphy --- .github/pull_request_template.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..de2b78a66 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,25 @@ +# Description + +Please include a summary of the changes along with any relevant motivation and context, +or link to an issue where this is explained. + + + +- Fixes # + +## Type of change + + + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (please discuss with the team first; Syft is 1.0 software and we won't accept breaking changes without going to 2.0) +- [ ] Documentation (updates the documentation) +- [ ] Chore (improve the developer experience, fix a test flake, etc, without changing the visible behavior of Syft) +- [ ] Performance (make Syft run faster or use less memory, without changing visible behavior much) + +# Checklist: + +- [ ] I have added unit tests that cover changed behavior +- [ ] I have tested my code in common scenarios and confirmed there are no regressions +- [ ] I have added comments to my code, particularly in hard-to-understand sections From 25f5c6729f02342c2a442b6d208e69b2a6661624 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Oct 2024 09:25:01 -0400 Subject: [PATCH 242/284] chore(deps): bump github/codeql-action from 3.26.10 to 3.26.11 (#3298) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.10 to 3.26.11. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/e2b3eafc8d227b0241d48be5f425d47c2d750a13...6db8d6351fd0be61f9ed8ebd12ccd35dcec51fea) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index be784870c..40cdaa41f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@e2b3eafc8d227b0241d48be5f425d47c2d750a13 #v3.26.10 + uses: github/codeql-action/init@6db8d6351fd0be61f9ed8ebd12ccd35dcec51fea #v3.26.11 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@e2b3eafc8d227b0241d48be5f425d47c2d750a13 #v3.26.10 + uses: github/codeql-action/autobuild@6db8d6351fd0be61f9ed8ebd12ccd35dcec51fea #v3.26.11 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@e2b3eafc8d227b0241d48be5f425d47c2d750a13 #v3.26.10 + uses: github/codeql-action/analyze@6db8d6351fd0be61f9ed8ebd12ccd35dcec51fea #v3.26.11 From 3b9c55d28b3e16193bb3b4fe6ecaa6920e9f5ad0 Mon Sep 17 00:00:00 2001 From: Piotr Radkowski Date: Mon, 7 Oct 2024 16:26:04 +0200 Subject: [PATCH 243/284] Fix: Parse package.json with non-standard fields in 'author' section (#3300) * Improved parsing of package.json 'author' section Signed-off-by: Piotr Radkowski * test: parse 'package.json' files with non-standard fields in author section Signed-off-by: Piotr Radkowski --------- Signed-off-by: Piotr Radkowski Co-authored-by: Piotr Radkowski --- .../javascript/parse_package_json.go | 24 +++++++++---------- .../javascript/parse_package_json_test.go | 21 ++++++++++++++++ .../pkg-json/package-author-non-standard.json | 16 +++++++++++++ 3 files changed, 49 insertions(+), 12 deletions(-) create mode 100644 syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-author-non-standard.json diff --git a/syft/pkg/cataloger/javascript/parse_package_json.go b/syft/pkg/cataloger/javascript/parse_package_json.go index b1677ae88..cc628c772 100644 --- a/syft/pkg/cataloger/javascript/parse_package_json.go +++ b/syft/pkg/cataloger/javascript/parse_package_json.go @@ -82,23 +82,23 @@ func parsePackageJSON(_ context.Context, _ file.Resolver, _ *generic.Environment func (a *author) UnmarshalJSON(b []byte) error { var authorStr string - var fields map[string]string var auth author - if err := json.Unmarshal(b, &authorStr); err != nil { - // string parsing did not work, assume a map was given - // for more information: https://docs.npmjs.com/files/package.json#people-fields-author-contributors + if err := json.Unmarshal(b, &authorStr); err == nil { + // successfully parsed as a string, now parse that string into fields + fields := internal.MatchNamedCaptureGroups(authorPattern, authorStr) + if err := mapstructure.Decode(fields, &auth); err != nil { + return fmt.Errorf("unable to decode package.json author: %w", err) + } + } else { + // it's a map that may contain fields of various data types (not just strings) + var fields map[string]interface{} if err := json.Unmarshal(b, &fields); err != nil { return fmt.Errorf("unable to parse package.json author: %w", err) } - } else { - // parse out "name (url)" into an author struct - fields = internal.MatchNamedCaptureGroups(authorPattern, authorStr) - } - - // translate the map into a structure - if err := mapstructure.Decode(fields, &auth); err != nil { - return fmt.Errorf("unable to decode package.json author: %w", err) + if err := mapstructure.Decode(fields, &auth); err != nil { + return fmt.Errorf("unable to decode package.json author: %w", err) + } } *a = auth diff --git a/syft/pkg/cataloger/javascript/parse_package_json_test.go b/syft/pkg/cataloger/javascript/parse_package_json_test.go index 5c544580a..5d6ebaf4a 100644 --- a/syft/pkg/cataloger/javascript/parse_package_json_test.go +++ b/syft/pkg/cataloger/javascript/parse_package_json_test.go @@ -179,6 +179,27 @@ func TestParsePackageJSON(t *testing.T) { }, }, }, + { + Fixture: "test-fixtures/pkg-json/package-author-non-standard.json", + ExpectedPkg: pkg.Package{ + Name: "npm", + Version: "6.14.6", + PURL: "pkg:npm/npm@6.14.6", + Type: pkg.NpmPkg, + Licenses: pkg.NewLicenseSet( + pkg.NewLicenseFromLocations("Artistic-2.0", file.NewLocation("test-fixtures/pkg-json/package-author-non-standard.json")), + ), + Language: pkg.JavaScript, + Metadata: pkg.NpmPackage{ + Name: "npm", + Version: "6.14.6", + Author: "npm Inc. (https://www.npmjs.com/)", + Homepage: "https://docs.npmjs.com/", + URL: "https://github.com/npm/cli", + Description: "a package manager for JavaScript", + }, + }, + }, } for _, test := range tests { diff --git a/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-author-non-standard.json b/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-author-non-standard.json new file mode 100644 index 000000000..a71cf820a --- /dev/null +++ b/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-author-non-standard.json @@ -0,0 +1,16 @@ +{ + "version": "6.14.6", + "name": "npm", + "description": "a package manager for JavaScript", + "homepage": "https://docs.npmjs.com/", + "author": { + "name": "npm Inc.", + "url": "https://www.npmjs.com/", + "organization": true + }, + "repository": { + "type": "git", + "url": "https://github.com/npm/cli" + }, + "license": "Artistic-2.0" +} \ No newline at end of file From 27ee203495eeda7ef0046d0c5c45dc377c9126ed Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 15:20:12 -0400 Subject: [PATCH 244/284] chore(deps): update CPE dictionary index (#3302) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: wagoodman <590471+wagoodman@users.noreply.github.com> --- .../dictionary/data/cpe-index.json | 131 +++++++++++++++++- 1 file changed, 126 insertions(+), 5 deletions(-) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index a775fdfb0..620c92698 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -7056,7 +7056,7 @@ "cpe:2.3:a:johnkolbert:absolute_privacy:*:*:*:*:*:wordpress:*:*" ], "absolute-reviews": [ - "cpe:2.3:a:ashstonestudios:absolute_reviews:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:codesupply:absolute_reviews:*:*:*:*:*:wordpress:*:*" ], "abwp-simple-counter": [ "cpe:2.3:a:ab-wp:simple_counter:*:*:*:*:*:wordpress:*:*" @@ -7400,6 +7400,9 @@ "advanced-recent-posts": [ "cpe:2.3:a:advanced_recent_posts_project:advanced_recent_posts:*:*:*:*:*:wordpress:*:*" ], + "advanced-sermons": [ + "cpe:2.3:a:wpcodeus:advanced_sermons:*:*:*:*:*:wordpress:*:*" + ], "advanced-uploader": [ "cpe:2.3:a:advanced_uploader_project:advanced_uploader:*:*:*:*:*:wordpress:*:*" ], @@ -7628,6 +7631,9 @@ "animated-counters": [ "cpe:2.3:a:eralion:animated_counters:*:*:*:*:*:wordpress:*:*" ], + "animated-number-counters": [ + "cpe:2.3:a:wpmart:animated_number_counters:*:*:*:*:*:wordpress:*:*" + ], "anonymous-restricted-content": [ "cpe:2.3:a:tarassych:anonymous_restricted_content:*:*:*:*:*:wordpress:*:*" ], @@ -7904,6 +7910,9 @@ "awsm-team": [ "cpe:2.3:a:awsm:awsm_team:*:*:*:*:free:wordpress:*:*" ], + "ays-chatgpt-assistant": [ + "cpe:2.3:a:ays-pro:chatgpt_assistant:*:*:*:*:free:wordpress:*:*" + ], "ays-facebook-popup-likebox": [ "cpe:2.3:a:ays-pro:popup_box:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:aysproextensions:popup_like:*:*:*:*:*:wordpress:*:*" @@ -8127,6 +8136,9 @@ "blockonomics-bitcoin-payments": [ "cpe:2.3:a:blockonomics:blockonomics:*:*:*:*:*:wordpress:*:*" ], + "blockspare": [ + "cpe:2.3:a:blockspare:blockspare:*:*:*:*:*:wordpress:*:*" + ], "blocksy-companion": [ "cpe:2.3:a:creativethemes:blocksy_companion:*:*:*:*:*:wordpress:*:*" ], @@ -8797,6 +8809,9 @@ "cmyee-momentopress": [ "cpe:2.3:a:chrisyee:momentopress_for_momento360:*:*:*:*:*:wordpress:*:*" ], + "coblocks": [ + "cpe:2.3:a:godaddy:coblocks:*:*:*:*:*:wordpress:*:*" + ], "code-snippets": [ "cpe:2.3:a:code_snippets:code_snippets:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:codesnippets:code_snippets:*:*:*:*:*:wordpress:*:*" @@ -8821,6 +8836,9 @@ "colibri-page-builder": [ "cpe:2.3:a:extendthemes:colibri_page_builder:*:*:*:*:*:wordpress:*:*" ], + "collectchat": [ + "cpe:2.3:a:micro.company:collect.chat:*:*:*:*:*:wordpress:*:*" + ], "colorful-categories": [ "cpe:2.3:a:gesundheit-bewegt:colorful_categories:*:*:*:*:*:wordpress:*:*" ], @@ -8910,6 +8928,9 @@ "conference-scheduler": [ "cpe:2.3:a:myceliumdesign:conference_scheduler:*:*:*:*:*:wordpress:*:*" ], + "confetti-fall-animation": [ + "cpe:2.3:a:wpdeveloperr:confetti_fall_animation:*:*:*:*:*:wordpress:*:*" + ], "configurable-tag-cloud-widget": [ "cpe:2.3:a:configurable_tag_cloud_project:configurable_tag_cloud:*:*:*:*:*:wordpress:*:*" ], @@ -9421,6 +9442,9 @@ "custom-options-plus": [ "cpe:2.3:a:leocaseiro:custom_options_plus:*:*:*:*:*:wordpress:*:*" ], + "custom-permalinks": [ + "cpe:2.3:a:samiahmedsiddiqui:custom_permalinks:*:*:*:*:*:wordpress:*:*" + ], "custom-post-type-cpt-cusom-taxonomy-ct-manager": [ "cpe:2.3:a:custom_post_type_and_taxonomy_gui_manager_project:custom_post_type_and_taxonomy_gui_manager:*:*:*:*:*:wordpress:*:*" ], @@ -9499,7 +9523,6 @@ "cpe:2.3:a:daggerhartlab:openid_connect_generic_client:*:*:*:*:*:wordpress:*:*" ], "daily-prayer-time-for-mosques": [ - "cpe:2.3:a:daily_prayer_time_project:daily_prayer_time:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:mmrs151:daily_prayer_time:*:*:*:*:*:wordpress:*:*" ], "dans-gcal": [ @@ -10703,6 +10726,10 @@ "foogallery-premium": [ "cpe:2.3:a:fooplugins:foogallery:*:*:*:*:*:wordpress:*:*" ], + "football-leagues-by-anwppro": [ + "cpe:2.3:a:anwp:football_leagues:*:*:*:*:free:wordpress:*:*", + "cpe:2.3:a:anwp:football_leagues:*:*:*:*:premium:wordpress:*:*" + ], "football-pool": [ "cpe:2.3:a:football_pool_project:football_pool:*:*:*:*:*:wordpress:*:*" ], @@ -10775,6 +10802,10 @@ "formzu-wp": [ "cpe:2.3:a:formzu:formzu_wp:*:*:*:*:*:wordpress:*:*" ], + "forumwp": [ + "cpe:2.3:a:ultimatemember:forumwp:*:*:*:*:free:wordpress:*:*", + "cpe:2.3:a:ultimatemember:forumwp:*:*:*:*:pro:wordpress:*:*" + ], "fossura-tag-miner": [ "cpe:2.3:a:fossura:tag_miner:*:*:*:*:*:wordpress:*:*" ], @@ -10996,6 +11027,9 @@ "gf-block-ips": [ "cpe:2.3:a:brightplugins:block_ips_for_gravity_forms:*:*:*:*:*:wordpress:*:*" ], + "gf-custom-style": [ + "cpe:2.3:a:alefypimentel:gf_custom_style:*:*:*:*:*:wordpress:*:*" + ], "gg-woo-feed": [ "cpe:2.3:a:gutengeek:gg_woo_feed:*:*:*:*:*:wordpress:*:*" ], @@ -11425,7 +11459,7 @@ "cpe:2.3:a:hasthemes:ht_feed:*:*:*:*:*:wordpress:*:*" ], "ht-mega-for-elementor": [ - "cpe:2.3:a:hasthemes:ht_mega_-_absolute_addons_for_elementor_page_builder:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:hasthemes:ht_mega:*:*:*:*:free:wordpress:*:*" ], "ht-menu-lite": [ "cpe:2.3:a:hasthemes:ht_menu:*:*:*:*:*:wordpress:*:*" @@ -11665,6 +11699,9 @@ "infographic-and-list-builder-ilist": [ "cpe:2.3:a:quantumcloud:infographic_maker:*:*:*:*:*:wordpress:*:*" ], + "infolinks-ad-wrap": [ + "cpe:2.3:a:rubayathasan:infolinks_ad_wrap:*:*:*:*:*:wordpress:*:*" + ], "information-reel": [ "cpe:2.3:a:gopiplus:information_reel:*:*:*:*:*:wordpress:*:*" ], @@ -12146,6 +12183,9 @@ "legal-pages": [ "cpe:2.3:a:wpwax:legal_pages:*:*:*:*:*:wordpress:*:*" ], + "leira-cron-jobs": [ + "cpe:2.3:a:leira:cron_jobs:*:*:*:*:*:wordpress:*:*" + ], "letterpress": [ "cpe:2.3:a:themeqx:letterpress:*:*:*:*:*:wordpress:*:*" ], @@ -12445,6 +12485,9 @@ "mapping-multiple-urls-redirect-same-page": [ "cpe:2.3:a:mapping_multiple_urls_redirect_same_page_project:mapping_multiple_urls_redirect_same_page:*:*:*:*:*:wordpress:*:*" ], + "mapplic-lite": [ + "cpe:2.3:a:mapplic:mapplic:*:*:*:*:lite:wordpress:*:*" + ], "mappress-google-maps-for-wordpress": [ "cpe:2.3:a:mappresspro:mappress:*:*:*:*:free:wordpress:*:*", "cpe:2.3:a:mappresspro:mappress:*:*:*:*:pro:wordpress:*:*", @@ -13100,6 +13143,9 @@ "nktagcloud": [ "cpe:2.3:a:better_tag_cloud_project:better_tag_cloud:*:*:*:*:*:wordpress:*:*" ], + "nm-visitors": [ + "cpe:2.3:a:nitinmaurya:wordpress_visitors:*:*:*:*:*:wordpress:*:*" + ], "nmedia-user-file-uploader": [ "cpe:2.3:a:najeebmedia:frontend_file_manager_plugin:*:*:*:*:*:wordpress:*:*" ], @@ -13297,6 +13343,9 @@ "cpe:2.3:a:tychesoftwares:order_delivery_date_for_woocommerce:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:tychesoftwares:order_delivery_date_for_wp_e-commerce:*:*:*:*:*:wordpress:*:*" ], + "order-hours-scheduler-for-woocommerce": [ + "cpe:2.3:a:bizswoop:store_hours_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], "order-import-export-for-woocommerce": [ "cpe:2.3:a:webtoffee:order_export_\\\u0026_order_import_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], @@ -13318,6 +13367,9 @@ "osmapper": [ "cpe:2.3:a:b4after:osmapper:*:*:*:*:*:wordpress:*:*" ], + "ota-sync-booking-engine-widget": [ + "cpe:2.3:a:otasync:ota_sync_booking_engine_widget:*:*:*:*:*:wordpress:*:*" + ], "otter-blocks": [ "cpe:2.3:a:themeisle:otter_blocks:*:*:*:*:*:*:*:*", "cpe:2.3:a:themeisle:otter_blocks:*:*:*:*:*:wordpress:*:*" @@ -13824,6 +13876,9 @@ "post-to-csv": [ "cpe:2.3:a:bestwebsoft:post_to_csv:*:*:*:*:*:wordpress:*:*" ], + "post-type-archive-mapping": [ + "cpe:2.3:a:mediaron:custom_query_blocks:*:*:*:*:*:wordpress:*:*" + ], "post-type-x": [ "cpe:2.3:a:implecode:product_catalog_simple:*:*:*:*:*:wordpress:*:*" ], @@ -13876,6 +13931,9 @@ "cpe:2.3:a:samperrow:party_resource_hints:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:samperrow:pre_party_resource_hints:*:*:*:*:*:wordpress:*:*" ], + "preloader-plus": [ + "cpe:2.3:a:wp-brandtheme:preloader_plus:*:*:*:*:*:wordpress:*:*" + ], "premium-addons-for-elementor": [ "cpe:2.3:a:leap13:premium_addons_for_elementor:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:leap13:premium_addons_for_elementor:*:*:*:*:pro:wordpress:*:*" @@ -13886,6 +13944,9 @@ "premmerce-redirect-manager": [ "cpe:2.3:a:premmerce:redirect_manager:*:*:*:*:*:wordpress:*:*" ], + "premmerce-woocommerce-product-filter": [ + "cpe:2.3:a:premmerce:premmerce_product_filter_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], "prepost-seo": [ "cpe:2.3:a:enzipe:prepost_seo:*:*:*:*:*:wordpress:*:*" ], @@ -13895,6 +13956,9 @@ "pressforward": [ "cpe:2.3:a:pressforward:pressforward:*:*:*:*:*:wordpress:*:*" ], + "pretty-simple-popup-builder": [ + "cpe:2.3:a:5starplugins:pretty_simple_popup_builder:*:*:*:*:*:wordpress:*:*" + ], "prettyphoto": [ "cpe:2.3:a:master-addons:prettyphoto:*:*:*:*:*:wordpress:*:*" ], @@ -14325,6 +14389,9 @@ "cpe:2.3:a:bestwebsoft:relevant:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:bestwebsoft:relevant_-_related_posts:*:*:*:*:*:wordpress:*:*" ], + "remember-me-controls": [ + "cpe:2.3:a:coffee2code:remember_me_controls:*:*:*:*:*:wordpress:*:*" + ], "remove-footer-credit": [ "cpe:2.3:a:wpchill:remove_footer_credit:*:*:*:*:*:wordpress:*:*" ], @@ -14798,7 +14865,7 @@ "cpe:2.3:a:share_on_diaspora_project:share_on_diaspora:*:*:*:*:*:wordpress:*:*" ], "share-this-image": [ - "cpe:2.3:a:share_this_image_project:share_this_image:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:wp-unit:share_this_image:*:*:*:*:*:wordpress:*:*" ], "shareaholic": [ "cpe:2.3:a:shareaholic:shareaholic:*:*:*:*:*:wordpress:*:*" @@ -14906,6 +14973,9 @@ "sideblog": [ "cpe:2.3:a:sideblog_project:sideblog:*:*:*:*:*:wordpress:*:*" ], + "sight": [ + "cpe:2.3:a:codesupply:sight:*:*:*:*:*:wordpress:*:*" + ], "sign-up-sheets": [ "cpe:2.3:a:fetchdesigns:sign-up_sheets:*:*:*:*:*:wordpress:*:*" ], @@ -15013,9 +15083,15 @@ "simple-jwt-login": [ "cpe:2.3:a:simple_jwt_login_project:simple_jwt_login:*:*:*:*:*:wordpress:*:*" ], + "simple-ldap-login": [ + "cpe:2.3:a:objectiv:simple_ldap_login:*:*:*:*:*:wordpress:*:*" + ], "simple-link-directory": [ "cpe:2.3:a:quantumcloud:simple_link_directory:*:*:*:*:*:wordpress:*:*" ], + "simple-local-avatars": [ + "cpe:2.3:a:10up:simple_local_avatars:*:*:*:*:*:wordpress:*:*" + ], "simple-login-log": [ "cpe:2.3:a:simplerealtytheme:simple_login_log:*:*:*:*:*:wordpress:*:*" ], @@ -15058,6 +15134,9 @@ "simple-popup-newsletter": [ "cpe:2.3:a:keszites:simple_popup_newsletter:*:*:*:*:*:wordpress:*:*" ], + "simple-popup-plugin": [ + "cpe:2.3:a:garrettgrimm:simple_popup_plugin:*:*:*:*:*:wordpress:*:*" + ], "simple-portfolio-gallery": [ "cpe:2.3:a:simple_portfolio_gallery_project:simple_portfolio_gallery:*:*:*:*:*:wordpress:*:*" ], @@ -15220,6 +15299,9 @@ "sliced-invoices": [ "cpe:2.3:a:slicedinvoices:sliced_invoices:*:*:*:*:*:wordpress:*:*" ], + "slicewp": [ + "cpe:2.3:a:slicewp:affiliate_program_suite:*:*:*:*:*:wordpress:*:*" + ], "slick-contact-forms": [ "cpe:2.3:a:leechesnutt:slick_contact_forms:*:*:*:*:*:wordpress:*:*" ], @@ -15428,6 +15510,9 @@ "sola-support-tickets": [ "cpe:2.3:a:solaplugins:sola_support_tickets:*:*:*:*:*:wordpress:*:*" ], + "sola-testimonials": [ + "cpe:2.3:a:codecabin:super_testimonials:*:*:*:*:*:wordpress:*:*" + ], "solidres": [ "cpe:2.3:a:solidres:solidres:*:*:*:*:*:wordpress:*:*" ], @@ -15931,6 +16016,9 @@ "theme-translation-for-polylang": [ "cpe:2.3:a:theme_and_plugin_translation_for_polylang_project:theme_and_plugin_translation_for_polylang:*:*:*:*:*:wordpress:*:*" ], + "themedy-toolbox": [ + "cpe:2.3:a:themedy:toolbox:*:*:*:*:*:wordpress:*:*" + ], "themegrill-demo-importer": [ "cpe:2.3:a:themegrill:themegrill_demo_importer:*:*:*:*:*:wordpress:*:*" ], @@ -17180,6 +17268,9 @@ "wordpress-nextgen-galleryview": [ "cpe:2.3:a:wordpress_nextgen_galleryview_project:wordpress_nextgen_galleryview:*:*:*:*:*:wordpress:*:*" ], + "wordpress-notification-bar": [ + "cpe:2.3:a:seedprod:wordpress_notification_bar:*:*:*:*:*:wordpress:*:*" + ], "wordpress-ping-optimizer": [ "cpe:2.3:a:wordpress_ping_optimizer_project:wordpress_ping_optimizer:*:*:*:*:*:wordpress:*:*" ], @@ -17335,6 +17426,9 @@ "wp-categories-widget": [ "cpe:2.3:a:wp-experts:wp-categories-widget:*:*:*:*:*:wordpress:*:*" ], + "wp-category-dropdown": [ + "cpe:2.3:a:gcsdesign:wp_category_dropdown:*:*:*:*:*:wordpress:*:*" + ], "wp-category-meta": [ "cpe:2.3:a:randyhoyt:category_meta:*:*:*:*:*:wordpress:*:*" ], @@ -18056,6 +18150,9 @@ "wp-pro-quiz": [ "cpe:2.3:a:wp-pro-quiz_project:wp-pro-quiz:*:*:*:*:*:wordpress:*:*" ], + "wp-product-feed-manager": [ + "cpe:2.3:a:wpmarketingrobot:woocommerce_google_feed_manager:*:*:*:*:*:wordpress:*:*" + ], "wp-product-gallery-lite": [ "cpe:2.3:a:accesspressthemes:wp_product_gallery_lite:*:*:*:*:*:wordpress:*:*" ], @@ -18354,7 +18451,7 @@ "cpe:2.3:a:ljapps:wp_tripadvisor_review_slider:*:*:*:*:*:wordpress:*:*" ], "wp-ulike": [ - "cpe:2.3:a:technowich:wp_ulike_-_most_advanced_wordpress_marketing_toolkit:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:technowich:wp_ulike:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:wpulike:wp_ulike:*:*:*:*:*:wordpress:*:*" ], "wp-ultimate-csv-importer": [ @@ -18489,6 +18586,9 @@ "wpcodefactory-helper": [ "cpe:2.3:a:wpfactory:wpfactory_helper:*:*:*:*:*:wordpress:*:*" ], + "wpcom-member": [ + "cpe:2.3:a:wpcom:wpcom_member:*:*:*:*:*:wordpress:*:*" + ], "wpcommenttwit": [ "cpe:2.3:a:wpcommenttwit_project:wpcommenttwit:*:*:*:*:*:wordpress:*:*" ], @@ -18564,6 +18664,9 @@ "wpglobus-translate-options": [ "cpe:2.3:a:wpglobus:wpglobus_translate_options:*:*:*:*:*:wordpress:*:*" ], + "wpgsi": [ + "cpe:2.3:a:javmah:spreadsheet_integration:*:*:*:*:*:wordpress:*:*" + ], "wpide": [ "cpe:2.3:a:xplodedthemes:wpide:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:xplodedthemes:wpide_-_file_manager_\\\u0026_code_editor:*:*:*:*:*:wordpress:*:*" @@ -18991,6 +19094,9 @@ "darcie": [ "cpe:2.3:a:catchthemes:darcie:*:*:*:*:*:wordpress:*:*" ], + "delicate": [ + "cpe:2.3:a:nattywp:delicate:*:*:*:*:*:wordpress:*:*" + ], "digital-newspaper": [ "cpe:2.3:a:blazethemes:digital_newspaper:*:*:*:*:*:wordpress:*:*" ], @@ -19061,6 +19167,9 @@ "cpe:2.3:a:climaxthemes:kata_apps:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:climaxthemes:kata_business:*:*:*:*:*:wordpress:*:*" ], + "liquido": [ + "cpe:2.3:a:cryoutcreations:liquido:*:*:*:*:*:wordpress:*:*" + ], "mantra": [ "cpe:2.3:a:cryoutcreations:mantra:*:*:*:*:*:wordpress:*:*" ], @@ -19085,6 +19194,9 @@ "mystique": [ "cpe:2.3:a:digitalnature:mystique:*:*:*:*:*:wordpress:*:*" ], + "neighborly": [ + "cpe:2.3:a:arnoldgoodway:neighborly:*:*:*:*:*:wordpress:*:*" + ], "newsmag": [ "cpe:2.3:a:machothemes:newsmag:*:*:*:*:*:wordpress:*:*" ], @@ -19109,6 +19221,9 @@ "parabola": [ "cpe:2.3:a:cryoutcreations:parabola:*:*:*:*:*:wordpress:*:*" ], + "phlox": [ + "cpe:2.3:a:averta:phlox:*:*:*:*:free:wordpress:*:*" + ], "pinzolo": [ "cpe:2.3:a:thriveweb:pinzolo:*:*:*:*:*:wordpress:*:*" ], @@ -19139,6 +19254,9 @@ "sinatra": [ "cpe:2.3:a:sinatrateam:sinatra:*:*:*:*:*:wordpress:*:*" ], + "sliding-door": [ + "cpe:2.3:a:wayneconnor:sliding_door:*:*:*:*:*:wordpress:*:*" + ], "sparkling": [ "cpe:2.3:a:colorlib:sparklinkg:*:*:*:*:*:wordpress:*:*" ], @@ -19148,6 +19266,9 @@ "transcend": [ "cpe:2.3:a:cpothemes:transcend:*:*:*:*:*:wordpress:*:*" ], + "tweaker5": [ + "cpe:2.3:a:arnoldgoodway:tweaker5:*:*:*:*:*:wordpress:*:*" + ], "upfrontwp": [ "cpe:2.3:a:wpazure:upfrontwp:*:*:*:*:*:wordpress:*:*" ], From 7b30ce15d75e78d64e52f5ef84f8eba688d23ce3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 15:20:29 -0400 Subject: [PATCH 245/284] chore(deps): bump actions/cache from 4.0.2 to 4.1.0 (#3305) Bumps [actions/cache](https://github.com/actions/cache) from 4.0.2 to 4.1.0. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/0c45773b623bea8c8e75f6c82b208c3cf94ea4f9...2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/benchmark-testing.yaml | 2 +- .github/workflows/validations.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/benchmark-testing.yaml b/.github/workflows/benchmark-testing.yaml index c749bdcbe..ea29b9927 100644 --- a/.github/workflows/benchmark-testing.yaml +++ b/.github/workflows/benchmark-testing.yaml @@ -23,7 +23,7 @@ jobs: uses: ./.github/actions/bootstrap - name: Restore base benchmark result - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2 + uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 #v4.1.0 with: path: test/results/benchmark-main.txt # use base sha for PR or new commit hash for main push in benchmark result key diff --git a/.github/workflows/validations.yaml b/.github/workflows/validations.yaml index c028492c7..c1d3ca627 100644 --- a/.github/workflows/validations.yaml +++ b/.github/workflows/validations.yaml @@ -78,7 +78,7 @@ jobs: # why not use actions/upload-artifact? It is very slow (3 minutes to upload ~600MB of data, vs 10 seconds with this approach). # see https://github.com/actions/upload-artifact/issues/199 for more info - name: Upload snapshot artifacts - uses: actions/cache/save@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2 + uses: actions/cache/save@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 #v4.1.0 with: # we need to preserve the snapshot data itself as well as the task data that confirms if the # snapshot build is stale or not. Otherwise the downstream jobs will attempt to rebuild the snapshot @@ -104,7 +104,7 @@ jobs: - name: Download snapshot build id: snapshot-cache - uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2 + uses: actions/cache/restore@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 #v4.1.0 with: path: | snapshot @@ -152,7 +152,7 @@ jobs: - name: Download snapshot build id: snapshot-cache - uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2 + uses: actions/cache/restore@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 #v4.1.0 with: path: | snapshot @@ -187,7 +187,7 @@ jobs: - name: Download snapshot build id: snapshot-cache - uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2 + uses: actions/cache/restore@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 #v4.1.0 with: path: | snapshot From 8b6159dbd8c2b2c665ddddaeac56bf9885f45a4a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 15:20:38 -0400 Subject: [PATCH 246/284] chore(deps): bump golang.org/x/net from 0.29.0 to 0.30.0 (#3304) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.29.0 to 0.30.0. - [Commits](https://github.com/golang/net/compare/v0.29.0...v0.30.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index ece0947f9..42650f58d 100644 --- a/go.mod +++ b/go.mod @@ -79,7 +79,7 @@ require ( github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1 go.uber.org/goleak v1.3.0 golang.org/x/mod v0.21.0 - golang.org/x/net v0.29.0 + golang.org/x/net v0.30.0 gopkg.in/yaml.v3 v3.0.1 modernc.org/sqlite v1.33.1 ) @@ -227,11 +227,11 @@ require ( go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect - golang.org/x/crypto v0.27.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/term v0.24.0 // indirect - golang.org/x/text v0.18.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/term v0.25.0 // indirect + golang.org/x/text v0.19.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect diff --git a/go.sum b/go.sum index a7223f4e1..6a7a19568 100644 --- a/go.sum +++ b/go.sum @@ -864,8 +864,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -954,8 +954,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1067,15 +1067,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1088,8 +1088,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 4c4e5cb06c27b28a637243f4b91a45ce668a4498 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 15:21:26 -0400 Subject: [PATCH 247/284] chore(deps): update stereoscope to efa76446cc1c7e6c4117350943a2754b2453aec4 (#3301) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: kzantow <3009477+kzantow@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 42650f58d..58c3c35b0 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f - github.com/anchore/stereoscope v0.0.4-0.20240925150116-dc10ea61fd18 + github.com/anchore/stereoscope v0.0.4-0.20241005180410-efa76446cc1c github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // we are hinting brotli to latest due to warning when installing archiver v3: // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption diff --git a/go.sum b/go.sum index 6a7a19568..e9a2d1f35 100644 --- a/go.sum +++ b/go.sum @@ -115,8 +115,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f h1:B/E9ixKNCasntpoch61NDaQyGPDXLEJlL+B9B/PbdbA= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.4-0.20240925150116-dc10ea61fd18 h1:JfE3paLL87dDBHHHdTfnkpyPR72ua8jUbIDs3U/KEBs= -github.com/anchore/stereoscope v0.0.4-0.20240925150116-dc10ea61fd18/go.mod h1:5DJheGPjVRsSqegTB24Zi6SCHnYQnA519yeIG+RG+I4= +github.com/anchore/stereoscope v0.0.4-0.20241005180410-efa76446cc1c h1:JXezMk8fF5ns4AgRGW49SGfoRgDjJHsDmcpNw272jkU= +github.com/anchore/stereoscope v0.0.4-0.20241005180410-efa76446cc1c/go.mod h1:GMupz2FoBhy5RTTmawU06c2pZxgVTceahLWiwJef2uI= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= From 4d7ed9f749243ceb56bf2ae8885a140c41350792 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 15:21:34 -0400 Subject: [PATCH 248/284] chore(deps): bump sigstore/cosign-installer from 3.6.0 to 3.7.0 (#3299) Bumps [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) from 3.6.0 to 3.7.0. - [Release notes](https://github.com/sigstore/cosign-installer/releases) - [Commits](https://github.com/sigstore/cosign-installer/compare/v3.6.0...v3.7.0) --- updated-dependencies: - dependency-name: sigstore/cosign-installer dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/validations.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validations.yaml b/.github/workflows/validations.yaml index c1d3ca627..9ec3e39ef 100644 --- a/.github/workflows/validations.yaml +++ b/.github/workflows/validations.yaml @@ -139,7 +139,7 @@ jobs: runs-on: macos-latest steps: - name: Install Cosign - uses: sigstore/cosign-installer@v3.6.0 + uses: sigstore/cosign-installer@v3.7.0 - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 From ccbee94b876240284c25c8931c6233fc71a5b7fb Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Mon, 7 Oct 2024 16:11:37 -0400 Subject: [PATCH 249/284] feat: report unknowns in sbom (#2998) Signed-off-by: Keith Zantow Signed-off-by: Alex Goodman Co-authored-by: Alex Goodman --- cmd/syft/internal/options/catalog.go | 12 + cmd/syft/internal/options/unknowns.go | 31 + internal/constants.go | 2 +- internal/file/zip_file_manifest.go | 6 +- internal/file/zip_read_closer.go | 8 +- internal/task/executor.go | 34 +- internal/task/file_tasks.go | 21 +- internal/task/package_task_factory.go | 5 +- internal/task/unknowns_tasks.go | 114 + internal/unknown/coordinate_error.go | 201 ++ internal/unknown/coordinate_error_test.go | 236 ++ schema/json/schema-16.0.18.json | 2727 +++++++++++++++++ schema/json/schema-latest.json | 8 +- syft/cataloging/unknowns.go | 15 + syft/create_sbom_config.go | 25 + syft/create_sbom_config_test.go | 15 + syft/file/cataloger/executable/cataloger.go | 37 +- syft/file/cataloger/executable/elf.go | 12 +- syft/file/cataloger/executable/elf_test.go | 2 + syft/file/cataloger/filecontent/cataloger.go | 13 +- syft/file/cataloger/filedigest/cataloger.go | 8 +- syft/file/cataloger/filemetadata/cataloger.go | 6 +- syft/file/coordinates.go | 4 + syft/format/syftjson/decoder_test.go | 1 + syft/format/syftjson/model/file.go | 1 + syft/format/syftjson/to_format_model.go | 6 + syft/format/syftjson/to_syft_model.go | 7 + syft/format/syftjson/to_syft_model_test.go | 2 + syft/pkg/cataloger/alpine/cataloger_test.go | 8 + syft/pkg/cataloger/alpine/parse_apk_db.go | 6 +- .../corrupt/lib/apk/db/installed | 43 + syft/pkg/cataloger/arch/cataloger_test.go | 8 + syft/pkg/cataloger/arch/parse_alpm_db.go | 64 +- .../var/lib/pacman/local/corrupt-0.2.1-3/desc | 34 + .../cataloger/binary/classifier_cataloger.go | 14 +- .../binary/classifier_cataloger_test.go | 2 +- .../cataloger/binary/elf_package_cataloger.go | 11 +- .../binary/elf_package_cataloger_test.go | 5 + .../elf-test-fixtures/Dockerfile | 4 + .../elfbinwithcorrupt/elfsrc/hello_world.cpp | 6 + .../elfbinwithcorrupt/elfsrc/hello_world.h | 8 + .../elfbinwithcorrupt/elfsrc/makefile | 48 + .../elfbinwithcorrupt/elfsrc/testbin.cpp | 8 + .../elfbinwithcorrupt/makefile | 18 + syft/pkg/cataloger/cpp/parse_conanfile.go | 3 +- syft/pkg/cataloger/cpp/parse_conanlock.go | 3 +- .../pkg/cataloger/cpp/parse_conanlock_test.go | 7 + .../cpp/test-fixtures/corrupt/conan.lock | 10 + syft/pkg/cataloger/dart/parse_pubspec_lock.go | 3 +- .../cataloger/dart/parse_pubspec_lock_test.go | 7 + .../dart/test-fixtures/corrupt/pubspec.lock | 7 + syft/pkg/cataloger/debian/parse_dpkg_db.go | 3 +- .../cataloger/debian/parse_dpkg_db_test.go | 13 +- .../var/lib/dpkg/status.d/corrupt | 6 + .../pkg/cataloger/dotnet/parse_dotnet_deps.go | 3 +- .../dotnet/parse_dotnet_deps_test.go | 7 + .../parse_dotnet_portable_executable.go | 18 +- .../parse_dotnet_portable_executable_test.go | 7 + syft/pkg/cataloger/elixir/parse_mix_lock.go | 11 +- syft/pkg/cataloger/erlang/parse_otp_app.go | 3 +- .../cataloger/erlang/parse_otp_app_test.go | 7 + syft/pkg/cataloger/erlang/parse_rebar_lock.go | 3 +- .../cataloger/erlang/parse_rebar_lock_test.go | 7 + .../erlang/test-fixtures/corrupt/rabbitmq.app | 9 + .../erlang/test-fixtures/corrupt/rebar.lock | 11 + syft/pkg/cataloger/generic/cataloger.go | 13 +- syft/pkg/cataloger/generic/cataloger_test.go | 25 + .../gentoo/parse_portage_contents.go | 2 +- syft/pkg/cataloger/githubactions/package.go | 9 +- .../githubactions/parse_composite_action.go | 18 +- .../parse_composite_action_test.go | 7 + .../cataloger/githubactions/parse_workflow.go | 35 +- .../githubactions/parse_workflow_test.go | 14 + .../corrupt/composite-action.yaml | 13 + .../corrupt/workflow-multi-job.yaml | 16 + syft/pkg/cataloger/golang/parse_go_binary.go | 6 +- .../pkg/cataloger/golang/parse_go_mod_test.go | 8 + syft/pkg/cataloger/golang/scan_binary.go | 23 +- .../golang/test-fixtures/corrupt/go.mod | 11 + .../golang/test-fixtures/corrupt/go.sum | 4 + .../pkg/cataloger/haskell/parse_stack_lock.go | 5 +- .../haskell/parse_stack_lock_test.go | 7 + .../pkg/cataloger/haskell/parse_stack_yaml.go | 5 +- .../haskell/parse_stack_yaml_test.go | 7 + .../haskell/test-fixtures/corrupt/stack.yaml | 6 + .../test-fixtures/corrupt/stack.yaml.lock | 8 + .../internal/pkgtest/test_generic_parser.go | 15 +- syft/pkg/cataloger/java/archive_parser.go | 25 +- .../pkg/cataloger/java/archive_parser_test.go | 18 +- syft/pkg/cataloger/java/maven_resolver.go | 2 +- syft/pkg/cataloger/java/parse_pom_xml.go | 5 +- syft/pkg/cataloger/java/parse_pom_xml_test.go | 8 + .../java/tar_wrapped_archive_parser_test.go | 9 + .../java/test-fixtures/corrupt/example.jar | 1 + .../java/test-fixtures/corrupt/example.tar | 1 + .../java/test-fixtures/corrupt/pom.xml | 1 + .../javascript/parse_package_json.go | 12 +- .../javascript/parse_package_json_test.go | 20 +- .../javascript/parse_package_lock.go | 3 +- .../javascript/parse_package_lock_test.go | 8 + .../cataloger/javascript/parse_pnpm_lock.go | 3 +- .../javascript/parse_pnpm_lock_test.go | 7 + .../cataloger/javascript/parse_yarn_lock.go | 3 +- .../test-fixtures/corrupt/package-lock.json | 4 + .../test-fixtures/corrupt/package.json | 5 + .../test-fixtures/corrupt/pnpm-lock.yaml | 7 + syft/pkg/cataloger/kernel/cataloger.go | 7 +- syft/pkg/cataloger/lua/parse_rockspec.go | 3 +- syft/pkg/cataloger/lua/parse_rockspec_test.go | 7 + .../corrupt/bad-1.23.0-0.rockspec | 5 + syft/pkg/cataloger/php/parse_composer_lock.go | 3 +- .../cataloger/php/parse_composer_lock_test.go | 7 + .../pkg/cataloger/php/parse_installed_json.go | 3 +- .../php/parse_installed_json_test.go | 7 + .../php/parse_pecl_serialized_test.go | 7 + .../python/parse_pipfile_lock_test.go | 7 + .../pkg/cataloger/python/parse_poetry_lock.go | 3 +- .../python/parse_poetry_lock_test.go | 7 + .../cataloger/python/parse_requirements.go | 6 +- .../python/parse_requirements_test.go | 8 + .../redhat/parse_rpm_archive_test.go | 7 + syft/pkg/cataloger/redhat/parse_rpm_db.go | 20 +- .../pkg/cataloger/redhat/parse_rpm_db_test.go | 7 + .../cataloger/redhat/parse_rpm_manifest.go | 3 +- syft/pkg/cataloger/ruby/parse_gemfile_lock.go | 3 +- syft/pkg/cataloger/rust/cataloger_test.go | 7 + syft/pkg/cataloger/rust/parse_audit_binary.go | 16 +- syft/pkg/cataloger/rust/parse_cargo_lock.go | 3 +- .../cataloger/rust/parse_cargo_lock_test.go | 7 + syft/pkg/cataloger/sbom/cataloger_test.go | 7 + .../cataloger/swift/parse_package_resolved.go | 5 +- .../swift/parse_package_resolved_test.go | 7 + .../pkg/cataloger/swift/parse_podfile_lock.go | 3 +- .../swift/parse_podfile_lock_test.go | 7 + syft/sbom/sbom.go | 4 + .../test-fixtures/image-unknowns/Dockerfile | 3 + test/cli/test-fixtures/image-unknowns/exe | 0 .../image-unknowns/executable-script | 2 + .../image-unknowns/package-lock.json | 3 + .../image-unknowns/unextracted.tar.gz | 0 .../image-unknowns/unextracted.zip | 0 .../image-unknowns/unknown-readable.jar | Bin 0 -> 209 bytes .../image-unknowns/unknown-unreadable.jar | 0 test/cli/unknowns_test.go | 39 + test/cli/utils_test.go | 27 +- 145 files changed, 4420 insertions(+), 233 deletions(-) create mode 100644 cmd/syft/internal/options/unknowns.go create mode 100644 internal/task/unknowns_tasks.go create mode 100644 internal/unknown/coordinate_error.go create mode 100644 internal/unknown/coordinate_error_test.go create mode 100644 schema/json/schema-16.0.18.json create mode 100644 syft/cataloging/unknowns.go create mode 100644 syft/pkg/cataloger/alpine/test-fixtures/corrupt/lib/apk/db/installed create mode 100644 syft/pkg/cataloger/arch/test-fixtures/installed/var/lib/pacman/local/corrupt-0.2.1-3/desc create mode 100644 syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/elfsrc/hello_world.cpp create mode 100644 syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/elfsrc/hello_world.h create mode 100644 syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/elfsrc/makefile create mode 100644 syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/elfsrc/testbin.cpp create mode 100644 syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/makefile create mode 100644 syft/pkg/cataloger/cpp/test-fixtures/corrupt/conan.lock create mode 100644 syft/pkg/cataloger/dart/test-fixtures/corrupt/pubspec.lock create mode 100644 syft/pkg/cataloger/debian/test-fixtures/var/lib/dpkg/status.d/corrupt create mode 100644 syft/pkg/cataloger/erlang/test-fixtures/corrupt/rabbitmq.app create mode 100644 syft/pkg/cataloger/erlang/test-fixtures/corrupt/rebar.lock create mode 100644 syft/pkg/cataloger/githubactions/test-fixtures/corrupt/composite-action.yaml create mode 100644 syft/pkg/cataloger/githubactions/test-fixtures/corrupt/workflow-multi-job.yaml create mode 100644 syft/pkg/cataloger/golang/test-fixtures/corrupt/go.mod create mode 100644 syft/pkg/cataloger/golang/test-fixtures/corrupt/go.sum create mode 100644 syft/pkg/cataloger/haskell/test-fixtures/corrupt/stack.yaml create mode 100644 syft/pkg/cataloger/haskell/test-fixtures/corrupt/stack.yaml.lock create mode 100644 syft/pkg/cataloger/java/test-fixtures/corrupt/example.jar create mode 100644 syft/pkg/cataloger/java/test-fixtures/corrupt/example.tar create mode 100644 syft/pkg/cataloger/java/test-fixtures/corrupt/pom.xml create mode 100644 syft/pkg/cataloger/javascript/test-fixtures/corrupt/package-lock.json create mode 100644 syft/pkg/cataloger/javascript/test-fixtures/corrupt/package.json create mode 100644 syft/pkg/cataloger/javascript/test-fixtures/corrupt/pnpm-lock.yaml create mode 100644 syft/pkg/cataloger/lua/test-fixtures/corrupt/bad-1.23.0-0.rockspec create mode 100644 test/cli/test-fixtures/image-unknowns/Dockerfile create mode 100644 test/cli/test-fixtures/image-unknowns/exe create mode 100755 test/cli/test-fixtures/image-unknowns/executable-script create mode 100644 test/cli/test-fixtures/image-unknowns/package-lock.json create mode 100644 test/cli/test-fixtures/image-unknowns/unextracted.tar.gz create mode 100644 test/cli/test-fixtures/image-unknowns/unextracted.zip create mode 100644 test/cli/test-fixtures/image-unknowns/unknown-readable.jar create mode 100644 test/cli/test-fixtures/image-unknowns/unknown-unreadable.jar create mode 100644 test/cli/unknowns_test.go diff --git a/cmd/syft/internal/options/catalog.go b/cmd/syft/internal/options/catalog.go index e692f546c..c7e0e4f6d 100644 --- a/cmd/syft/internal/options/catalog.go +++ b/cmd/syft/internal/options/catalog.go @@ -53,6 +53,9 @@ type Catalog struct { Platform string `yaml:"platform" json:"platform" mapstructure:"platform"` Source sourceConfig `yaml:"source" json:"source" mapstructure:"source"` Exclusions []string `yaml:"exclude" json:"exclude" mapstructure:"exclude"` + + // configuration for inclusion of unknown information within elements + Unknowns unknownsConfig `yaml:"unknowns" mapstructure:"unknowns"` } var _ interface { @@ -71,6 +74,7 @@ func DefaultCatalog() Catalog { Java: defaultJavaConfig(), File: defaultFileConfig(), Relationships: defaultRelationshipsConfig(), + Unknowns: defaultUnknowns(), Source: defaultSourceConfig(), Parallelism: 1, } @@ -82,6 +86,7 @@ func (cfg Catalog) ToSBOMConfig(id clio.Identification) *syft.CreateSBOMConfig { WithParallelism(cfg.Parallelism). WithRelationshipsConfig(cfg.ToRelationshipsConfig()). WithComplianceConfig(cfg.ToComplianceConfig()). + WithUnknownsConfig(cfg.ToUnknownsConfig()). WithSearchConfig(cfg.ToSearchConfig()). WithPackagesConfig(cfg.ToPackagesConfig()). WithFilesConfig(cfg.ToFilesConfig()). @@ -114,6 +119,13 @@ func (cfg Catalog) ToComplianceConfig() cataloging.ComplianceConfig { } } +func (cfg Catalog) ToUnknownsConfig() cataloging.UnknownsConfig { + return cataloging.UnknownsConfig{ + IncludeExecutablesWithoutPackages: cfg.Unknowns.ExecutablesWithoutPackages, + IncludeUnexpandedArchives: cfg.Unknowns.UnexpandedArchives, + } +} + func (cfg Catalog) ToFilesConfig() filecataloging.Config { hashers, err := intFile.Hashers(cfg.File.Metadata.Digests...) if err != nil { diff --git a/cmd/syft/internal/options/unknowns.go b/cmd/syft/internal/options/unknowns.go new file mode 100644 index 000000000..e26694902 --- /dev/null +++ b/cmd/syft/internal/options/unknowns.go @@ -0,0 +1,31 @@ +package options + +import ( + "github.com/anchore/clio" + "github.com/anchore/syft/syft/cataloging" +) + +type unknownsConfig struct { + RemoveWhenPackagesDefined bool `json:"remove-when-packages-defined" yaml:"remove-when-packages-defined" mapstructure:"remove-when-packages-defined"` + ExecutablesWithoutPackages bool `json:"executables-without-packages" yaml:"executables-without-packages" mapstructure:"executables-without-packages"` + UnexpandedArchives bool `json:"unexpanded-archives" yaml:"unexpanded-archives" mapstructure:"unexpanded-archives"` +} + +var _ interface { + clio.FieldDescriber +} = (*unknownsConfig)(nil) + +func (o *unknownsConfig) DescribeFields(descriptions clio.FieldDescriptionSet) { + descriptions.Add(&o.RemoveWhenPackagesDefined, `remove unknown errors on files with discovered packages`) + descriptions.Add(&o.ExecutablesWithoutPackages, `include executables without any identified packages`) + descriptions.Add(&o.UnexpandedArchives, `include archives which were not expanded and searched`) +} + +func defaultUnknowns() unknownsConfig { + def := cataloging.DefaultUnknownsConfig() + return unknownsConfig{ + RemoveWhenPackagesDefined: def.RemoveWhenPackagesDefined, + ExecutablesWithoutPackages: def.IncludeExecutablesWithoutPackages, + UnexpandedArchives: def.IncludeUnexpandedArchives, + } +} diff --git a/internal/constants.go b/internal/constants.go index e21291830..4dd27cf79 100644 --- a/internal/constants.go +++ b/internal/constants.go @@ -3,5 +3,5 @@ package internal const ( // JSONSchemaVersion is the current schema version output by the JSON encoder // This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment. - JSONSchemaVersion = "16.0.17" + JSONSchemaVersion = "16.0.18" ) diff --git a/internal/file/zip_file_manifest.go b/internal/file/zip_file_manifest.go index 6306ca6b0..ac61e6ae9 100644 --- a/internal/file/zip_file_manifest.go +++ b/internal/file/zip_file_manifest.go @@ -1,7 +1,6 @@ package file import ( - "fmt" "os" "sort" "strings" @@ -19,12 +18,13 @@ func NewZipFileManifest(archivePath string) (ZipFileManifest, error) { zipReader, err := OpenZip(archivePath) manifest := make(ZipFileManifest) if err != nil { - return manifest, fmt.Errorf("unable to open zip archive (%s): %w", archivePath, err) + log.Debugf("unable to open zip archive (%s): %v", archivePath, err) + return manifest, err } defer func() { err = zipReader.Close() if err != nil { - log.Warnf("unable to close zip archive (%s): %+v", archivePath, err) + log.Debugf("unable to close zip archive (%s): %+v", archivePath, err) } }() diff --git a/internal/file/zip_read_closer.go b/internal/file/zip_read_closer.go index 4c0f523e7..fd45f52a1 100644 --- a/internal/file/zip_read_closer.go +++ b/internal/file/zip_read_closer.go @@ -8,6 +8,8 @@ import ( "io" "math" "os" + + "github.com/anchore/syft/internal/log" ) // directoryEndLen, readByf, directoryEnd, and findSignatureInBlock were copied from the golang stdlib, specifically: @@ -46,7 +48,8 @@ func OpenZip(filepath string) (*ZipReadCloser, error) { // need to find the start of the archive and keep track of this offset. offset, err := findArchiveStartOffset(f, fi.Size()) if err != nil { - return nil, fmt.Errorf("cannot find beginning of zip archive=%q : %w", filepath, err) + log.Debugf("cannot find beginning of zip archive=%q : %v", filepath, err) + return nil, err } if _, err := f.Seek(0, io.SeekStart); err != nil { @@ -62,7 +65,8 @@ func OpenZip(filepath string) (*ZipReadCloser, error) { r, err := zip.NewReader(io.NewSectionReader(f, offset64, size), size) if err != nil { - return nil, fmt.Errorf("unable to open ZipReadCloser @ %q: %w", filepath, err) + log.Debugf("unable to open ZipReadCloser @ %q: %v", filepath, err) + return nil, err } return &ZipReadCloser{ diff --git a/internal/task/executor.go b/internal/task/executor.go index 899796424..0d8754b9d 100644 --- a/internal/task/executor.go +++ b/internal/task/executor.go @@ -11,8 +11,10 @@ import ( "github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/sbomsync" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/event/monitor" "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/sbom" ) type Executor struct { @@ -35,6 +37,12 @@ func NewTaskExecutor(tasks []Task, numWorkers int) *Executor { } func (p *Executor) Execute(ctx context.Context, resolver file.Resolver, s sbomsync.Builder, prog *monitor.CatalogerTaskProgress) error { + var lock sync.Mutex + withLock := func(fn func()) { + lock.Lock() + defer lock.Unlock() + fn() + } var errs error wg := &sync.WaitGroup{} for i := 0; i < p.numWorkers; i++ { @@ -48,9 +56,16 @@ func (p *Executor) Execute(ctx context.Context, resolver file.Resolver, s sbomsy return } - if err := runTaskSafely(ctx, tsk, resolver, s); err != nil { - errs = multierror.Append(errs, fmt.Errorf("failed to run task: %w", err)) - prog.SetError(err) + err := runTaskSafely(ctx, tsk, resolver, s) + unknowns, err := unknown.ExtractCoordinateErrors(err) + if len(unknowns) > 0 { + appendUnknowns(s, tsk.Name(), unknowns) + } + if err != nil { + withLock(func() { + errs = multierror.Append(errs, fmt.Errorf("failed to run task: %w", err)) + prog.SetError(err) + }) } prog.Increment() } @@ -62,6 +77,19 @@ func (p *Executor) Execute(ctx context.Context, resolver file.Resolver, s sbomsy return errs } +func appendUnknowns(builder sbomsync.Builder, taskName string, unknowns []unknown.CoordinateError) { + if accessor, ok := builder.(sbomsync.Accessor); ok { + accessor.WriteToSBOM(func(sb *sbom.SBOM) { + for _, u := range unknowns { + if sb.Artifacts.Unknowns == nil { + sb.Artifacts.Unknowns = map[file.Coordinates][]string{} + } + sb.Artifacts.Unknowns[u.Coordinates] = append(sb.Artifacts.Unknowns[u.Coordinates], formatUnknown(u.Reason.Error(), taskName)) + } + }) + } +} + func runTaskSafely(ctx context.Context, t Task, resolver file.Resolver, s sbomsync.Builder) (err error) { // handle individual cataloger panics defer func() { diff --git a/internal/task/file_tasks.go b/internal/task/file_tasks.go index 5369db327..5b6f7bbd4 100644 --- a/internal/task/file_tasks.go +++ b/internal/task/file_tasks.go @@ -3,7 +3,6 @@ package task import ( "context" "crypto" - "fmt" "github.com/anchore/syft/internal/sbomsync" "github.com/anchore/syft/syft/artifact" @@ -32,15 +31,12 @@ func NewFileDigestCatalogerTask(selection file.Selection, hashers ...crypto.Hash } result, err := digestsCataloger.Catalog(ctx, resolver, coordinates...) - if err != nil { - return fmt.Errorf("unable to catalog file digests: %w", err) - } accessor.WriteToSBOM(func(sbom *sbom.SBOM) { sbom.Artifacts.FileDigests = result }) - return nil + return err } return NewTask("file-digest-cataloger", fn) @@ -62,15 +58,12 @@ func NewFileMetadataCatalogerTask(selection file.Selection) Task { } result, err := metadataCataloger.Catalog(ctx, resolver, coordinates...) - if err != nil { - return err - } accessor.WriteToSBOM(func(sbom *sbom.SBOM) { sbom.Artifacts.FileMetadata = result }) - return nil + return err } return NewTask("file-metadata-cataloger", fn) @@ -87,15 +80,12 @@ func NewFileContentCatalogerTask(cfg filecontent.Config) Task { accessor := builder.(sbomsync.Accessor) result, err := cat.Catalog(ctx, resolver) - if err != nil { - return err - } accessor.WriteToSBOM(func(sbom *sbom.SBOM) { sbom.Artifacts.FileContents = result }) - return nil + return err } return NewTask("file-content-cataloger", fn) @@ -112,15 +102,12 @@ func NewExecutableCatalogerTask(selection file.Selection, cfg executable.Config) accessor := builder.(sbomsync.Accessor) result, err := cat.Catalog(resolver) - if err != nil { - return err - } accessor.WriteToSBOM(func(sbom *sbom.SBOM) { sbom.Artifacts.Executables = result }) - return nil + return err } return NewTask("file-executable-cataloger", fn) diff --git a/internal/task/package_task_factory.go b/internal/task/package_task_factory.go index 4a86aed12..5a65a29f0 100644 --- a/internal/task/package_task_factory.go +++ b/internal/task/package_task_factory.go @@ -103,9 +103,6 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string t := bus.StartCatalogerTask(info, -1, "") pkgs, relationships, err := c.Catalog(ctx, resolver) - if err != nil { - return fmt.Errorf("unable to catalog packages with %q: %w", catalogerName, err) - } log.WithFields("cataloger", catalogerName).Debugf("discovered %d packages", len(pkgs)) @@ -120,7 +117,7 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string t.SetCompleted() log.WithFields("name", catalogerName).Trace("package cataloger completed") - return nil + return err } tags = append(tags, pkgcataloging.PackageTag) diff --git a/internal/task/unknowns_tasks.go b/internal/task/unknowns_tasks.go new file mode 100644 index 000000000..243ba9502 --- /dev/null +++ b/internal/task/unknowns_tasks.go @@ -0,0 +1,114 @@ +package task + +import ( + "context" + "strings" + + "github.com/mholt/archiver/v3" + + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/sbomsync" + "github.com/anchore/syft/syft/cataloging" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/sbom" +) + +const unknownsLabelerTaskName = "unknowns-labeler" + +func NewUnknownsLabelerTask(cfg cataloging.UnknownsConfig) Task { + return NewTask(unknownsLabelerTaskName, unknownsLabelerTask{cfg}.processUnknowns) +} + +type unknownsLabelerTask struct { + cataloging.UnknownsConfig +} + +// processUnknowns removes unknown entries that have valid packages reported for the locations +func (c unknownsLabelerTask) processUnknowns(_ context.Context, resolver file.Resolver, builder sbomsync.Builder) error { + accessor := builder.(sbomsync.Accessor) + accessor.WriteToSBOM(func(s *sbom.SBOM) { + c.finalize(resolver, s) + }) + return nil +} + +func (c unknownsLabelerTask) finalize(resolver file.Resolver, s *sbom.SBOM) { + hasPackageReference := coordinateReferenceLookup(resolver, s) + + if c.RemoveWhenPackagesDefined { + for coords := range s.Artifacts.Unknowns { + if !hasPackageReference(coords) { + continue + } + delete(s.Artifacts.Unknowns, coords) + } + } + + if s.Artifacts.Unknowns == nil { + s.Artifacts.Unknowns = map[file.Coordinates][]string{} + } + + if c.IncludeExecutablesWithoutPackages { + for coords := range s.Artifacts.Executables { + if !hasPackageReference(coords) { + s.Artifacts.Unknowns[coords] = append(s.Artifacts.Unknowns[coords], formatUnknown("no package identified in executable file", unknownsLabelerTaskName)) + } + } + } + + if c.IncludeUnexpandedArchives { + for coords := range s.Artifacts.FileMetadata { + unarchiver, notArchiveErr := archiver.ByExtension(coords.RealPath) + if unarchiver != nil && notArchiveErr == nil && !hasPackageReference(coords) { + s.Artifacts.Unknowns[coords] = append(s.Artifacts.Unknowns[coords], "archive not cataloged") + } + } + } +} + +func formatUnknown(err string, task ...string) string { + return strings.Join(task, "/") + ": " + err +} + +func coordinateReferenceLookup(resolver file.Resolver, s *sbom.SBOM) func(coords file.Coordinates) bool { + allPackageCoords := file.NewCoordinateSet() + + // include all directly included locations that result in packages + for p := range s.Artifacts.Packages.Enumerate() { + allPackageCoords.Add(p.Locations.CoordinateSet().ToSlice()...) + } + + // include owned files, for example specified by package managers. + // relationships for these owned files may be disabled, but we always want to include them + for p := range s.Artifacts.Packages.Enumerate() { + if f, ok := p.Metadata.(pkg.FileOwner); ok { + for _, ownedFilePath := range f.OwnedFiles() { + // resolve these owned files, as they may have symlinks + // but coordinates we will test against are always absolute paths + locations, err := resolver.FilesByPath(ownedFilePath) + if err != nil { + log.Debugf("unable to resolve owned file '%s': %v", ownedFilePath, err) + } + for _, loc := range locations { + allPackageCoords.Add(loc.Coordinates) + } + } + } + } + + // include relationships + for _, r := range s.Relationships { + _, fromPkgOk := r.From.(pkg.Package) + fromFile, fromFileOk := r.From.(file.Coordinates) + _, toPkgOk := r.To.(pkg.Package) + toFile, toFileOk := r.To.(file.Coordinates) + if fromPkgOk && toFileOk { + allPackageCoords.Add(toFile) + } else if fromFileOk && toPkgOk { + allPackageCoords.Add(fromFile) + } + } + + return allPackageCoords.Contains +} diff --git a/internal/unknown/coordinate_error.go b/internal/unknown/coordinate_error.go new file mode 100644 index 000000000..46bc53e11 --- /dev/null +++ b/internal/unknown/coordinate_error.go @@ -0,0 +1,201 @@ +package unknown + +import ( + "errors" + "fmt" + "strings" + + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/syft/file" +) + +type hasCoordinates interface { + GetCoordinates() file.Coordinates +} + +type CoordinateError struct { + Coordinates file.Coordinates + Reason error +} + +var _ error = (*CoordinateError)(nil) + +func (u *CoordinateError) Error() string { + if u.Coordinates.FileSystemID == "" { + return fmt.Sprintf("%s: %v", u.Coordinates.RealPath, u.Reason) + } + return fmt.Sprintf("%s (%s): %v", u.Coordinates.RealPath, u.Coordinates.FileSystemID, u.Reason) +} + +// New returns a new CoordinateError unless the reason is a CoordinateError itself, in which case +// reason will be returned directly or if reason is nil, nil will be returned +func New(coords hasCoordinates, reason error) *CoordinateError { + if reason == nil { + return nil + } + coordinates := coords.GetCoordinates() + reasonCoordinateError := &CoordinateError{} + if errors.As(reason, &reasonCoordinateError) { + // if the reason is already a coordinate error, it is potentially for a different location, + // so we do not want to surface this location having an error + return reasonCoordinateError + } + return &CoordinateError{ + Coordinates: coordinates, + Reason: reason, + } +} + +// Newf returns a new CoordinateError with a reason of an error created from given format and args +func Newf(coords hasCoordinates, format string, args ...any) *CoordinateError { + return New(coords, fmt.Errorf(format, args...)) +} + +// Append returns an error joined to the first error/set of errors, with a new CoordinateError appended to the end +func Append(errs error, coords hasCoordinates, reason error) error { + return Join(errs, New(coords, reason)) +} + +// Appendf returns an error joined to the first error/set of errors, with a new CoordinateError appended to the end, +// created from the given reason and args +func Appendf(errs error, coords hasCoordinates, format string, args ...any) error { + return Append(errs, coords, fmt.Errorf(format, args...)) +} + +// Join joins the provided sets of errors together in a flattened manner, taking into account nested errors created +// from other sources, including errors.Join, multierror.Append, and unknown.Join +func Join(errs ...error) error { + var out []error + for _, err := range errs { + // append errors, de-duplicated + for _, e := range flatten(err) { + if containsErr(out, e) { + continue + } + out = append(out, e) + } + } + if len(out) == 1 { + return out[0] + } + if len(out) == 0 { + return nil + } + return errors.Join(out...) +} + +// Joinf joins the provided sets of errors together in a flattened manner, taking into account nested errors created +// from other sources, including errors.Join, multierror.Append, and unknown.Join and appending a new error, +// created from the format and args provided -- the error is NOT a CoordinateError +func Joinf(errs error, format string, args ...any) error { + return Join(errs, fmt.Errorf(format, args...)) +} + +// IfEmptyf returns a new Errorf-formatted error, only when the provided slice is empty or nil when +// the slice has entries +func IfEmptyf[T any](emptyTest []T, format string, args ...any) error { + if len(emptyTest) == 0 { + return fmt.Errorf(format, args...) + } + return nil +} + +// ExtractCoordinateErrors extracts all coordinate errors returned, and any _additional_ errors in the graph +// are encapsulated in the second, error return parameter +func ExtractCoordinateErrors(err error) (coordinateErrors []CoordinateError, remainingErrors error) { + remainingErrors = visitErrors(err, func(e error) error { + if coordinateError, _ := e.(*CoordinateError); coordinateError != nil { + coordinateErrors = append(coordinateErrors, *coordinateError) + return nil + } + return e + }) + return coordinateErrors, remainingErrors +} + +func flatten(errs ...error) []error { + var out []error + for _, err := range errs { + if err == nil { + continue + } + // turn all errors nested under a coordinate error to individual coordinate errors + if e, ok := err.(*CoordinateError); ok { + if e == nil { + continue + } + for _, r := range flatten(e.Reason) { + out = append(out, New(e.Coordinates, r)) + } + } else + // from multierror.Append + if e, ok := err.(interface{ WrappedErrors() []error }); ok { + if e == nil { + continue + } + out = append(out, flatten(e.WrappedErrors()...)...) + } else + // from errors.Join + if e, ok := err.(interface{ Unwrap() []error }); ok { + if e == nil { + continue + } + out = append(out, flatten(e.Unwrap()...)...) + } else { + out = append(out, err) + } + } + return out +} + +// containsErr returns true if a duplicate error is found +func containsErr(out []error, err error) bool { + defer func() { + if err := recover(); err != nil { + log.Tracef("error comparing errors: %v", err) + } + }() + for _, e := range out { + if e == err { + return true + } + } + return false +} + +// visitErrors visits every wrapped error. the returned error replaces the provided error, null errors are omitted from +// the object graph +func visitErrors(err error, fn func(error) error) error { + // unwrap errors from errors.Join + if errs, ok := err.(interface{ Unwrap() []error }); ok { + var out []error + for _, e := range errs.Unwrap() { + out = append(out, visitErrors(e, fn)) + } + // errors.Join omits nil errors and will return nil if all passed errors are nil + return errors.Join(out...) + } + // unwrap errors from multierror.Append -- these also implement Unwrap() error, so check this first + if errs, ok := err.(interface{ WrappedErrors() []error }); ok { + var out []error + for _, e := range errs.WrappedErrors() { + out = append(out, visitErrors(e, fn)) + } + // errors.Join omits nil errors and will return nil if all passed errors are nil + return errors.Join(out...) + } + // unwrap singly wrapped errors + if e, ok := err.(interface{ Unwrap() error }); ok { + wrapped := e.Unwrap() + got := visitErrors(wrapped, fn) + if got == nil { + return nil + } + if wrapped.Error() != got.Error() { + prefix := strings.TrimSuffix(err.Error(), wrapped.Error()) + return fmt.Errorf("%s%w", prefix, got) + } + return err + } + return fn(err) +} diff --git a/internal/unknown/coordinate_error_test.go b/internal/unknown/coordinate_error_test.go new file mode 100644 index 000000000..27c53a5ff --- /dev/null +++ b/internal/unknown/coordinate_error_test.go @@ -0,0 +1,236 @@ +package unknown + +import ( + "errors" + "fmt" + "strings" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/anchore/syft/syft/file" +) + +func Test_visitErrors(t *testing.T) { + tests := []struct { + name string + in error + transform func(error) error + expected string + }{ + { + name: "return", + in: fmt.Errorf("err1"), + transform: func(e error) error { + return e + }, + expected: "err1", + }, + { + name: "omit", + in: fmt.Errorf("err1"), + transform: func(_ error) error { + return nil + }, + expected: "", + }, + { + name: "wrapped return", + in: fmt.Errorf("wrapped: %w", fmt.Errorf("err1")), + transform: func(e error) error { + return e + }, + expected: "wrapped: err1", + }, + { + name: "wrapped omit", + in: fmt.Errorf("wrapped: %w", fmt.Errorf("err1")), + transform: func(e error) error { + if e.Error() == "err1" { + return nil + } + return e + }, + expected: "", + }, + { + name: "joined return", + in: errors.Join(fmt.Errorf("err1"), fmt.Errorf("err2")), + transform: func(e error) error { + return e + }, + expected: "err1\nerr2", + }, + { + name: "joined omit", + in: errors.Join(fmt.Errorf("err1"), fmt.Errorf("err2")), + transform: func(_ error) error { + return nil + }, + expected: "", + }, + { + name: "joined omit first", + in: errors.Join(fmt.Errorf("err1"), fmt.Errorf("err2")), + transform: func(e error) error { + if e.Error() == "err1" { + return nil + } + return e + }, + expected: "err2", + }, + { + name: "joined wrapped return", + in: errors.Join(fmt.Errorf("wrapped: %w", fmt.Errorf("err1")), fmt.Errorf("err2")), + transform: func(e error) error { + return e + }, + expected: "wrapped: err1\nerr2", + }, + { + name: "joined wrapped omit first", + in: errors.Join(fmt.Errorf("wrapped: %w", fmt.Errorf("err1")), fmt.Errorf("err2")), + transform: func(e error) error { + if e.Error() == "err1" { + return nil + } + return e + }, + expected: "err2", + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + gotErr := visitErrors(test.in, test.transform) + got := fmt.Sprintf("%v", gotErr) + require.Equal(t, test.expected, got) + }) + } +} + +func Test_Join(t *testing.T) { + err1 := fmt.Errorf("err1") + err2 := fmt.Errorf("err2") + + tests := []struct { + name string `` + in []error + expected string + }{ + { + name: "basic", + in: []error{fmt.Errorf("err")}, + expected: "err", + }, + { + name: "wrapped", + in: []error{fmt.Errorf("outer: %w", fmt.Errorf("err"))}, + expected: "outer: err", + }, + { + name: "wrapped joined", + in: []error{errors.Join(fmt.Errorf("outer: %w", fmt.Errorf("err1")), fmt.Errorf("err2"))}, + expected: "outer: err1\nerr2", + }, + { + name: "duplicates", + in: []error{err1, err1, err2}, + expected: "err1\nerr2", + }, + { + name: "nested duplicates", + in: []error{errors.Join(err1, err2), err1, err2}, + expected: "err1\nerr2", + }, + { + name: "nested duplicates coords", + in: []error{New(file.NewLocation("l1"), errors.Join(fmt.Errorf("err1"), fmt.Errorf("err2"))), fmt.Errorf("err1"), fmt.Errorf("err2")}, + expected: "l1: err1\nl1: err2\nerr1\nerr2", + }, + { + name: "all nil", + in: []error{nil, nil, nil}, + expected: "", + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got := Join(test.in...) + if test.expected == "" { + require.Nil(t, got) + return + } + require.NotNil(t, got) + require.Equal(t, test.expected, got.Error()) + }) + } +} + +func Test_flatten(t *testing.T) { + coords := file.Coordinates{ + RealPath: "real/path", + } + e1 := fmt.Errorf("e1") + e2 := fmt.Errorf("e2") + c1 := New(coords, fmt.Errorf("c1")) + c2 := New(coords, fmt.Errorf("c2")) + tests := []struct { + name string `` + in error + expected string + }{ + { + name: "basic", + in: errors.Join(e1, e2), + expected: "e1//e2", + }, + { + name: "coords", + in: New(coords, e1), + expected: "real/path: e1", + }, + { + name: "coords with joined children", + in: New(coords, errors.Join(e1, e2)), + expected: "real/path: e1//real/path: e2", + }, + { + name: "very nested", + in: errors.Join(errors.Join(errors.Join(errors.Join(e1, c1), e2), c2), e2), + expected: "e1//real/path: c1//e2//real/path: c2//e2", + }, + } + toString := func(errs ...error) string { + var parts []string + for _, e := range errs { + parts = append(parts, e.Error()) + } + return strings.Join(parts, "//") + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got := flatten(test.in) + require.NotNil(t, got) + require.Equal(t, test.expected, toString(got...)) + }) + } +} + +func Test_Append(t *testing.T) { + e1 := New(file.NewLocation("l1"), fmt.Errorf("e1")) + e2 := Append(e1, file.NewLocation("l2"), fmt.Errorf("e2")) + e3 := Appendf(e2, file.NewLocation("l3"), "%s", "e3") + require.Equal(t, "l1: e1\nl2: e2\nl3: e3", e3.Error()) + + e1 = New(file.NewLocation("l1"), nil) + require.Nil(t, e1) + e2 = Append(e1, file.NewLocation("l2"), fmt.Errorf("e2")) + e3 = Appendf(e2, file.NewLocation("l3"), "%s", "e3") + require.Equal(t, "l2: e2\nl3: e3", e3.Error()) + + e1 = New(file.NewLocation("l1"), fmt.Errorf("e1")) + e2 = Append(e1, file.NewLocation("l2"), nil) + e3 = Appendf(e2, file.NewLocation("l3"), "%s", "e3") + require.Equal(t, "l1: e1\nl3: e3", e3.Error()) +} diff --git a/schema/json/schema-16.0.18.json b/schema/json/schema-16.0.18.json new file mode 100644 index 000000000..936582e2d --- /dev/null +++ b/schema/json/schema-16.0.18.json @@ -0,0 +1,2727 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "anchore.io/schema/syft/json/16.0.18/document", + "$ref": "#/$defs/Document", + "$defs": { + "AlpmDbEntry": { + "properties": { + "basepackage": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "packager": { + "type": "string" + }, + "url": { + "type": "string" + }, + "validation": { + "type": "string" + }, + "reason": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "backup": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "basepackage", + "package", + "version", + "description", + "architecture", + "size", + "packager", + "url", + "validation", + "reason", + "files", + "backup" + ] + }, + "AlpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "type": { + "type": "string" + }, + "uid": { + "type": "string" + }, + "gid": { + "type": "string" + }, + "time": { + "type": "string", + "format": "date-time" + }, + "size": { + "type": "string" + }, + "link": { + "type": "string" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object" + }, + "ApkDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "originPackage": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "version": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "url": { + "type": "string" + }, + "description": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "installedSize": { + "type": "integer" + }, + "pullDependencies": { + "items": { + "type": "string" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "pullChecksum": { + "type": "string" + }, + "gitCommitOfApkPort": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/ApkFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "originPackage", + "maintainer", + "version", + "architecture", + "url", + "description", + "size", + "installedSize", + "pullDependencies", + "provides", + "pullChecksum", + "gitCommitOfApkPort", + "files" + ] + }, + "ApkFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "ownerUid": { + "type": "string" + }, + "ownerGid": { + "type": "string" + }, + "permissions": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "BinarySignature": { + "properties": { + "matches": { + "items": { + "$ref": "#/$defs/ClassifierMatch" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "matches" + ] + }, + "CConanFileEntry": { + "properties": { + "ref": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanInfoEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "build_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "py_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "options": { + "$ref": "#/$defs/KeyValues" + }, + "path": { + "type": "string" + }, + "context": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockV2Entry": { + "properties": { + "ref": { + "type": "string" + }, + "packageID": { + "type": "string" + }, + "username": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "recipeRevision": { + "type": "string" + }, + "packageRevision": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CPE": { + "properties": { + "cpe": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "cpe" + ] + }, + "ClassifierMatch": { + "properties": { + "classifier": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Location" + } + }, + "type": "object", + "required": [ + "classifier", + "location" + ] + }, + "CocoaPodfileLockEntry": { + "properties": { + "checksum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "checksum" + ] + }, + "Coordinates": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "DartPubspecLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hosted_url": { + "type": "string" + }, + "vcs_url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Descriptor": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "configuration": true + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Digest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "Document": { + "properties": { + "artifacts": { + "items": { + "$ref": "#/$defs/Package" + }, + "type": "array" + }, + "artifactRelationships": { + "items": { + "$ref": "#/$defs/Relationship" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/File" + }, + "type": "array" + }, + "source": { + "$ref": "#/$defs/Source" + }, + "distro": { + "$ref": "#/$defs/LinuxRelease" + }, + "descriptor": { + "$ref": "#/$defs/Descriptor" + }, + "schema": { + "$ref": "#/$defs/Schema" + } + }, + "type": "object", + "required": [ + "artifacts", + "artifactRelationships", + "source", + "distro", + "descriptor", + "schema" + ] + }, + "DotnetDepsEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "path": { + "type": "string" + }, + "sha512": { + "type": "string" + }, + "hashPath": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "path", + "sha512", + "hashPath" + ] + }, + "DotnetPortableExecutableEntry": { + "properties": { + "assemblyVersion": { + "type": "string" + }, + "legalCopyright": { + "type": "string" + }, + "comments": { + "type": "string" + }, + "internalName": { + "type": "string" + }, + "companyName": { + "type": "string" + }, + "productName": { + "type": "string" + }, + "productVersion": { + "type": "string" + } + }, + "type": "object", + "required": [ + "assemblyVersion", + "legalCopyright", + "companyName", + "productName", + "productVersion" + ] + }, + "DpkgDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ] + }, + "DpkgFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "isConfigFile": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "path", + "isConfigFile" + ] + }, + "ELFSecurityFeatures": { + "properties": { + "symbolTableStripped": { + "type": "boolean" + }, + "stackCanary": { + "type": "boolean" + }, + "nx": { + "type": "boolean" + }, + "relRO": { + "type": "string" + }, + "pie": { + "type": "boolean" + }, + "dso": { + "type": "boolean" + }, + "safeStack": { + "type": "boolean" + }, + "cfi": { + "type": "boolean" + }, + "fortify": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "symbolTableStripped", + "nx", + "relRO", + "pie", + "dso" + ] + }, + "ElfBinaryPackageNoteJsonPayload": { + "properties": { + "type": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "osCPE": { + "type": "string" + }, + "os": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "system": { + "type": "string" + }, + "vendor": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "commit": { + "type": "string" + } + }, + "type": "object" + }, + "ElixirMixLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "ErlangRebarLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "Executable": { + "properties": { + "format": { + "type": "string" + }, + "hasExports": { + "type": "boolean" + }, + "hasEntrypoint": { + "type": "boolean" + }, + "importedLibraries": { + "items": { + "type": "string" + }, + "type": "array" + }, + "elfSecurityFeatures": { + "$ref": "#/$defs/ELFSecurityFeatures" + } + }, + "type": "object", + "required": [ + "format", + "hasExports", + "hasEntrypoint", + "importedLibraries" + ] + }, + "File": { + "properties": { + "id": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Coordinates" + }, + "metadata": { + "$ref": "#/$defs/FileMetadataEntry" + }, + "contents": { + "type": "string" + }, + "digests": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/FileLicense" + }, + "type": "array" + }, + "executable": { + "$ref": "#/$defs/Executable" + }, + "unknowns": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "id", + "location" + ] + }, + "FileLicense": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "evidence": { + "$ref": "#/$defs/FileLicenseEvidence" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type" + ] + }, + "FileLicenseEvidence": { + "properties": { + "confidence": { + "type": "integer" + }, + "offset": { + "type": "integer" + }, + "extent": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "confidence", + "offset", + "extent" + ] + }, + "FileMetadataEntry": { + "properties": { + "mode": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "linkDestination": { + "type": "string" + }, + "userID": { + "type": "integer" + }, + "groupID": { + "type": "integer" + }, + "mimeType": { + "type": "string" + }, + "size": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "mode", + "type", + "userID", + "groupID", + "mimeType", + "size" + ] + }, + "GoModuleBuildinfoEntry": { + "properties": { + "goBuildSettings": { + "$ref": "#/$defs/KeyValues" + }, + "goCompiledVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "h1Digest": { + "type": "string" + }, + "mainModule": { + "type": "string" + }, + "goCryptoSettings": { + "items": { + "type": "string" + }, + "type": "array" + }, + "goExperiments": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "goCompiledVersion", + "architecture" + ] + }, + "GoModuleEntry": { + "properties": { + "h1Digest": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackEntry": { + "properties": { + "pkgHash": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackLockEntry": { + "properties": { + "pkgHash": { + "type": "string" + }, + "snapshotURL": { + "type": "string" + } + }, + "type": "object" + }, + "IDLikes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "JavaArchive": { + "properties": { + "virtualPath": { + "type": "string" + }, + "manifest": { + "$ref": "#/$defs/JavaManifest" + }, + "pomProperties": { + "$ref": "#/$defs/JavaPomProperties" + }, + "pomProject": { + "$ref": "#/$defs/JavaPomProject" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "virtualPath" + ] + }, + "JavaJvmInstallation": { + "properties": { + "release": { + "$ref": "#/$defs/JavaVMRelease" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "release", + "files" + ] + }, + "JavaManifest": { + "properties": { + "main": { + "$ref": "#/$defs/KeyValues" + }, + "sections": { + "items": { + "$ref": "#/$defs/KeyValues" + }, + "type": "array" + } + }, + "type": "object" + }, + "JavaPomParent": { + "properties": { + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object", + "required": [ + "groupId", + "artifactId", + "version" + ] + }, + "JavaPomProject": { + "properties": { + "path": { + "type": "string" + }, + "parent": { + "$ref": "#/$defs/JavaPomParent" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "groupId", + "artifactId", + "version", + "name" + ] + }, + "JavaPomProperties": { + "properties": { + "path": { + "type": "string" + }, + "name": { + "type": "string" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "extraFields": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "name", + "groupId", + "artifactId", + "version" + ] + }, + "JavaVMRelease": { + "properties": { + "implementor": { + "type": "string" + }, + "implementorVersion": { + "type": "string" + }, + "javaRuntimeVersion": { + "type": "string" + }, + "javaVersion": { + "type": "string" + }, + "javaVersionDate": { + "type": "string" + }, + "libc": { + "type": "string" + }, + "modules": { + "items": { + "type": "string" + }, + "type": "array" + }, + "osArch": { + "type": "string" + }, + "osName": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "source": { + "type": "string" + }, + "buildSource": { + "type": "string" + }, + "buildSourceRepo": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "fullVersion": { + "type": "string" + }, + "semanticVersion": { + "type": "string" + }, + "buildInfo": { + "type": "string" + }, + "jvmVariant": { + "type": "string" + }, + "jvmVersion": { + "type": "string" + }, + "imageType": { + "type": "string" + }, + "buildType": { + "type": "string" + } + }, + "type": "object" + }, + "JavascriptNpmPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "private": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "homepage", + "description", + "url", + "private" + ] + }, + "JavascriptNpmPackageLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "JavascriptYarnLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "KeyValue": { + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "key", + "value" + ] + }, + "KeyValues": { + "items": { + "$ref": "#/$defs/KeyValue" + }, + "type": "array" + }, + "License": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "urls": { + "items": { + "type": "string" + }, + "type": "array" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type", + "urls", + "locations" + ] + }, + "LinuxKernelArchive": { + "properties": { + "name": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "version": { + "type": "string" + }, + "extendedVersion": { + "type": "string" + }, + "buildTime": { + "type": "string" + }, + "author": { + "type": "string" + }, + "format": { + "type": "string" + }, + "rwRootFS": { + "type": "boolean" + }, + "swapDevice": { + "type": "integer" + }, + "rootDevice": { + "type": "integer" + }, + "videoMode": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "architecture", + "version" + ] + }, + "LinuxKernelModule": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "path": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "license": { + "type": "string" + }, + "kernelVersion": { + "type": "string" + }, + "versionMagic": { + "type": "string" + }, + "parameters": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/LinuxKernelModuleParameter" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "LinuxKernelModuleParameter": { + "properties": { + "type": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "type": "object" + }, + "LinuxRelease": { + "properties": { + "prettyName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" + }, + "idLike": { + "$ref": "#/$defs/IDLikes" + }, + "version": { + "type": "string" + }, + "versionID": { + "type": "string" + }, + "versionCodename": { + "type": "string" + }, + "buildID": { + "type": "string" + }, + "imageID": { + "type": "string" + }, + "imageVersion": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "variantID": { + "type": "string" + }, + "homeURL": { + "type": "string" + }, + "supportURL": { + "type": "string" + }, + "bugReportURL": { + "type": "string" + }, + "privacyPolicyURL": { + "type": "string" + }, + "cpeName": { + "type": "string" + }, + "supportEnd": { + "type": "string" + } + }, + "type": "object" + }, + "Location": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + }, + "accessPath": { + "type": "string" + }, + "annotations": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "accessPath" + ] + }, + "LuarocksPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "dependencies": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "name", + "version", + "license", + "homepage", + "description", + "url", + "dependencies" + ] + }, + "MicrosoftKbPatch": { + "properties": { + "product_id": { + "type": "string" + }, + "kb": { + "type": "string" + } + }, + "type": "object", + "required": [ + "product_id", + "kb" + ] + }, + "NixStoreEntry": { + "properties": { + "outputHash": { + "type": "string" + }, + "output": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "outputHash", + "files" + ] + }, + "OpamPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "licenses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "url": { + "type": "string" + }, + "checksum": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "licenses", + "url", + "checksum", + "homepage", + "dependencies" + ] + }, + "Package": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "foundBy": { + "type": "string" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "licenses": { + "$ref": "#/$defs/licenses" + }, + "language": { + "type": "string" + }, + "cpes": { + "$ref": "#/$defs/cpes" + }, + "purl": { + "type": "string" + }, + "metadataType": { + "type": "string" + }, + "metadata": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/AlpmDbEntry" + }, + { + "$ref": "#/$defs/ApkDbEntry" + }, + { + "$ref": "#/$defs/BinarySignature" + }, + { + "$ref": "#/$defs/CConanFileEntry" + }, + { + "$ref": "#/$defs/CConanInfoEntry" + }, + { + "$ref": "#/$defs/CConanLockEntry" + }, + { + "$ref": "#/$defs/CConanLockV2Entry" + }, + { + "$ref": "#/$defs/CocoaPodfileLockEntry" + }, + { + "$ref": "#/$defs/DartPubspecLockEntry" + }, + { + "$ref": "#/$defs/DotnetDepsEntry" + }, + { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + }, + { + "$ref": "#/$defs/DpkgDbEntry" + }, + { + "$ref": "#/$defs/ElfBinaryPackageNoteJsonPayload" + }, + { + "$ref": "#/$defs/ElixirMixLockEntry" + }, + { + "$ref": "#/$defs/ErlangRebarLockEntry" + }, + { + "$ref": "#/$defs/GoModuleBuildinfoEntry" + }, + { + "$ref": "#/$defs/GoModuleEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackLockEntry" + }, + { + "$ref": "#/$defs/JavaArchive" + }, + { + "$ref": "#/$defs/JavaJvmInstallation" + }, + { + "$ref": "#/$defs/JavascriptNpmPackage" + }, + { + "$ref": "#/$defs/JavascriptNpmPackageLockEntry" + }, + { + "$ref": "#/$defs/JavascriptYarnLockEntry" + }, + { + "$ref": "#/$defs/LinuxKernelArchive" + }, + { + "$ref": "#/$defs/LinuxKernelModule" + }, + { + "$ref": "#/$defs/LuarocksPackage" + }, + { + "$ref": "#/$defs/MicrosoftKbPatch" + }, + { + "$ref": "#/$defs/NixStoreEntry" + }, + { + "$ref": "#/$defs/OpamPackage" + }, + { + "$ref": "#/$defs/PhpComposerInstalledEntry" + }, + { + "$ref": "#/$defs/PhpComposerLockEntry" + }, + { + "$ref": "#/$defs/PhpPeclEntry" + }, + { + "$ref": "#/$defs/PortageDbEntry" + }, + { + "$ref": "#/$defs/PythonPackage" + }, + { + "$ref": "#/$defs/PythonPipRequirementsEntry" + }, + { + "$ref": "#/$defs/PythonPipfileLockEntry" + }, + { + "$ref": "#/$defs/PythonPoetryLockEntry" + }, + { + "$ref": "#/$defs/RDescription" + }, + { + "$ref": "#/$defs/RpmArchive" + }, + { + "$ref": "#/$defs/RpmDbEntry" + }, + { + "$ref": "#/$defs/RubyGemspec" + }, + { + "$ref": "#/$defs/RustCargoAuditEntry" + }, + { + "$ref": "#/$defs/RustCargoLockEntry" + }, + { + "$ref": "#/$defs/SwiftPackageManagerLockEntry" + }, + { + "$ref": "#/$defs/SwiplpackPackage" + }, + { + "$ref": "#/$defs/WordpressPluginEntry" + } + ] + } + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "foundBy", + "locations", + "licenses", + "language", + "cpes", + "purl" + ] + }, + "PhpComposerAuthors": { + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name" + ] + }, + "PhpComposerExternalReference": { + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "shasum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "type", + "url", + "reference" + ] + }, + "PhpComposerInstalledEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpComposerLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpPeclEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "PortageDbEntry": { + "properties": { + "installedSize": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/PortageFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "installedSize", + "files" + ] + }, + "PortageFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonDirectURLOriginInfo": { + "properties": { + "url": { + "type": "string" + }, + "commitId": { + "type": "string" + }, + "vcs": { + "type": "string" + } + }, + "type": "object", + "required": [ + "url" + ] + }, + "PythonFileDigest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "PythonFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/PythonFileDigest" + }, + "size": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/PythonFileRecord" + }, + "type": "array" + }, + "sitePackagesRootPath": { + "type": "string" + }, + "topLevelPackages": { + "items": { + "type": "string" + }, + "type": "array" + }, + "directUrlOrigin": { + "$ref": "#/$defs/PythonDirectURLOriginInfo" + }, + "requiresPython": { + "type": "string" + }, + "requiresDist": { + "items": { + "type": "string" + }, + "type": "array" + }, + "providesExtra": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "platform", + "sitePackagesRootPath" + ] + }, + "PythonPipRequirementsEntry": { + "properties": { + "name": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + }, + "versionConstraint": { + "type": "string" + }, + "url": { + "type": "string" + }, + "markers": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "versionConstraint" + ] + }, + "PythonPipfileLockEntry": { + "properties": { + "hashes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "index": { + "type": "string" + } + }, + "type": "object", + "required": [ + "hashes", + "index" + ] + }, + "PythonPoetryLockDependencyEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "optional": { + "type": "boolean" + }, + "markers": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "optional" + ] + }, + "PythonPoetryLockEntry": { + "properties": { + "index": { + "type": "string" + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonPoetryLockDependencyEntry" + }, + "type": "array" + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonPoetryLockExtraEntry" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ] + }, + "PythonPoetryLockExtraEntry": { + "properties": { + "name": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ] + }, + "RDescription": { + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "url": { + "items": { + "type": "string" + }, + "type": "array" + }, + "repository": { + "type": "string" + }, + "built": { + "type": "string" + }, + "needsCompilation": { + "type": "boolean" + }, + "imports": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "suggests": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "Relationship": { + "properties": { + "parent": { + "type": "string" + }, + "child": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "parent", + "child", + "type" + ] + }, + "RpmArchive": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmDbEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "mode": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "userName": { + "type": "string" + }, + "groupName": { + "type": "string" + }, + "flags": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "mode", + "size", + "digest", + "userName", + "groupName", + "flags" + ] + }, + "RubyGemspec": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "RustCargoAuditEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source" + ] + }, + "RustCargoLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + }, + "checksum": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "checksum", + "dependencies" + ] + }, + "Schema": { + "properties": { + "version": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "version", + "url" + ] + }, + "Source": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "metadata" + ] + }, + "SwiftPackageManagerLockEntry": { + "properties": { + "revision": { + "type": "string" + } + }, + "type": "object", + "required": [ + "revision" + ] + }, + "SwiplpackPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "packager": { + "type": "string" + }, + "packagerEmail": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "packager", + "packagerEmail", + "homepage", + "dependencies" + ] + }, + "WordpressPluginEntry": { + "properties": { + "pluginInstallDirectory": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorUri": { + "type": "string" + } + }, + "type": "object", + "required": [ + "pluginInstallDirectory" + ] + }, + "cpes": { + "items": { + "$ref": "#/$defs/CPE" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/License" + }, + "type": "array" + } + } +} diff --git a/schema/json/schema-latest.json b/schema/json/schema-latest.json index 015c9003b..936582e2d 100644 --- a/schema/json/schema-latest.json +++ b/schema/json/schema-latest.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "anchore.io/schema/syft/json/16.0.17/document", + "$id": "anchore.io/schema/syft/json/16.0.18/document", "$ref": "#/$defs/Document", "$defs": { "AlpmDbEntry": { @@ -777,6 +777,12 @@ }, "executable": { "$ref": "#/$defs/Executable" + }, + "unknowns": { + "items": { + "type": "string" + }, + "type": "array" } }, "type": "object", diff --git a/syft/cataloging/unknowns.go b/syft/cataloging/unknowns.go new file mode 100644 index 000000000..ad3f55fea --- /dev/null +++ b/syft/cataloging/unknowns.go @@ -0,0 +1,15 @@ +package cataloging + +type UnknownsConfig struct { + RemoveWhenPackagesDefined bool + IncludeExecutablesWithoutPackages bool + IncludeUnexpandedArchives bool +} + +func DefaultUnknownsConfig() UnknownsConfig { + return UnknownsConfig{ + RemoveWhenPackagesDefined: true, + IncludeExecutablesWithoutPackages: true, + IncludeUnexpandedArchives: true, + } +} diff --git a/syft/create_sbom_config.go b/syft/create_sbom_config.go index 66c1bb339..8e9e76b5c 100644 --- a/syft/create_sbom_config.go +++ b/syft/create_sbom_config.go @@ -22,6 +22,7 @@ type CreateSBOMConfig struct { Compliance cataloging.ComplianceConfig Search cataloging.SearchConfig Relationships cataloging.RelationshipsConfig + Unknowns cataloging.UnknownsConfig DataGeneration cataloging.DataGenerationConfig Packages pkgcataloging.Config Files filecataloging.Config @@ -113,6 +114,12 @@ func (c *CreateSBOMConfig) WithRelationshipsConfig(cfg cataloging.RelationshipsC return c } +// WithUnknownsConfig allows for defining the specific behavior dealing with unknowns +func (c *CreateSBOMConfig) WithUnknownsConfig(cfg cataloging.UnknownsConfig) *CreateSBOMConfig { + c.Unknowns = cfg + return c +} + // WithDataGenerationConfig allows for defining what data elements that cannot be discovered from the underlying // target being scanned that should be generated after package creation. func (c *CreateSBOMConfig) WithDataGenerationConfig(cfg cataloging.DataGenerationConfig) *CreateSBOMConfig { @@ -173,6 +180,7 @@ func (c *CreateSBOMConfig) makeTaskGroups(src source.Description) ([][]task.Task // generate package and file tasks based on the configuration environmentTasks := c.environmentTasks() relationshipsTasks := c.relationshipTasks(src) + unknownTasks := c.unknownsTasks() fileTasks := c.fileTasks() pkgTasks, selectionEvidence, err := c.packageTasks(src) if err != nil { @@ -192,6 +200,11 @@ func (c *CreateSBOMConfig) makeTaskGroups(src source.Description) ([][]task.Task taskGroups = append(taskGroups, relationshipsTasks) } + // all unknowns tasks should happen after all scanning is complete + if len(unknownTasks) > 0 { + taskGroups = append(taskGroups, unknownTasks) + } + // identifying the environment (i.e. the linux release) must be done first as this is required for package cataloging taskGroups = append( [][]task.Task{ @@ -338,6 +351,18 @@ func (c *CreateSBOMConfig) environmentTasks() []task.Task { return tsks } +// unknownsTasks returns a set of tasks that perform any necessary post-processing +// to identify SBOM elements as unknowns +func (c *CreateSBOMConfig) unknownsTasks() []task.Task { + var tasks []task.Task + + if t := task.NewUnknownsLabelerTask(c.Unknowns); t != nil { + tasks = append(tasks, t) + } + + return tasks +} + func (c *CreateSBOMConfig) validate() error { if c.Relationships.ExcludeBinaryPackagesWithFileOwnershipOverlap { if !c.Relationships.PackageFileOwnershipOverlap { diff --git a/syft/create_sbom_config_test.go b/syft/create_sbom_config_test.go index 8c74b57cd..64a9a2a0a 100644 --- a/syft/create_sbom_config_test.go +++ b/syft/create_sbom_config_test.go @@ -90,6 +90,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { pkgCatalogerNamesWithTagOrName(t, "image"), fileCatalogerNames(true, true, true), relationshipCatalogerNames(), + unknownsTaskNames(), }, wantManifest: &catalogerManifest{ Requested: pkgcataloging.SelectionRequest{ @@ -108,6 +109,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { pkgCatalogerNamesWithTagOrName(t, "directory"), fileCatalogerNames(true, true, true), relationshipCatalogerNames(), + unknownsTaskNames(), }, wantManifest: &catalogerManifest{ Requested: pkgcataloging.SelectionRequest{ @@ -127,6 +129,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { pkgCatalogerNamesWithTagOrName(t, "directory"), fileCatalogerNames(true, true, true), relationshipCatalogerNames(), + unknownsTaskNames(), }, wantManifest: &catalogerManifest{ Requested: pkgcataloging.SelectionRequest{ @@ -145,6 +148,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { pkgCatalogerNamesWithTagOrName(t, "image"), fileCatalogerNames(false, true, true), // note: the digest cataloger is not included relationshipCatalogerNames(), + unknownsTaskNames(), }, wantManifest: &catalogerManifest{ Requested: pkgcataloging.SelectionRequest{ @@ -163,6 +167,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { pkgCatalogerNamesWithTagOrName(t, "image"), // note: there are no file catalogers in their own group relationshipCatalogerNames(), + unknownsTaskNames(), }, wantManifest: &catalogerManifest{ Requested: pkgcataloging.SelectionRequest{ @@ -184,6 +189,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { fileCatalogerNames(true, true, true)..., ), relationshipCatalogerNames(), + unknownsTaskNames(), }, wantManifest: &catalogerManifest{ Requested: pkgcataloging.SelectionRequest{ @@ -204,6 +210,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { addTo(pkgCatalogerNamesWithTagOrName(t, "image"), "persistent"), fileCatalogerNames(true, true, true), relationshipCatalogerNames(), + unknownsTaskNames(), }, wantManifest: &catalogerManifest{ Requested: pkgcataloging.SelectionRequest{ @@ -224,6 +231,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { addTo(pkgCatalogerNamesWithTagOrName(t, "directory"), "persistent"), fileCatalogerNames(true, true, true), relationshipCatalogerNames(), + unknownsTaskNames(), }, wantManifest: &catalogerManifest{ Requested: pkgcataloging.SelectionRequest{ @@ -244,6 +252,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { addTo(pkgIntersect("image", "javascript"), "persistent"), fileCatalogerNames(true, true, true), relationshipCatalogerNames(), + unknownsTaskNames(), }, wantManifest: &catalogerManifest{ Requested: pkgcataloging.SelectionRequest{ @@ -265,6 +274,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { addTo(pkgCatalogerNamesWithTagOrName(t, "image"), "user-provided"), fileCatalogerNames(true, true, true), relationshipCatalogerNames(), + unknownsTaskNames(), }, wantManifest: &catalogerManifest{ Requested: pkgcataloging.SelectionRequest{ @@ -285,6 +295,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { pkgCatalogerNamesWithTagOrName(t, "image"), fileCatalogerNames(true, true, true), relationshipCatalogerNames(), + unknownsTaskNames(), }, wantManifest: &catalogerManifest{ Requested: pkgcataloging.SelectionRequest{ @@ -385,6 +396,10 @@ func relationshipCatalogerNames() []string { return []string{"relationships-cataloger"} } +func unknownsTaskNames() []string { + return []string{"unknowns-labeler"} +} + func environmentCatalogerNames() []string { return []string{"environment-cataloger"} } diff --git a/syft/file/cataloger/executable/cataloger.go b/syft/file/cataloger/executable/cataloger.go index b0f10e15d..7de2b33b0 100644 --- a/syft/file/cataloger/executable/cataloger.go +++ b/syft/file/cataloger/executable/cataloger.go @@ -15,6 +15,7 @@ import ( "github.com/anchore/syft/internal/bus" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/mimetype" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/event/monitor" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/internal/unionreader" @@ -45,6 +46,8 @@ func NewCataloger(cfg Config) *Cataloger { } func (i *Cataloger) Catalog(resolver file.Resolver) (map[file.Coordinates]file.Executable, error) { + var errs error + locs, err := resolver.FilesByMIMEType(i.config.MIMETypes...) if err != nil { return nil, fmt.Errorf("unable to get file locations for binaries: %w", err) @@ -61,7 +64,10 @@ func (i *Cataloger) Catalog(resolver file.Resolver) (map[file.Coordinates]file.E for _, loc := range locs { prog.AtomicStage.Set(loc.Path()) - exec := processExecutableLocation(loc, resolver) + exec, err := processExecutableLocation(loc, resolver) + if err != nil { + errs = unknown.Append(errs, loc, err) + } if exec != nil { prog.Increment() @@ -74,30 +80,24 @@ func (i *Cataloger) Catalog(resolver file.Resolver) (map[file.Coordinates]file.E prog.AtomicStage.Set(fmt.Sprintf("%s executables", humanize.Comma(prog.Current()))) prog.SetCompleted() - return results, nil + return results, errs } -func processExecutableLocation(loc file.Location, resolver file.Resolver) *file.Executable { +func processExecutableLocation(loc file.Location, resolver file.Resolver) (*file.Executable, error) { reader, err := resolver.FileContentsByLocation(loc) if err != nil { - // TODO: known-unknowns log.WithFields("error", err).Warnf("unable to get file contents for %q", loc.RealPath) - return nil + return nil, fmt.Errorf("unable to get file contents: %w", err) } defer internal.CloseAndLogError(reader, loc.RealPath) uReader, err := unionreader.GetUnionReader(reader) if err != nil { - // TODO: known-unknowns log.WithFields("error", err).Warnf("unable to get union reader for %q", loc.RealPath) - return nil + return nil, fmt.Errorf("unable to get union reader: %w", err) } - exec, err := processExecutable(loc, uReader) - if err != nil { - log.WithFields("error", err).Warnf("unable to process executable %q", loc.RealPath) - } - return exec + return processExecutable(loc, uReader) } func catalogingProgress(locations int64) *monitor.CatalogerTaskProgress { @@ -153,10 +153,12 @@ func processExecutable(loc file.Location, reader unionreader.UnionReader) (*file format, err := findExecutableFormat(reader) if err != nil { + log.Debugf("unable to determine executable kind for %v: %v", loc.RealPath, err) return nil, fmt.Errorf("unable to determine executable kind: %w", err) } if format == "" { + // this is not an "unknown", so just log -- this binary does not have parseable data in it log.Debugf("unable to determine executable format for %q", loc.RealPath) return nil, nil } @@ -165,16 +167,19 @@ func processExecutable(loc file.Location, reader unionreader.UnionReader) (*file switch format { case file.ELF: - if err := findELFFeatures(&data, reader); err != nil { + if err = findELFFeatures(&data, reader); err != nil { log.WithFields("error", err).Tracef("unable to determine ELF features for %q", loc.RealPath) + err = fmt.Errorf("unable to determine ELF features: %w", err) } case file.PE: - if err := findPEFeatures(&data, reader); err != nil { + if err = findPEFeatures(&data, reader); err != nil { log.WithFields("error", err).Tracef("unable to determine PE features for %q", loc.RealPath) + err = fmt.Errorf("unable to determine PE features: %w", err) } case file.MachO: - if err := findMachoFeatures(&data, reader); err != nil { + if err = findMachoFeatures(&data, reader); err != nil { log.WithFields("error", err).Tracef("unable to determine Macho features for %q", loc.RealPath) + err = fmt.Errorf("unable to determine Macho features: %w", err) } } @@ -183,7 +188,7 @@ func processExecutable(loc file.Location, reader unionreader.UnionReader) (*file data.ImportedLibraries = []string{} } - return &data, nil + return &data, err } func findExecutableFormat(reader unionreader.UnionReader) (file.ExecutableFormat, error) { diff --git a/syft/file/cataloger/executable/elf.go b/syft/file/cataloger/executable/elf.go index dec6abd34..b9d2205cf 100644 --- a/syft/file/cataloger/executable/elf.go +++ b/syft/file/cataloger/executable/elf.go @@ -8,6 +8,7 @@ import ( "github.com/scylladb/go-set/strset" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/internal/unionreader" ) @@ -20,8 +21,8 @@ func findELFFeatures(data *file.Executable, reader unionreader.UnionReader) erro libs, err := f.ImportedLibraries() if err != nil { - // TODO: known-unknowns log.WithFields("error", err).Trace("unable to read imported libraries from elf file") + err = unknown.Joinf(err, "unable to read imported libraries from elf file: %w", err) libs = nil } @@ -34,7 +35,7 @@ func findELFFeatures(data *file.Executable, reader unionreader.UnionReader) erro data.HasEntrypoint = elfHasEntrypoint(f) data.HasExports = elfHasExports(f) - return nil + return err } func findELFSecurityFeatures(f *elf.File) *file.ELFSecurityFeatures { @@ -62,7 +63,6 @@ func checkElfStackCanary(file *elf.File) *bool { func hasAnyDynamicSymbols(file *elf.File, symbolNames ...string) *bool { dynSyms, err := file.DynamicSymbols() if err != nil { - // TODO: known-unknowns log.WithFields("error", err).Trace("unable to read dynamic symbols from elf file") return nil } @@ -129,7 +129,6 @@ func hasBindNowDynTagOrFlag(f *elf.File) bool { func hasElfDynFlag(f *elf.File, flag elf.DynFlag) bool { vals, err := f.DynValue(elf.DT_FLAGS) if err != nil { - // TODO: known-unknowns log.WithFields("error", err).Trace("unable to read DT_FLAGS from elf file") return false } @@ -144,7 +143,6 @@ func hasElfDynFlag(f *elf.File, flag elf.DynFlag) bool { func hasElfDynFlag1(f *elf.File, flag elf.DynFlag1) bool { vals, err := f.DynValue(elf.DT_FLAGS_1) if err != nil { - // TODO: known-unknowns log.WithFields("error", err).Trace("unable to read DT_FLAGS_1 from elf file") return false } @@ -203,7 +201,6 @@ func checkLLVMControlFlowIntegrity(file *elf.File) *bool { // look for any symbols that are functions and end with ".cfi" dynSyms, err := file.Symbols() if err != nil { - // TODO: known-unknowns log.WithFields("error", err).Trace("unable to read symbols from elf file") return nil } @@ -225,7 +222,6 @@ var fortifyPattern = regexp.MustCompile(`__\w+_chk@.+`) func checkClangFortifySource(file *elf.File) *bool { dynSyms, err := file.Symbols() if err != nil { - // TODO: known-unknowns log.WithFields("error", err).Trace("unable to read symbols from elf file") return nil } @@ -254,7 +250,7 @@ func elfHasExports(f *elf.File) bool { // really anything that is not marked with 'U' (undefined) is considered an export. symbols, err := f.DynamicSymbols() if err != nil { - // TODO: known-unknowns? + log.WithFields("error", err).Trace("unable to get ELF dynamic symbols") return false } diff --git a/syft/file/cataloger/executable/elf_test.go b/syft/file/cataloger/executable/elf_test.go index 454775891..fd3536cca 100644 --- a/syft/file/cataloger/executable/elf_test.go +++ b/syft/file/cataloger/executable/elf_test.go @@ -27,6 +27,7 @@ func Test_findELFSecurityFeatures(t *testing.T) { name string fixture string want *file.ELFSecurityFeatures + wantErr require.ErrorAssertionFunc wantStripped bool }{ { @@ -221,6 +222,7 @@ func Test_elfHasExports(t *testing.T) { f, err := elf.NewFile(readerForFixture(t, tt.fixture)) require.NoError(t, err) assert.Equal(t, tt.want, elfHasExports(f)) + require.NoError(t, err) }) } } diff --git a/syft/file/cataloger/filecontent/cataloger.go b/syft/file/cataloger/filecontent/cataloger.go index 36a411d39..b88257308 100644 --- a/syft/file/cataloger/filecontent/cataloger.go +++ b/syft/file/cataloger/filecontent/cataloger.go @@ -13,6 +13,7 @@ import ( "github.com/anchore/syft/internal/bus" intFile "github.com/anchore/syft/internal/file" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/event/monitor" "github.com/anchore/syft/syft/file" ) @@ -46,6 +47,7 @@ func NewCataloger(cfg Config) *Cataloger { func (i *Cataloger) Catalog(_ context.Context, resolver file.Resolver) (map[file.Coordinates]string, error) { results := make(map[file.Coordinates]string) var locations []file.Location + var errs error locations, err := resolver.FilesByGlob(i.globs...) if err != nil { @@ -59,8 +61,9 @@ func (i *Cataloger) Catalog(_ context.Context, resolver file.Resolver) (map[file metadata, err := resolver.FileMetadataByLocation(location) if err != nil { + errs = unknown.Append(errs, location, err) prog.SetError(err) - return nil, err + continue } if i.skipFilesAboveSizeInBytes > 0 && metadata.Size() > i.skipFilesAboveSizeInBytes { @@ -69,12 +72,12 @@ func (i *Cataloger) Catalog(_ context.Context, resolver file.Resolver) (map[file result, err := i.catalogLocation(resolver, location) if internal.IsErrPathPermission(err) { - log.Debugf("file contents cataloger skipping - %+v", err) + errs = unknown.Append(errs, location, fmt.Errorf("permission error reading file contents: %w", err)) continue } if err != nil { - prog.SetError(err) - return nil, err + errs = unknown.Append(errs, location, err) + continue } prog.Increment() @@ -87,7 +90,7 @@ func (i *Cataloger) Catalog(_ context.Context, resolver file.Resolver) (map[file prog.AtomicStage.Set(fmt.Sprintf("%s files", humanize.Comma(prog.Current()))) prog.SetCompleted() - return results, nil + return results, errs } func (i *Cataloger) catalogLocation(resolver file.Resolver, location file.Location) (string, error) { diff --git a/syft/file/cataloger/filedigest/cataloger.go b/syft/file/cataloger/filedigest/cataloger.go index e5d8c347e..f8aa9ace1 100644 --- a/syft/file/cataloger/filedigest/cataloger.go +++ b/syft/file/cataloger/filedigest/cataloger.go @@ -13,6 +13,7 @@ import ( "github.com/anchore/syft/internal/bus" intFile "github.com/anchore/syft/internal/file" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/event/monitor" "github.com/anchore/syft/syft/file" intCataloger "github.com/anchore/syft/syft/file/cataloger/internal" @@ -33,6 +34,7 @@ func NewCataloger(hashes []crypto.Hash) *Cataloger { func (i *Cataloger) Catalog(ctx context.Context, resolver file.Resolver, coordinates ...file.Coordinates) (map[file.Coordinates][]file.Digest, error) { results := make(map[file.Coordinates][]file.Digest) var locations []file.Location + var errs error if len(coordinates) == 0 { locations = intCataloger.AllRegularFiles(ctx, resolver) @@ -58,12 +60,14 @@ func (i *Cataloger) Catalog(ctx context.Context, resolver file.Resolver, coordin if internal.IsErrPathPermission(err) { log.Debugf("file digests cataloger skipping %q: %+v", location.RealPath, err) + errs = unknown.Append(errs, location, err) continue } if err != nil { prog.SetError(err) - return nil, fmt.Errorf("failed to process file %q: %w", location.RealPath, err) + errs = unknown.Append(errs, location, err) + continue } prog.Increment() @@ -76,7 +80,7 @@ func (i *Cataloger) Catalog(ctx context.Context, resolver file.Resolver, coordin prog.AtomicStage.Set(fmt.Sprintf("%s files", humanize.Comma(prog.Current()))) prog.SetCompleted() - return results, nil + return results, errs } func (i *Cataloger) catalogLocation(resolver file.Resolver, location file.Location) ([]file.Digest, error) { diff --git a/syft/file/cataloger/filemetadata/cataloger.go b/syft/file/cataloger/filemetadata/cataloger.go index e6935df73..b158e751d 100644 --- a/syft/file/cataloger/filemetadata/cataloger.go +++ b/syft/file/cataloger/filemetadata/cataloger.go @@ -8,6 +8,7 @@ import ( "github.com/anchore/syft/internal/bus" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/event/monitor" "github.com/anchore/syft/syft/file" ) @@ -20,6 +21,7 @@ func NewCataloger() *Cataloger { } func (i *Cataloger) Catalog(ctx context.Context, resolver file.Resolver, coordinates ...file.Coordinates) (map[file.Coordinates]file.Metadata, error) { + var errs error results := make(map[file.Coordinates]file.Metadata) var locations <-chan file.Location ctx, cancel := context.WithCancel(ctx) @@ -34,7 +36,7 @@ func (i *Cataloger) Catalog(ctx context.Context, resolver file.Resolver, coordin for _, c := range coordinates { locs, err := resolver.FilesByPath(c.RealPath) if err != nil { - log.Warn("unable to get file locations for path %q: %w", c.RealPath, err) + errs = unknown.Append(errs, c, err) continue } for _, loc := range locs { @@ -71,7 +73,7 @@ func (i *Cataloger) Catalog(ctx context.Context, resolver file.Resolver, coordin prog.AtomicStage.Set(fmt.Sprintf("%s locations", humanize.Comma(prog.Current()))) prog.SetCompleted() - return results, nil + return results, errs } func catalogingProgress(locations int64) *monitor.CatalogerTaskProgress { diff --git a/syft/file/coordinates.go b/syft/file/coordinates.go index 16256c31b..0d6cd0ec3 100644 --- a/syft/file/coordinates.go +++ b/syft/file/coordinates.go @@ -39,3 +39,7 @@ func (c Coordinates) String() string { } return fmt.Sprintf("Location<%s>", str) } + +func (c Coordinates) GetCoordinates() Coordinates { + return c +} diff --git a/syft/format/syftjson/decoder_test.go b/syft/format/syftjson/decoder_test.go index daa019dc4..27a6813b9 100644 --- a/syft/format/syftjson/decoder_test.go +++ b/syft/format/syftjson/decoder_test.go @@ -221,6 +221,7 @@ func Test_encodeDecodeFileMetadata(t *testing.T) { }, }, }, + Unknowns: map[file.Coordinates][]string{}, Executables: map[file.Coordinates]file.Executable{ c: { Format: file.ELF, diff --git a/syft/format/syftjson/model/file.go b/syft/format/syftjson/model/file.go index a98349f41..0ce0d92b3 100644 --- a/syft/format/syftjson/model/file.go +++ b/syft/format/syftjson/model/file.go @@ -13,6 +13,7 @@ type File struct { Digests []file.Digest `json:"digests,omitempty"` Licenses []FileLicense `json:"licenses,omitempty"` Executable *file.Executable `json:"executable,omitempty"` + Unknowns []string `json:"unknowns,omitempty"` } type FileMetadataEntry struct { diff --git a/syft/format/syftjson/to_format_model.go b/syft/format/syftjson/to_format_model.go index 42ec48f77..a5cd128a8 100644 --- a/syft/format/syftjson/to_format_model.go +++ b/syft/format/syftjson/to_format_model.go @@ -101,6 +101,11 @@ func toFile(s sbom.SBOM) []model.File { contents = contentsForLocation } + var unknowns []string + if unknownsForLocation, exists := artifacts.Unknowns[coordinates]; exists { + unknowns = unknownsForLocation + } + var licenses []model.FileLicense for _, l := range artifacts.FileLicenses[coordinates] { var evidence *model.FileLicenseEvidence @@ -132,6 +137,7 @@ func toFile(s sbom.SBOM) []model.File { Contents: contents, Licenses: licenses, Executable: executable, + Unknowns: unknowns, }) } diff --git a/syft/format/syftjson/to_syft_model.go b/syft/format/syftjson/to_syft_model.go index b2b1916e2..154b8fa8e 100644 --- a/syft/format/syftjson/to_syft_model.go +++ b/syft/format/syftjson/to_syft_model.go @@ -38,6 +38,7 @@ func toSyftModel(doc model.Document) *sbom.SBOM { FileContents: fileArtifacts.FileContents, FileLicenses: fileArtifacts.FileLicenses, Executables: fileArtifacts.Executables, + Unknowns: fileArtifacts.Unknowns, LinuxDistribution: toSyftLinuxRelease(doc.Distro), }, Source: *toSyftSourceData(doc.Source), @@ -66,6 +67,7 @@ func deduplicateErrors(errors []error) []string { return errorMessages } +//nolint:funlen func toSyftFiles(files []model.File) sbom.Artifacts { ret := sbom.Artifacts{ FileMetadata: make(map[file.Coordinates]file.Metadata), @@ -73,6 +75,7 @@ func toSyftFiles(files []model.File) sbom.Artifacts { FileContents: make(map[file.Coordinates]string), FileLicenses: make(map[file.Coordinates][]file.License), Executables: make(map[file.Coordinates]file.Executable), + Unknowns: make(map[file.Coordinates][]string), } for _, f := range files { @@ -130,6 +133,10 @@ func toSyftFiles(files []model.File) sbom.Artifacts { if f.Executable != nil { ret.Executables[coord] = *f.Executable } + + if len(f.Unknowns) > 0 { + ret.Unknowns[coord] = f.Unknowns + } } return ret diff --git a/syft/format/syftjson/to_syft_model_test.go b/syft/format/syftjson/to_syft_model_test.go index 5559db295..babba6345 100644 --- a/syft/format/syftjson/to_syft_model_test.go +++ b/syft/format/syftjson/to_syft_model_test.go @@ -234,6 +234,7 @@ func Test_toSyftFiles(t *testing.T) { FileMetadata: map[file.Coordinates]file.Metadata{}, FileDigests: map[file.Coordinates][]file.Digest{}, Executables: map[file.Coordinates]file.Executable{}, + Unknowns: make(map[file.Coordinates][]string), }, }, { @@ -349,6 +350,7 @@ func Test_toSyftFiles(t *testing.T) { t.Run(tt.name, func(t *testing.T) { tt.want.FileContents = make(map[file.Coordinates]string) tt.want.FileLicenses = make(map[file.Coordinates][]file.License) + tt.want.Unknowns = make(map[file.Coordinates][]string) assert.Equal(t, tt.want, toSyftFiles(tt.files)) }) } diff --git a/syft/pkg/cataloger/alpine/cataloger_test.go b/syft/pkg/cataloger/alpine/cataloger_test.go index 8ac6eaa8e..fff8e77f4 100644 --- a/syft/pkg/cataloger/alpine/cataloger_test.go +++ b/syft/pkg/cataloger/alpine/cataloger_test.go @@ -190,6 +190,14 @@ func TestApkDBCataloger(t *testing.T) { } +func Test_corruptDb(t *testing.T) { + pkgtest.NewCatalogTester(). + FromDirectory(t, "test-fixtures/corrupt"). + WithCompareOptions(cmpopts.IgnoreFields(pkg.ApkDBEntry{}, "Files", "GitCommit", "Checksum")). + WithError(). + TestCataloger(t, NewDBCataloger()) +} + func TestCatalogerDependencyTree(t *testing.T) { assertion := func(t *testing.T, pkgs []pkg.Package, relationships []artifact.Relationship) { expected := map[string][]string{ diff --git a/syft/pkg/cataloger/alpine/parse_apk_db.go b/syft/pkg/cataloger/alpine/parse_apk_db.go index 227d93bcb..181b2bbf4 100644 --- a/syft/pkg/cataloger/alpine/parse_apk_db.go +++ b/syft/pkg/cataloger/alpine/parse_apk_db.go @@ -12,6 +12,7 @@ import ( "github.com/anchore/syft/internal" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/linux" @@ -38,6 +39,7 @@ type parsedData struct { func parseApkDB(_ context.Context, resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { scanner := bufio.NewScanner(reader) + var errs error var apks []parsedData var currentEntry parsedData entryParsingInProgress := false @@ -81,10 +83,12 @@ func parseApkDB(_ context.Context, resolver file.Resolver, env *generic.Environm field := parseApkField(line) if field == nil { log.Warnf("unable to parse field data from line %q", line) + errs = unknown.Appendf(errs, reader, "unable to parse field data from line %q", line) continue } if len(field.name) == 0 { log.Warnf("failed to parse field name from line %q", line) + errs = unknown.Appendf(errs, reader, "failed to parse field name from line %q", line) continue } if len(field.value) == 0 { @@ -131,7 +135,7 @@ func parseApkDB(_ context.Context, resolver file.Resolver, env *generic.Environm pkgs = append(pkgs, newPackage(apk, r, reader.Location)) } - return pkgs, nil, nil + return pkgs, nil, errs } func findReleases(resolver file.Resolver, dbPath string) []linux.Release { diff --git a/syft/pkg/cataloger/alpine/test-fixtures/corrupt/lib/apk/db/installed b/syft/pkg/cataloger/alpine/test-fixtures/corrupt/lib/apk/db/installed new file mode 100644 index 000000000..b1f971acc --- /dev/null +++ b/syft/pkg/cataloger/alpine/test-fixtures/corrupt/lib/apk/db/installed @@ -0,0 +1,43 @@ +this is a corrupt db + +C:Q1v4QhLje3kWlC8DJj+ZfJTjlJRSU= +P:alpine-baselayout-data +V:3.2.0-r22 +A:x86_64 +S:11435 +I:73728 +o:alpine-baselayout +t:1655134784 +c:cb70ca5c6d6db0399d2dd09189c5d57827bce5cd +r:alpine-baselayout +F:etc +R:fstab +Z:Q11Q7hNe8QpDS531guqCdrXBzoA/o= +R:group +Z:Q13K+olJg5ayzHSVNUkggZJXuB+9Y= +R:hostname +Z:Q16nVwYVXP/tChvUPdukVD2ifXOmc= +R:hosts +Z:Q1BD6zJKZTRWyqGnPi4tSfd3krsMU= +R:inittab +Z:Q1TsthbhW7QzWRe1E/NKwTOuD4pHc= +R:modules +Z:Q1toogjUipHGcMgECgPJX64SwUT1M= +R:mtab +a:0:0:777 +Z:Q1kiljhXXH1LlQroHsEJIkPZg2eiw= +R:passwd +Z:Q1TchuuLUfur0izvfZQZxgN/LJhB8= +R:profile +Z:Q1F3DgXUP+jNZDknmQPPb5t9FSfDg= +R:protocols +Z:Q1omKlp3vgGq2ZqYzyD/KHNdo8rDc= +R:services +Z:Q19WLCv5ItKg4MH7RWfNRh1I7byQc= +R:shadow +a:0:42:640 +Z:Q1ltrPIAW2zHeDiajsex2Bdmq3uqA= +R:shells +Z:Q1ojm2YdpCJ6B/apGDaZ/Sdb2xJkA= +R:sysctl.conf +Z:Q14upz3tfnNxZkIEsUhWn7Xoiw96g= diff --git a/syft/pkg/cataloger/arch/cataloger_test.go b/syft/pkg/cataloger/arch/cataloger_test.go index 0badcb828..e61525246 100644 --- a/syft/pkg/cataloger/arch/cataloger_test.go +++ b/syft/pkg/cataloger/arch/cataloger_test.go @@ -11,6 +11,14 @@ import ( "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" ) +func TestAlpmUnknowns(t *testing.T) { + pkgtest.NewCatalogTester(). + FromDirectory(t, "test-fixtures/installed"). + WithCompareOptions(cmpopts.IgnoreFields(pkg.AlpmFileRecord{}, "Time")). + WithError(). + TestCataloger(t, NewDBCataloger()) +} + func TestAlpmCataloger(t *testing.T) { gmpDbLocation := file.NewLocation("var/lib/pacman/local/gmp-6.2.1-2/desc") treeSitterDbLocation := file.NewLocation("var/lib/pacman/local/tree-sitter-0.22.6-1/desc") diff --git a/syft/pkg/cataloger/arch/parse_alpm_db.go b/syft/pkg/cataloger/arch/parse_alpm_db.go index cb068df81..4c79abb8f 100644 --- a/syft/pkg/cataloger/arch/parse_alpm_db.go +++ b/syft/pkg/cataloger/arch/parse_alpm_db.go @@ -17,6 +17,7 @@ import ( "github.com/anchore/syft/internal" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -41,6 +42,8 @@ type parsedData struct { // parseAlpmDB parses the arch linux pacman database flat-files and returns the packages and relationships found within. func parseAlpmDB(_ context.Context, resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { + var errs error + data, err := parseAlpmDBEntry(reader) if err != nil { return nil, nil, err @@ -52,24 +55,25 @@ func parseAlpmDB(_ context.Context, resolver file.Resolver, env *generic.Environ base := path.Dir(reader.RealPath) + var locs []file.Location + // replace the files found the pacman database with the files from the mtree These contain more metadata and // thus more useful. - files, fileLoc := fetchPkgFiles(base, resolver) - backups, backupLoc := fetchBackupFiles(base, resolver) - - var locs []file.Location - if fileLoc != nil { + files, fileLoc, err := fetchPkgFiles(base, resolver) + errs = unknown.Join(errs, err) + if err == nil { locs = append(locs, fileLoc.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) data.Files = files } - - if backupLoc != nil { + backups, backupLoc, err := fetchBackupFiles(base, resolver) + errs = unknown.Join(errs, err) + if err == nil { locs = append(locs, backupLoc.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) data.Backup = backups } if data.Package == "" { - return nil, nil, nil + return nil, nil, errs } return []pkg.Package{ @@ -79,63 +83,56 @@ func parseAlpmDB(_ context.Context, resolver file.Resolver, env *generic.Environ reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), locs..., ), - }, nil, nil + }, nil, errs } -func fetchPkgFiles(base string, resolver file.Resolver) ([]pkg.AlpmFileRecord, *file.Location) { +func fetchPkgFiles(base string, resolver file.Resolver) ([]pkg.AlpmFileRecord, file.Location, error) { // TODO: probably want to use MTREE and PKGINFO here target := path.Join(base, "mtree") loc, err := getLocation(target, resolver) if err != nil { log.WithFields("error", err, "path", target).Trace("failed to find mtree file") - return []pkg.AlpmFileRecord{}, nil - } - if loc == nil { - return []pkg.AlpmFileRecord{}, nil + return []pkg.AlpmFileRecord{}, loc, unknown.New(loc, fmt.Errorf("failed to find mtree file: %w", err)) } - - reader, err := resolver.FileContentsByLocation(*loc) + reader, err := resolver.FileContentsByLocation(loc) if err != nil { - return []pkg.AlpmFileRecord{}, nil + return []pkg.AlpmFileRecord{}, loc, unknown.New(loc, fmt.Errorf("failed to get contents: %w", err)) } defer internal.CloseAndLogError(reader, loc.RealPath) pkgFiles, err := parseMtree(reader) if err != nil { log.WithFields("error", err, "path", target).Trace("failed to parse mtree file") - return []pkg.AlpmFileRecord{}, nil + return []pkg.AlpmFileRecord{}, loc, unknown.New(loc, fmt.Errorf("failed to parse mtree: %w", err)) } - return pkgFiles, loc + return pkgFiles, loc, nil } -func fetchBackupFiles(base string, resolver file.Resolver) ([]pkg.AlpmFileRecord, *file.Location) { +func fetchBackupFiles(base string, resolver file.Resolver) ([]pkg.AlpmFileRecord, file.Location, error) { // We only really do this to get any backup database entries from the files database target := filepath.Join(base, "files") loc, err := getLocation(target, resolver) if err != nil { log.WithFields("error", err, "path", target).Trace("failed to find alpm files") - return []pkg.AlpmFileRecord{}, nil - } - if loc == nil { - return []pkg.AlpmFileRecord{}, nil + return []pkg.AlpmFileRecord{}, loc, unknown.New(loc, fmt.Errorf("failed to find alpm files: %w", err)) } - reader, err := resolver.FileContentsByLocation(*loc) + reader, err := resolver.FileContentsByLocation(loc) if err != nil { - return []pkg.AlpmFileRecord{}, nil + return []pkg.AlpmFileRecord{}, loc, unknown.New(loc, fmt.Errorf("failed to get contents: %w", err)) } defer internal.CloseAndLogError(reader, loc.RealPath) filesMetadata, err := parseAlpmDBEntry(reader) if err != nil { - return []pkg.AlpmFileRecord{}, nil + return []pkg.AlpmFileRecord{}, loc, unknown.New(loc, fmt.Errorf("failed to parse alpm db entry: %w", err)) } if filesMetadata != nil { - return filesMetadata.Backup, loc + return filesMetadata.Backup, loc, nil } - return []pkg.AlpmFileRecord{}, loc + return []pkg.AlpmFileRecord{}, loc, nil } func parseAlpmDBEntry(reader io.Reader) (*parsedData, error) { @@ -171,20 +168,21 @@ func newScanner(reader io.Reader) *bufio.Scanner { return scanner } -func getLocation(path string, resolver file.Resolver) (*file.Location, error) { +func getLocation(path string, resolver file.Resolver) (file.Location, error) { + loc := file.NewLocation(path) locs, err := resolver.FilesByPath(path) if err != nil { - return nil, err + return loc, err } if len(locs) == 0 { - return nil, fmt.Errorf("could not find file: %s", path) + return loc, fmt.Errorf("could not find file: %s", path) } if len(locs) > 1 { log.WithFields("path", path).Trace("multiple files found for path, using first path") } - return &locs[0], nil + return locs[0], nil } func parseDatabase(b *bufio.Scanner) (*parsedData, error) { diff --git a/syft/pkg/cataloger/arch/test-fixtures/installed/var/lib/pacman/local/corrupt-0.2.1-3/desc b/syft/pkg/cataloger/arch/test-fixtures/installed/var/lib/pacman/local/corrupt-0.2.1-3/desc new file mode 100644 index 000000000..ff403145b --- /dev/null +++ b/syft/pkg/cataloger/arch/test-fixtures/installed/var/lib/pacman/local/corrupt-0.2.1-3/desc @@ -0,0 +1,34 @@ +%NME% +tree-sitter + +%VER.6-1 + +%BASE% +tree-sitter + +%DESC% +Incremental parsing library + + +%BUILDDATE% +1714945746 + +%INSTALLDATE% +1715026360 + +%PACKA@archlinux.org> + +%SIZE% +223539 + +%REASON% +1 + +%LICENSE% +MIT + +%VALIDATION% +pgp + +%PROVIDE +libtree-sitter.so=0-64 diff --git a/syft/pkg/cataloger/binary/classifier_cataloger.go b/syft/pkg/cataloger/binary/classifier_cataloger.go index 7352202d4..05e1c622a 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger.go @@ -6,8 +6,10 @@ package binary import ( "context" "encoding/json" + "fmt" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -59,12 +61,14 @@ func (c cataloger) Name() string { func (c cataloger) Catalog(_ context.Context, resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) { var packages []pkg.Package var relationships []artifact.Relationship + var errs error for _, cls := range c.classifiers { log.WithFields("classifier", cls.Class).Trace("cataloging binaries") newPkgs, err := catalog(resolver, cls) if err != nil { - log.WithFields("error", err, "classifier", cls.Class).Warn("unable to catalog binary package: %w", err) + log.WithFields("error", err, "classifier", cls.Class).Debugf("unable to catalog binary package: %v", err) + errs = unknown.Join(errs, fmt.Errorf("%s: %w", cls.Class, err)) continue } newPackages: @@ -82,7 +86,7 @@ func (c cataloger) Catalog(_ context.Context, resolver file.Resolver) ([]pkg.Pac } } - return packages, relationships, nil + return packages, relationships, errs } // mergePackages merges information from the extra package into the target package @@ -98,6 +102,7 @@ func mergePackages(target *pkg.Package, extra *pkg.Package) { } func catalog(resolver file.Resolver, cls Classifier) (packages []pkg.Package, err error) { + var errs error locations, err := resolver.FilesByGlob(cls.FileGlob) if err != nil { return nil, err @@ -105,11 +110,12 @@ func catalog(resolver file.Resolver, cls Classifier) (packages []pkg.Package, er for _, location := range locations { pkgs, err := cls.EvidenceMatcher(cls, matcherContext{resolver: resolver, location: location}) if err != nil { - return nil, err + errs = unknown.Append(errs, location, err) + continue } packages = append(packages, pkgs...) } - return packages, nil + return packages, errs } // packagesMatch returns true if the binary packages "match" based on basic criteria diff --git a/syft/pkg/cataloger/binary/classifier_cataloger_test.go b/syft/pkg/cataloger/binary/classifier_cataloger_test.go index 1bba77b25..f093b97ca 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger_test.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger_test.go @@ -1668,7 +1668,7 @@ func Test_Cataloger_ResilientToErrors(t *testing.T) { resolver := &panicyResolver{} _, _, err := c.Catalog(context.Background(), resolver) - assert.NoError(t, err) + assert.Error(t, err) assert.True(t, resolver.searchCalled) } diff --git a/syft/pkg/cataloger/binary/elf_package_cataloger.go b/syft/pkg/cataloger/binary/elf_package_cataloger.go index ae2b94d9e..24b4c0b08 100644 --- a/syft/pkg/cataloger/binary/elf_package_cataloger.go +++ b/syft/pkg/cataloger/binary/elf_package_cataloger.go @@ -11,6 +11,7 @@ import ( "github.com/anchore/syft/internal" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/mimetype" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/internal/unionreader" @@ -52,6 +53,7 @@ func (c *elfPackageCataloger) Name() string { } func (c *elfPackageCataloger) Catalog(_ context.Context, resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) { + var errs error locations, err := resolver.FilesByMIMEType(mimetype.ExecutableMIMETypeSet.List()...) if err != nil { return nil, nil, fmt.Errorf("unable to get binary files by mime type: %w", err) @@ -62,7 +64,8 @@ func (c *elfPackageCataloger) Catalog(_ context.Context, resolver file.Resolver) for _, location := range locations { notes, key, err := parseElfPackageNotes(resolver, location, c) if err != nil { - return nil, nil, err + errs = unknown.Append(errs, location, err) + continue } if notes == nil { continue @@ -87,7 +90,7 @@ func (c *elfPackageCataloger) Catalog(_ context.Context, resolver file.Resolver) // why not return relationships? We have an executable cataloger that will note the dynamic libraries imported by // each binary. After all files and packages are processed there is a final task that creates package-to-package // and package-to-file relationships based on the dynamic libraries imported by each binary. - return pkgs, nil, nil + return pkgs, nil, errs } func parseElfPackageNotes(resolver file.Resolver, location file.Location, c *elfPackageCataloger) (*elfBinaryPackageNotes, elfPackageKey, error) { @@ -104,7 +107,7 @@ func parseElfPackageNotes(resolver file.Resolver, location file.Location, c *elf if err != nil { log.WithFields("file", location.Path(), "error", err).Trace("unable to parse ELF notes") - return nil, elfPackageKey{}, nil + return nil, elfPackageKey{}, err } if notes == nil { @@ -173,7 +176,7 @@ func getELFNotes(r file.LocationReadCloser) (*elfBinaryPackageNotes, error) { if len(notes) > headerSize { var metadata elfBinaryPackageNotes newPayload := bytes.TrimRight(notes[headerSize:], "\x00") - if err := json.Unmarshal(newPayload, &metadata); err == nil { + if err = json.Unmarshal(newPayload, &metadata); err == nil { return &metadata, nil } log.WithFields("file", r.Location.Path(), "error", err).Trace("unable to unmarshal ELF package notes as JSON") diff --git a/syft/pkg/cataloger/binary/elf_package_cataloger_test.go b/syft/pkg/cataloger/binary/elf_package_cataloger_test.go index d9a97cc64..0325b3083 100644 --- a/syft/pkg/cataloger/binary/elf_package_cataloger_test.go +++ b/syft/pkg/cataloger/binary/elf_package_cataloger_test.go @@ -3,6 +3,8 @@ package binary import ( "testing" + "github.com/stretchr/testify/require" + "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" @@ -14,6 +16,7 @@ func Test_ELF_Package_Cataloger(t *testing.T) { name string fixture string expected []pkg.Package + wantErr require.ErrorAssertionFunc }{ { name: "go case", @@ -63,6 +66,7 @@ func Test_ELF_Package_Cataloger(t *testing.T) { }, }, }, + wantErr: require.Error, }, { name: "fedora 64 bit binaries", @@ -116,6 +120,7 @@ func Test_ELF_Package_Cataloger(t *testing.T) { WithImageResolver(t, v.fixture). IgnoreLocationLayer(). // this fixture can be rebuilt, thus the layer ID will change Expects(v.expected, nil). + WithErrorAssertion(v.wantErr). TestCataloger(t, NewELFPackageCataloger()) }) } diff --git a/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/Dockerfile b/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/Dockerfile index 42a74837c..a54ffdcc7 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/Dockerfile +++ b/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/Dockerfile @@ -5,9 +5,11 @@ RUN dnf update -y; \ dnf clean all RUN mkdir -p /usr/local/bin/elftests/elfbinwithnestedlib RUN mkdir -p /usr/local/bin/elftests/elfbinwithsisterlib +RUN mkdir -p /usr/local/bin/elftests/elfbinwithcorrupt COPY ./elfbinwithnestedlib /usr/local/bin/elftests/elfbinwithnestedlib COPY ./elfbinwithsisterlib /usr/local/bin/elftests/elfbinwithsisterlib +COPY ./elfbinwithcorrupt /usr/local/bin/elftests/elfbinwithcorrupt ENV LD_LIBRARY_PATH=/usr/local/bin/elftests/elfbinwithnestedlib/bin/lib @@ -16,6 +18,8 @@ RUN make WORKDIR /usr/local/bin/elftests/elfbinwithsisterlib RUN make +WORKDIR /usr/local/bin/elftests/elfbinwithcorrupt +RUN make # let's make the test image smaller, since we only require the built binaries and supporting libraries FROM busybox:1.36.1-musl diff --git a/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/elfsrc/hello_world.cpp b/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/elfsrc/hello_world.cpp new file mode 100644 index 000000000..9da59af37 --- /dev/null +++ b/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/elfsrc/hello_world.cpp @@ -0,0 +1,6 @@ +#include +#include "hello_world.h" + +void print_hello_world() { + std::cout << "Hello, World!" << std::endl; +} diff --git a/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/elfsrc/hello_world.h b/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/elfsrc/hello_world.h new file mode 100644 index 000000000..d4193a609 --- /dev/null +++ b/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/elfsrc/hello_world.h @@ -0,0 +1,8 @@ + +#ifndef HELLO_WORLD_H +#define HELLO_WORLD_H + +// Function declaration for printing "Hello, World!" to stdout +void print_hello_world(); + +#endif // HELLO_WORLD_H diff --git a/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/elfsrc/makefile b/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/elfsrc/makefile new file mode 100644 index 000000000..9b471a878 --- /dev/null +++ b/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/elfsrc/makefile @@ -0,0 +1,48 @@ +LDFLAGS := -L/lib64 -lstdc++ + +SRC_DIR := ./ +BUILD_DIR := ../build +BIN_DIR := ../bin +LIB_DIR := $(BIN_DIR)/lib + +LIB_NAME := hello_world +LIB_SRC := $(SRC_DIR)/hello_world.cpp +LIB_OBJ := $(BUILD_DIR)/$(LIB_NAME).o +LIB_SO := $(LIB_DIR)/lib$(LIB_NAME).so + +EXECUTABLE := elfbinwithnestedlib +EXEC_SRC := $(SRC_DIR)/testbin.cpp +EXEC_OBJ := $(BUILD_DIR)/$(EXECUTABLE).o + + + +all: testfixture + +$(LIB_SO): $(LIB_OBJ) | $(LIB_DIR) + $(CC) -shared -o $@ $< + echo '{ corrupt json "system": "syftsys","name": "libhello_world.so","version": "0.01","pure:0.01"}' | objcopy --add-section .note.package=/dev/stdin --set-section-flags .note.package=noload,readonly $@ + +$(LIB_OBJ): $(LIB_SRC) | $(BUILD_DIR) + $(CC) $(CFLAGS) -fPIC -c $< -o $@ + +$(EXEC_OBJ): $(EXEC_SRC) | $(BUILD_DIR) + $(CC) $(CFLAGS) -c $< -o $@ + +$(BIN_DIR): + mkdir -p $(BIN_DIR) +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) +$(LIB_DIR): + mkdir -p $(LIB_DIR) + +$(BIN_DIR)/$(EXECUTABLE): $(EXEC_OBJ) $(LIB_SO) | $(BIN_DIR) + $(CC) $(CFLAGS) -o $@ $^ -L$(LIB_DIR) -l$(LIB_NAME) $(LDFLAGS) + echo '{corrupt json ..._syfttestfixture:0.01"}' | objcopy --add-section .note.package=/dev/stdin --set-section-flags .note.package=noload,readonly $@ + +testfixture: $(BIN_DIR)/$(EXECUTABLE) + +clean: + rm -rf $(BUILD_DIR) $(LIB_DIR) $(BIN_DIR) $(EXECUTABLE) + +.PHONY: all clean + diff --git a/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/elfsrc/testbin.cpp b/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/elfsrc/testbin.cpp new file mode 100644 index 000000000..58a6e1050 --- /dev/null +++ b/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/elfsrc/testbin.cpp @@ -0,0 +1,8 @@ +#include "hello_world.h" + +int main() { + // Call the function from the shared library + print_hello_world(); + + return 0; +} diff --git a/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/makefile b/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/makefile new file mode 100644 index 000000000..b53f429a3 --- /dev/null +++ b/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/elfbinwithcorrupt/makefile @@ -0,0 +1,18 @@ +CC = g++ +CFLAGS = -std=c++17 -Wall -Wextra -pedantic +BUILD_DIR := ./build +BIN_DIR := ./bin +LIB_DIR := $(BIN_DIR)/lib + + + +all: testfixtures + +testfixtures: + $(MAKE) -C elfsrc + +clean: + rm -rf $(BUILD_DIR) $(BIN_DIR) + +.PHONY: all clean testfixtures + diff --git a/syft/pkg/cataloger/cpp/parse_conanfile.go b/syft/pkg/cataloger/cpp/parse_conanfile.go index 622acbdcb..2885b6f71 100644 --- a/syft/pkg/cataloger/cpp/parse_conanfile.go +++ b/syft/pkg/cataloger/cpp/parse_conanfile.go @@ -8,6 +8,7 @@ import ( "io" "strings" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -25,7 +26,7 @@ func parseConanfile(_ context.Context, _ file.Resolver, _ *generic.Environment, line, err := r.ReadString('\n') switch { case errors.Is(err, io.EOF): - return pkgs, nil, nil + return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") case err != nil: return nil, nil, fmt.Errorf("failed to parse conanfile.txt file: %w", err) } diff --git a/syft/pkg/cataloger/cpp/parse_conanlock.go b/syft/pkg/cataloger/cpp/parse_conanlock.go index efdfcf08d..1a1aa4d12 100644 --- a/syft/pkg/cataloger/cpp/parse_conanlock.go +++ b/syft/pkg/cataloger/cpp/parse_conanlock.go @@ -5,6 +5,7 @@ import ( "encoding/json" "strings" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -72,7 +73,7 @@ func parseConanLock(_ context.Context, _ file.Resolver, _ *generic.Environment, } } - return pkgs, relationships, nil + return pkgs, relationships, unknown.IfEmptyf(pkgs, "unable to determine packages") } // handleConanLockV1 handles the parsing of conan lock v1 files (aka v0.4) diff --git a/syft/pkg/cataloger/cpp/parse_conanlock_test.go b/syft/pkg/cataloger/cpp/parse_conanlock_test.go index da143fe51..23fe24c28 100644 --- a/syft/pkg/cataloger/cpp/parse_conanlock_test.go +++ b/syft/pkg/cataloger/cpp/parse_conanlock_test.go @@ -373,3 +373,10 @@ func TestParseConanLockV2(t *testing.T) { pkgtest.TestFileParser(t, fixture, parseConanLock, expected, expectedRelationships) } + +func Test_corruptConanlock(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/corrupt/conan.lock"). + WithError(). + TestParser(t, parseConanLock) +} diff --git a/syft/pkg/cataloger/cpp/test-fixtures/corrupt/conan.lock b/syft/pkg/cataloger/cpp/test-fixtures/corrupt/conan.lock new file mode 100644 index 000000000..c7e82d59c --- /dev/null +++ b/syft/pkg/cataloger/cpp/test-fixtures/corrupt/conan.lock @@ -0,0 +1,10 @@ +{ + corrupt json + version": "0.5", + "requires": [ + "sound32/1.0#83d4b7bf607b3b60a6546f8b58b5cdd7%1675278904.0791488", + "matrix/1.1#905c3f0babc520684c84127378fefdd0%1675278901.7527816" + ], + "build_requires": [], + "python_requires": [] +} diff --git a/syft/pkg/cataloger/dart/parse_pubspec_lock.go b/syft/pkg/cataloger/dart/parse_pubspec_lock.go index 12009659a..ebf41f822 100644 --- a/syft/pkg/cataloger/dart/parse_pubspec_lock.go +++ b/syft/pkg/cataloger/dart/parse_pubspec_lock.go @@ -9,6 +9,7 @@ import ( "gopkg.in/yaml.v3" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -85,7 +86,7 @@ func parsePubspecLock(_ context.Context, _ file.Resolver, _ *generic.Environment ) } - return pkgs, nil, nil + return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") } func (p *pubspecLockPackage) getVcsURL() string { diff --git a/syft/pkg/cataloger/dart/parse_pubspec_lock_test.go b/syft/pkg/cataloger/dart/parse_pubspec_lock_test.go index 6904b88c6..5aa5fc702 100644 --- a/syft/pkg/cataloger/dart/parse_pubspec_lock_test.go +++ b/syft/pkg/cataloger/dart/parse_pubspec_lock_test.go @@ -106,3 +106,10 @@ func TestParsePubspecLock(t *testing.T) { pkgtest.TestFileParser(t, fixture, parsePubspecLock, expected, expectedRelationships) } + +func Test_corruptPubspecLock(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/corrupt/pubspec.lock"). + WithError(). + TestParser(t, parsePubspecLock) +} diff --git a/syft/pkg/cataloger/dart/test-fixtures/corrupt/pubspec.lock b/syft/pkg/cataloger/dart/test-fixtures/corrupt/pubspec.lock new file mode 100644 index 000000000..583bf6702 --- /dev/null +++ b/syft/pkg/cataloger/dart/test-fixtures/corrupt/pubspec.lock @@ -0,0 +1,7 @@ +pa +kages: + ale: + dependency: transitive + descr +s ps: + dart: ">=2.12.0 <3.0.0" diff --git a/syft/pkg/cataloger/debian/parse_dpkg_db.go b/syft/pkg/cataloger/debian/parse_dpkg_db.go index 8fc47eb49..97a73c656 100644 --- a/syft/pkg/cataloger/debian/parse_dpkg_db.go +++ b/syft/pkg/cataloger/debian/parse_dpkg_db.go @@ -15,6 +15,7 @@ import ( "github.com/anchore/syft/internal" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -39,7 +40,7 @@ func parseDpkgDB(_ context.Context, resolver file.Resolver, env *generic.Environ pkgs = append(pkgs, p) } - return pkgs, nil, nil + return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") } func findDpkgInfoFiles(name string, resolver file.Resolver, dbLocation file.Location) []file.Location { diff --git a/syft/pkg/cataloger/debian/parse_dpkg_db_test.go b/syft/pkg/cataloger/debian/parse_dpkg_db_test.go index 603de91e3..50ab3485b 100644 --- a/syft/pkg/cataloger/debian/parse_dpkg_db_test.go +++ b/syft/pkg/cataloger/debian/parse_dpkg_db_test.go @@ -257,6 +257,17 @@ func Test_parseDpkgStatus(t *testing.T) { } } +func Test_corruptEntry(t *testing.T) { + f, err := os.Open("test-fixtures/var/lib/dpkg/status.d/corrupt") + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, f.Close()) }) + + reader := bufio.NewReader(f) + + _, err = parseDpkgStatus(reader) + require.Error(t, err) +} + func TestSourceVersionExtract(t *testing.T) { tests := []struct { name string @@ -312,7 +323,7 @@ func Test_parseDpkgStatus_negativeCases(t *testing.T) { { name: "no more packages", input: `Package: apt`, - wantErr: require.NoError, + wantErr: requireAs(errors.New("unable to determine packages")), }, { name: "duplicated key", diff --git a/syft/pkg/cataloger/debian/test-fixtures/var/lib/dpkg/status.d/corrupt b/syft/pkg/cataloger/debian/test-fixtures/var/lib/dpkg/status.d/corrupt new file mode 100644 index 000000000..aadb72197 --- /dev/null +++ b/syft/pkg/cataloger/debian/test-fixtures/var/lib/dpkg/status.d/corrupt @@ -0,0 +1,6 @@ +Pakij: apt +Stratus: install ok installed +Prioority: required +Section: admin +Insterface to the configuration settings + * apt-key as an interface to manage authentication keys diff --git a/syft/pkg/cataloger/dotnet/parse_dotnet_deps.go b/syft/pkg/cataloger/dotnet/parse_dotnet_deps.go index 496148a35..2d980ca4e 100644 --- a/syft/pkg/cataloger/dotnet/parse_dotnet_deps.go +++ b/syft/pkg/cataloger/dotnet/parse_dotnet_deps.go @@ -8,6 +8,7 @@ import ( "github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/relationship" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -126,5 +127,5 @@ func parseDotnetDeps(_ context.Context, _ file.Resolver, _ *generic.Environment, // this will only consider package-to-package relationships. relationship.Sort(relationships) - return pkgs, relationships, nil + return pkgs, relationships, unknown.IfEmptyf(pkgs, "unable to determine packages") } diff --git a/syft/pkg/cataloger/dotnet/parse_dotnet_deps_test.go b/syft/pkg/cataloger/dotnet/parse_dotnet_deps_test.go index bdf40851a..84878c86c 100644 --- a/syft/pkg/cataloger/dotnet/parse_dotnet_deps_test.go +++ b/syft/pkg/cataloger/dotnet/parse_dotnet_deps_test.go @@ -9,6 +9,13 @@ import ( "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" ) +func Test_corruptDotnetDeps(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/glob-paths/src/something.deps.json"). + WithError(). + TestParser(t, parseDotnetDeps) +} + func TestParseDotnetDeps(t *testing.T) { fixture := "test-fixtures/TestLibrary.deps.json" fixtureLocationSet := file.NewLocationSet(file.NewLocation(fixture)) diff --git a/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable.go b/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable.go index 3ec83f229..4ea4d1c18 100644 --- a/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable.go +++ b/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable.go @@ -28,30 +28,26 @@ func parseDotnetPortableExecutable(_ context.Context, _ file.Resolver, _ *generi peFile, err := pe.NewBytes(by, &pe.Options{}) if err != nil { - // TODO: known-unknown log.Tracef("unable to create PE instance for file '%s': %v", f.RealPath, err) - return nil, nil, nil + return nil, nil, err } err = peFile.Parse() if err != nil { - // TODO: known-unknown log.Tracef("unable to parse PE file '%s': %v", f.RealPath, err) - return nil, nil, nil + return nil, nil, err } versionResources, err := peFile.ParseVersionResources() if err != nil { - // TODO: known-unknown log.Tracef("unable to parse version resources in PE file: %s: %v", f.RealPath, err) - return nil, nil, nil + return nil, nil, fmt.Errorf("unable to parse version resources in PE file: %w", err) } dotNetPkg, err := buildDotNetPackage(versionResources, f) if err != nil { - // TODO: known-unknown - log.Tracef("unable to build dotnet package: %v", err) - return nil, nil, nil + log.Tracef("unable to build dotnet package for: %v %v", f.RealPath, err) + return nil, nil, err } return []pkg.Package{dotNetPkg}, nil, nil @@ -60,12 +56,12 @@ func parseDotnetPortableExecutable(_ context.Context, _ file.Resolver, _ *generi func buildDotNetPackage(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: %s", f.RealPath) + return dnpkg, fmt.Errorf("unable to find PE name in file") } version := findVersion(versionResources) if version == "" { - return dnpkg, fmt.Errorf("unable to find PE version in file: %s", f.RealPath) + return dnpkg, fmt.Errorf("unable to find PE version in file") } metadata := pkg.DotnetPortableExecutableEntry{ 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 4d915a50d..2be417d6a 100644 --- a/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable_test.go +++ b/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable_test.go @@ -297,6 +297,13 @@ func TestParseDotnetPortableExecutable(t *testing.T) { } } +func Test_corruptDotnetPE(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/glob-paths/src/something.exe"). + WithError(). + TestParser(t, parseDotnetPortableExecutable) +} + func Test_extractVersion(t *testing.T) { tests := []struct { input string diff --git a/syft/pkg/cataloger/elixir/parse_mix_lock.go b/syft/pkg/cataloger/elixir/parse_mix_lock.go index dcd4a7858..adcdfbd9e 100644 --- a/syft/pkg/cataloger/elixir/parse_mix_lock.go +++ b/syft/pkg/cataloger/elixir/parse_mix_lock.go @@ -9,6 +9,7 @@ import ( "regexp" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -22,25 +23,33 @@ var mixLockDelimiter = regexp.MustCompile(`[%{}\n" ,:]+`) // parseMixLock parses a mix.lock and returns the discovered Elixir packages. func parseMixLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { + var errs error r := bufio.NewReader(reader) var packages []pkg.Package + lineNum := 0 for { + lineNum++ line, err := r.ReadString('\n') switch { case errors.Is(err, io.EOF): - return packages, nil, nil + if errs == nil { + errs = unknown.IfEmptyf(packages, "unable to determine packages") + } + return packages, nil, errs case err != nil: return nil, nil, fmt.Errorf("failed to parse mix.lock file: %w", err) } tokens := mixLockDelimiter.Split(line, -1) if len(tokens) < 6 { + errs = unknown.Appendf(errs, reader, "unable to read mix lock line %d: %s", lineNum, line) continue } name, version, hash, hashExt := tokens[1], tokens[4], tokens[5], tokens[len(tokens)-2] if name == "" { log.WithFields("path", reader.RealPath).Debug("skipping empty package name from mix.lock file") + errs = unknown.Appendf(errs, reader, "skipping empty package name from mix.lock file, for line: %d: %s", lineNum, line) continue } diff --git a/syft/pkg/cataloger/erlang/parse_otp_app.go b/syft/pkg/cataloger/erlang/parse_otp_app.go index dcea41c18..09edd1b3a 100644 --- a/syft/pkg/cataloger/erlang/parse_otp_app.go +++ b/syft/pkg/cataloger/erlang/parse_otp_app.go @@ -2,6 +2,7 @@ package erlang import ( "context" + "fmt" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/artifact" @@ -17,7 +18,7 @@ func parseOTPApp(_ context.Context, _ file.Resolver, _ *generic.Environment, rea // there are multiple file formats that use the *.app extension, so it's possible that this is not an OTP app file at all // ... which means we should not return an error here log.WithFields("error", err).Trace("unable to parse Erlang OTP app") - return nil, nil, nil + return nil, nil, fmt.Errorf("unable to parse Erlang OTP app") } var packages []pkg.Package diff --git a/syft/pkg/cataloger/erlang/parse_otp_app_test.go b/syft/pkg/cataloger/erlang/parse_otp_app_test.go index 9c0abf16e..93c0aa238 100644 --- a/syft/pkg/cataloger/erlang/parse_otp_app_test.go +++ b/syft/pkg/cataloger/erlang/parse_otp_app_test.go @@ -41,3 +41,10 @@ func TestParseOTPApplication(t *testing.T) { }) } } + +func Test_corruptOtpApp(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/corrupt/rabbitmq.app"). + WithError(). + TestParser(t, parseOTPApp) +} diff --git a/syft/pkg/cataloger/erlang/parse_rebar_lock.go b/syft/pkg/cataloger/erlang/parse_rebar_lock.go index a173ec81b..e77053419 100644 --- a/syft/pkg/cataloger/erlang/parse_rebar_lock.go +++ b/syft/pkg/cataloger/erlang/parse_rebar_lock.go @@ -4,6 +4,7 @@ import ( "context" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -95,7 +96,7 @@ func parseRebarLock(_ context.Context, _ file.Resolver, _ *generic.Environment, p.SetID() packages = append(packages, *p) } - return packages, nil, nil + return packages, nil, unknown.IfEmptyf(packages, "unable to determine packages") } // integrity check diff --git a/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go b/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go index 00d7a2730..67e309cd3 100644 --- a/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go +++ b/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go @@ -255,3 +255,10 @@ func TestParseRebarLock(t *testing.T) { }) } } + +func Test_corruptRebarLock(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/corrupt/rebar.lock"). + WithError(). + TestParser(t, parseRebarLock) +} diff --git a/syft/pkg/cataloger/erlang/test-fixtures/corrupt/rabbitmq.app b/syft/pkg/cataloger/erlang/test-fixtures/corrupt/rabbitmq.app new file mode 100644 index 000000000..5c8f73fd0 --- /dev/null +++ b/syft/pkg/cataloger/erlang/test-fixtures/corrupt/rabbitmq.app @@ -0,0 +1,9 @@ +cation, 'rabbit', [ + {description, "RabbitMQ"}, + {vsn, "3.12.10"}, + {id, "v3.12.9-9-g1f61ca8"}, + {modules, ['amqqueue','background_gc']}, + {optional_itmq-server#1593 + {channel_max, 2047} + ]} +]}. \ No newline at end of file diff --git a/syft/pkg/cataloger/erlang/test-fixtures/corrupt/rebar.lock b/syft/pkg/cataloger/erlang/test-fixtures/corrupt/rebar.lock new file mode 100644 index 000000000..ea6afc2a6 --- /dev/null +++ b/syft/pkg/cataloger/erlang/test-fixtures/corrupt/rebar.lock @@ -0,0 +1,11 @@ +{"1.2.0", +[{<<"certifi{pkg,<<"certifi">>,<<"2.9.0">>},0}, + {<<"idna">>,{pkg,<<"idpkg,<<"parse_trans">>,<<"3.3.1">>},0}, + {<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.6">>},0}, + {<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.7.0">>},0}]}. +[ +{pkg_hash,[ + {<<"certifi">>, <<"6F2A475689DD47F19FB74334859D460A2DC4E3252A3324BD2111B8F0429E7E21">>}, + {<<"idna">>, <<"8A63070E9F7D0C62EB9D9FCB360A7DE382448200FBBD1B106CC96D3D8099DF8D">>}, + {<<"metrics">>, <<"25F094DEA2CDA98213CECC3AEFF09E940299D950904393B2A29D191C346A8486">>}, + {<<"mimerl diff --git a/syft/pkg/cataloger/generic/cataloger.go b/syft/pkg/cataloger/generic/cataloger.go index 49e1b47b9..f955ed350 100644 --- a/syft/pkg/cataloger/generic/cataloger.go +++ b/syft/pkg/cataloger/generic/cataloger.go @@ -6,6 +6,7 @@ import ( "github.com/anchore/go-logger" "github.com/anchore/syft/internal" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/linux" @@ -151,6 +152,7 @@ func (c *Cataloger) Name() string { func (c *Cataloger) Catalog(ctx context.Context, resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) { var packages []pkg.Package var relationships []artifact.Relationship + var errs error logger := log.Nested("cataloger", c.upstreamCataloger) @@ -166,7 +168,8 @@ func (c *Cataloger) Catalog(ctx context.Context, resolver file.Resolver) ([]pkg. discoveredPackages, discoveredRelationships, err := invokeParser(ctx, resolver, location, logger, parser, &env) if err != nil { - continue // logging is handled within invokeParser + // parsers may return errors and valid packages / relationships + errs = unknown.Append(errs, location, err) } for _, p := range discoveredPackages { @@ -176,7 +179,7 @@ func (c *Cataloger) Catalog(ctx context.Context, resolver file.Resolver) ([]pkg. relationships = append(relationships, discoveredRelationships...) } - return c.process(ctx, resolver, packages, relationships, nil) + return c.process(ctx, resolver, packages, relationships, errs) } func (c *Cataloger) process(ctx context.Context, resolver file.Resolver, pkgs []pkg.Package, rels []artifact.Relationship, err error) ([]pkg.Package, []artifact.Relationship, error) { @@ -196,11 +199,11 @@ func invokeParser(ctx context.Context, resolver file.Resolver, location file.Loc discoveredPackages, discoveredRelationships, err := parser(ctx, resolver, env, file.NewLocationReadCloser(location, contentReader)) if err != nil { - logger.WithFields("location", location.RealPath, "error", err).Warnf("cataloger failed") - return nil, nil, err + // these errors are propagated up, and are likely to be coordinate errors + logger.WithFields("location", location.RealPath, "error", err).Trace("cataloger returned errors") } - return discoveredPackages, discoveredRelationships, nil + return discoveredPackages, discoveredRelationships, err } // selectFiles takes a set of file trees and resolves and file references of interest for future cataloging diff --git a/syft/pkg/cataloger/generic/cataloger_test.go b/syft/pkg/cataloger/generic/cataloger_test.go index e971b4459..1941b93f3 100644 --- a/syft/pkg/cataloger/generic/cataloger_test.go +++ b/syft/pkg/cataloger/generic/cataloger_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -187,3 +188,27 @@ func TestClosesFileOnParserPanic(t *testing.T) { }) require.True(t, spy.closed) } + +func Test_genericCatalogerReturnsErrors(t *testing.T) { + genericErrorReturning := NewCataloger("error returning").WithParserByGlobs(func(ctx context.Context, resolver file.Resolver, environment *Environment, locationReader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { + return []pkg.Package{ + { + Name: "some-package-" + locationReader.Path(), + }, + }, nil, unknown.Newf(locationReader, "unable to read") + }, "**/*") + + m := file.NewMockResolverForPaths( + "test-fixtures/a-path.txt", + "test-fixtures/empty.txt", + ) + + got, _, errs := genericErrorReturning.Catalog(context.TODO(), m) + + // require packages and errors + require.NotEmpty(t, got) + + unknowns, others := unknown.ExtractCoordinateErrors(errs) + require.NotEmpty(t, unknowns) + require.Empty(t, others) +} diff --git a/syft/pkg/cataloger/gentoo/parse_portage_contents.go b/syft/pkg/cataloger/gentoo/parse_portage_contents.go index 553976ea2..56370d012 100644 --- a/syft/pkg/cataloger/gentoo/parse_portage_contents.go +++ b/syft/pkg/cataloger/gentoo/parse_portage_contents.go @@ -35,7 +35,7 @@ func parsePortageContents(_ context.Context, resolver file.Resolver, _ *generic. name, version := cpvMatch[1], cpvMatch[2] if name == "" || version == "" { log.WithFields("path", reader.Location.RealPath).Warnf("failed to parse portage name and version") - return nil, nil, nil + return nil, nil, fmt.Errorf("failed to parse portage name and version") } p := pkg.Package{ diff --git a/syft/pkg/cataloger/githubactions/package.go b/syft/pkg/cataloger/githubactions/package.go index 7d6341d3c..ff1567a91 100644 --- a/syft/pkg/cataloger/githubactions/package.go +++ b/syft/pkg/cataloger/githubactions/package.go @@ -1,6 +1,7 @@ package githubactions import ( + "fmt" "strings" "github.com/anchore/packageurl-go" @@ -9,19 +10,19 @@ import ( "github.com/anchore/syft/syft/pkg" ) -func newPackageFromUsageStatement(use string, location file.Location) *pkg.Package { +func newPackageFromUsageStatement(use string, location file.Location) (*pkg.Package, error) { name, version := parseStepUsageStatement(use) if name == "" { log.WithFields("file", location.RealPath, "statement", use).Trace("unable to parse github action usage statement") - return nil + return nil, fmt.Errorf("unable to parse github action usage statement") } if strings.Contains(name, ".github/workflows/") { - return newGithubActionWorkflowPackageUsage(name, version, location) + return newGithubActionWorkflowPackageUsage(name, version, location), nil } - return newGithubActionPackageUsage(name, version, location) + return newGithubActionPackageUsage(name, version, location), nil } func newGithubActionWorkflowPackageUsage(name, version string, workflowLocation file.Location) *pkg.Package { diff --git a/syft/pkg/cataloger/githubactions/parse_composite_action.go b/syft/pkg/cataloger/githubactions/parse_composite_action.go index 99a20d282..3236679de 100644 --- a/syft/pkg/cataloger/githubactions/parse_composite_action.go +++ b/syft/pkg/cataloger/githubactions/parse_composite_action.go @@ -7,6 +7,7 @@ import ( "gopkg.in/yaml.v3" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -24,14 +25,14 @@ type compositeActionRunsDef struct { } func parseCompositeActionForActionUsage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { - contents, err := io.ReadAll(reader) - if err != nil { - return nil, nil, fmt.Errorf("unable to read yaml composite action file: %w", err) + contents, errs := io.ReadAll(reader) + if errs != nil { + return nil, nil, fmt.Errorf("unable to read yaml composite action file: %w", errs) } var ca compositeActionDef - if err = yaml.Unmarshal(contents, &ca); err != nil { - return nil, nil, fmt.Errorf("unable to parse yaml composite action file: %w", err) + if errs = yaml.Unmarshal(contents, &ca); errs != nil { + return nil, nil, fmt.Errorf("unable to parse yaml composite action file: %w", errs) } // we use a collection to help with deduplication before raising to higher level processing @@ -42,11 +43,14 @@ func parseCompositeActionForActionUsage(_ context.Context, _ file.Resolver, _ *g continue } - p := newPackageFromUsageStatement(step.Uses, reader.Location) + p, err := newPackageFromUsageStatement(step.Uses, reader.Location) + if err != nil { + errs = unknown.Append(errs, reader, err) + } if p != nil { pkgs.Add(*p) } } - return pkgs.Sorted(), nil, nil + return pkgs.Sorted(), nil, errs } diff --git a/syft/pkg/cataloger/githubactions/parse_composite_action_test.go b/syft/pkg/cataloger/githubactions/parse_composite_action_test.go index e39e18e1a..080d80816 100644 --- a/syft/pkg/cataloger/githubactions/parse_composite_action_test.go +++ b/syft/pkg/cataloger/githubactions/parse_composite_action_test.go @@ -33,3 +33,10 @@ func Test_parseCompositeActionForActionUsage(t *testing.T) { var expectedRelationships []artifact.Relationship pkgtest.TestFileParser(t, fixture, parseCompositeActionForActionUsage, expected, expectedRelationships) } + +func Test_corruptCompositeAction(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/corrupt/composite-action.yaml"). + WithError(). + TestParser(t, parseCompositeActionForActionUsage) +} diff --git a/syft/pkg/cataloger/githubactions/parse_workflow.go b/syft/pkg/cataloger/githubactions/parse_workflow.go index 880248cca..2480caf08 100644 --- a/syft/pkg/cataloger/githubactions/parse_workflow.go +++ b/syft/pkg/cataloger/githubactions/parse_workflow.go @@ -7,6 +7,7 @@ import ( "gopkg.in/yaml.v3" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -37,14 +38,14 @@ type stepDef struct { } func parseWorkflowForWorkflowUsage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { - contents, err := io.ReadAll(reader) - if err != nil { - return nil, nil, fmt.Errorf("unable to read yaml workflow file: %w", err) + contents, errs := io.ReadAll(reader) + if errs != nil { + return nil, nil, fmt.Errorf("unable to read yaml workflow file: %w", errs) } var wf workflowDef - if err = yaml.Unmarshal(contents, &wf); err != nil { - return nil, nil, fmt.Errorf("unable to parse yaml workflow file: %w", err) + if errs = yaml.Unmarshal(contents, &wf); errs != nil { + return nil, nil, fmt.Errorf("unable to parse yaml workflow file: %w", errs) } // we use a collection to help with deduplication before raising to higher level processing @@ -52,25 +53,28 @@ func parseWorkflowForWorkflowUsage(_ context.Context, _ file.Resolver, _ *generi for _, job := range wf.Jobs { if job.Uses != "" { - p := newPackageFromUsageStatement(job.Uses, reader.Location) + p, err := newPackageFromUsageStatement(job.Uses, reader.Location) + if err != nil { + errs = unknown.Append(errs, reader, err) + } if p != nil { pkgs.Add(*p) } } } - return pkgs.Sorted(), nil, nil + return pkgs.Sorted(), nil, errs } func parseWorkflowForActionUsage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { - contents, err := io.ReadAll(reader) - if err != nil { - return nil, nil, fmt.Errorf("unable to read yaml workflow file: %w", err) + contents, errs := io.ReadAll(reader) + if errs != nil { + return nil, nil, fmt.Errorf("unable to read yaml workflow file: %w", errs) } var wf workflowDef - if err = yaml.Unmarshal(contents, &wf); err != nil { - return nil, nil, fmt.Errorf("unable to parse yaml workflow file: %w", err) + if errs = yaml.Unmarshal(contents, &wf); errs != nil { + return nil, nil, fmt.Errorf("unable to parse yaml workflow file: %w", errs) } // we use a collection to help with deduplication before raising to higher level processing @@ -81,12 +85,15 @@ func parseWorkflowForActionUsage(_ context.Context, _ file.Resolver, _ *generic. if step.Uses == "" { continue } - p := newPackageFromUsageStatement(step.Uses, reader.Location) + p, err := newPackageFromUsageStatement(step.Uses, reader.Location) + if err != nil { + errs = unknown.Append(errs, reader, err) + } if p != nil { pkgs.Add(*p) } } } - return pkgs.Sorted(), nil, nil + return pkgs.Sorted(), nil, errs } diff --git a/syft/pkg/cataloger/githubactions/parse_workflow_test.go b/syft/pkg/cataloger/githubactions/parse_workflow_test.go index f5e5128b4..52c4e1ebd 100644 --- a/syft/pkg/cataloger/githubactions/parse_workflow_test.go +++ b/syft/pkg/cataloger/githubactions/parse_workflow_test.go @@ -86,3 +86,17 @@ func Test_parseWorkflowForWorkflowUsage(t *testing.T) { var expectedRelationships []artifact.Relationship pkgtest.TestFileParser(t, fixture, parseWorkflowForWorkflowUsage, expected, expectedRelationships) } + +func Test_corruptActionWorkflow(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/corrupt/workflow-multi-job.yaml"). + WithError(). + TestParser(t, parseWorkflowForActionUsage) +} + +func Test_corruptWorkflowWorkflow(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/corrupt/workflow-multi-job.yaml"). + WithError(). + TestParser(t, parseWorkflowForWorkflowUsage) +} diff --git a/syft/pkg/cataloger/githubactions/test-fixtures/corrupt/composite-action.yaml b/syft/pkg/cataloger/githubactions/test-fixtures/corrupt/composite-action.yaml new file mode 100644 index 000000000..44526253e --- /dev/null +++ b/syft/pkg/cataloger/githubactions/test-fixtures/corrupt/composite-action.yaml @@ -0,0 +1,13 @@ +name: "Bootstrap" +description: "Bootstrap all tools and dependencies" +ints: + go-version: + descrapt-packages: + description: "Space delimited list of tools to install via apt" + default: "libxml2-utils" + +rns: + us all cache fingerprints + shell: bash + run: make fingerprints + diff --git a/syft/pkg/cataloger/githubactions/test-fixtures/corrupt/workflow-multi-job.yaml b/syft/pkg/cataloger/githubactions/test-fixtures/corrupt/workflow-multi-job.yaml new file mode 100644 index 000000000..f9c2c0570 --- /dev/null +++ b/syft/pkg/cataloger/githubactions/test-fixtures/corrupt/workflow-multi-job.yaml @@ -0,0 +1,16 @@ +name: "Validations" + +on: + workflow_dispatch: + pull_request: + push: + branches: + - main + +jbs + + Statnapshot + key: snapshot-build-${{ github.run_id }} + + - name: Run CLI Tests (Linux) + run: make cli diff --git a/syft/pkg/cataloger/golang/parse_go_binary.go b/syft/pkg/cataloger/golang/parse_go_binary.go index 3f62ea4d8..bf3a6d722 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary.go +++ b/syft/pkg/cataloger/golang/parse_go_binary.go @@ -66,9 +66,9 @@ func (c *goBinaryCataloger) parseGoBinary(_ context.Context, resolver file.Resol if err != nil { return nil, nil, err } + defer internal.CloseAndLogError(reader.ReadCloser, reader.RealPath) - mods := scanFile(unionReader, reader.RealPath) - internal.CloseAndLogError(reader.ReadCloser, reader.RealPath) + mods, errs := scanFile(reader.Location, unionReader) var rels []artifact.Relationship for _, mod := range mods { @@ -81,7 +81,7 @@ func (c *goBinaryCataloger) parseGoBinary(_ context.Context, resolver file.Resol pkgs = append(pkgs, depPkgs...) } - return pkgs, rels, nil + return pkgs, rels, errs } func createModuleRelationships(main pkg.Package, deps []pkg.Package) []artifact.Relationship { diff --git a/syft/pkg/cataloger/golang/parse_go_mod_test.go b/syft/pkg/cataloger/golang/parse_go_mod_test.go index 19ae7f33b..20538e4c7 100644 --- a/syft/pkg/cataloger/golang/parse_go_mod_test.go +++ b/syft/pkg/cataloger/golang/parse_go_mod_test.go @@ -157,3 +157,11 @@ func Test_GoSumHashes(t *testing.T) { }) } } + +func Test_corruptGoMod(t *testing.T) { + c := NewGoModuleFileCataloger(DefaultCatalogerConfig().WithSearchRemoteLicenses(false)) + pkgtest.NewCatalogTester(). + FromDirectory(t, "test-fixtures/corrupt"). + WithError(). + TestCataloger(t, c) +} diff --git a/syft/pkg/cataloger/golang/scan_binary.go b/syft/pkg/cataloger/golang/scan_binary.go index 720008045..bef5c1b99 100644 --- a/syft/pkg/cataloger/golang/scan_binary.go +++ b/syft/pkg/cataloger/golang/scan_binary.go @@ -9,6 +9,8 @@ import ( "github.com/kastenhq/goversion/version" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" + "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/internal/unionreader" ) @@ -19,20 +21,21 @@ type extendedBuildInfo struct { } // scanFile scans file to try to report the Go and module versions. -func scanFile(reader unionreader.UnionReader, filename string) []*extendedBuildInfo { +func scanFile(location file.Location, reader unionreader.UnionReader) ([]*extendedBuildInfo, error) { // NOTE: multiple readers are returned to cover universal binaries, which are files // with more than one binary - readers, err := unionreader.GetReaders(reader) - if err != nil { - log.WithFields("error", err).Warnf("failed to open a golang binary") - return nil + readers, errs := unionreader.GetReaders(reader) + if errs != nil { + log.WithFields("error", errs).Warnf("failed to open a golang binary") + return nil, fmt.Errorf("failed to open a golang binary: %w", errs) } var builds []*extendedBuildInfo for _, r := range readers { bi, err := getBuildInfo(r) if err != nil { - log.WithFields("file", filename, "error", err).Trace("unable to read golang buildinfo") + log.WithFields("file", location.RealPath, "error", err).Trace("unable to read golang buildinfo") + continue } // it's possible the reader just isn't a go binary, in which case just skip it @@ -42,23 +45,25 @@ func scanFile(reader unionreader.UnionReader, filename string) []*extendedBuildI v, err := getCryptoInformation(r) if err != nil { - log.WithFields("file", filename, "error", err).Trace("unable to read golang version info") + log.WithFields("file", location.RealPath, "error", err).Trace("unable to read golang version info") // don't skip this build info. // we can still catalog packages, even if we can't get the crypto information + errs = unknown.Appendf(errs, location, "unable to read golang version info: %w", err) } arch := getGOARCH(bi.Settings) if arch == "" { arch, err = getGOARCHFromBin(r) if err != nil { - log.WithFields("file", filename, "error", err).Trace("unable to read golang arch info") + log.WithFields("file", location.RealPath, "error", err).Trace("unable to read golang arch info") // don't skip this build info. // we can still catalog packages, even if we can't get the arch information + errs = unknown.Appendf(errs, location, "unable to read golang arch info: %w", err) } } builds = append(builds, &extendedBuildInfo{BuildInfo: bi, cryptoSettings: v, arch: arch}) } - return builds + return builds, errs } func getCryptoInformation(reader io.ReaderAt) ([]string, error) { diff --git a/syft/pkg/cataloger/golang/test-fixtures/corrupt/go.mod b/syft/pkg/cataloger/golang/test-fixtures/corrupt/go.mod new file mode 100644 index 000000000..1e345eec5 --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/corrupt/go.mod @@ -0,0 +1,11 @@ +module github.com/anchore/syft + +go 1.18 + +ruire ( + github.com/CycloneDX/cyclonedx-go v0.7.0 + github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d + github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect +) + +replace github.com/CycloneDX/cyclonedx-go => github.com/CycloneDX/cyclonedx-go v0.6.0 diff --git a/syft/pkg/cataloger/golang/test-fixtures/corrupt/go.sum b/syft/pkg/cataloger/golang/test-fixtures/corrupt/go.sum new file mode 100644 index 000000000..e80236beb --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/corrupt/go.sum @@ -0,0 +1,4 @@ +github.com/CycloneDX/cyclonedx-go v0.6.0/go.mod h1:nQCiF4Tvrg5Ieu8qPhYMvzPGMu5I7fANZkrSsJjl5mg= +github.com/Cycpansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= +github6IF +github.com/stretchr/test4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/syft/pkg/cataloger/haskell/parse_stack_lock.go b/syft/pkg/cataloger/haskell/parse_stack_lock.go index eb8b85475..505e2a612 100644 --- a/syft/pkg/cataloger/haskell/parse_stack_lock.go +++ b/syft/pkg/cataloger/haskell/parse_stack_lock.go @@ -9,6 +9,7 @@ import ( "gopkg.in/yaml.v3" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -50,7 +51,7 @@ func parseStackLock(_ context.Context, _ file.Resolver, _ *generic.Environment, if err := yaml.Unmarshal(bytes, &lockFile); err != nil { log.WithFields("error", err).Tracef("failed to parse stack.yaml.lock file %q", reader.RealPath) - return nil, nil, nil + return nil, nil, fmt.Errorf("failed to parse stack.yaml.lock file") } var ( @@ -82,7 +83,7 @@ func parseStackLock(_ context.Context, _ file.Resolver, _ *generic.Environment, ) } - return pkgs, nil, nil + return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") } func parseStackPackageEncoding(pkgEncoding string) (name, version, hash string) { diff --git a/syft/pkg/cataloger/haskell/parse_stack_lock_test.go b/syft/pkg/cataloger/haskell/parse_stack_lock_test.go index 682aa3432..ee84ae092 100644 --- a/syft/pkg/cataloger/haskell/parse_stack_lock_test.go +++ b/syft/pkg/cataloger/haskell/parse_stack_lock_test.go @@ -130,3 +130,10 @@ func TestParseStackLock(t *testing.T) { pkgtest.TestFileParser(t, fixture, parseStackLock, expectedPkgs, expectedRelationships) } + +func Test_corruptStackLock(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/corrupt/stack.yaml.lock"). + WithError(). + TestParser(t, parseStackLock) +} diff --git a/syft/pkg/cataloger/haskell/parse_stack_yaml.go b/syft/pkg/cataloger/haskell/parse_stack_yaml.go index 4ecb6af96..d762a2b06 100644 --- a/syft/pkg/cataloger/haskell/parse_stack_yaml.go +++ b/syft/pkg/cataloger/haskell/parse_stack_yaml.go @@ -8,6 +8,7 @@ import ( "gopkg.in/yaml.v3" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -31,7 +32,7 @@ func parseStackYaml(_ context.Context, _ file.Resolver, _ *generic.Environment, if err := yaml.Unmarshal(bytes, &stackFile); err != nil { log.WithFields("error", err).Tracef("failed to parse stack.yaml file %q", reader.RealPath) - return nil, nil, nil + return nil, nil, fmt.Errorf("failed to parse stack.yaml file") } var pkgs []pkg.Package @@ -50,5 +51,5 @@ func parseStackYaml(_ context.Context, _ file.Resolver, _ *generic.Environment, ) } - return pkgs, nil, nil + return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") } diff --git a/syft/pkg/cataloger/haskell/parse_stack_yaml_test.go b/syft/pkg/cataloger/haskell/parse_stack_yaml_test.go index 1aa825357..ee4586396 100644 --- a/syft/pkg/cataloger/haskell/parse_stack_yaml_test.go +++ b/syft/pkg/cataloger/haskell/parse_stack_yaml_test.go @@ -110,3 +110,10 @@ func TestParseStackYaml(t *testing.T) { pkgtest.TestFileParser(t, fixture, parseStackYaml, expectedPkgs, expectedRelationships) } + +func Test_corruptStackYaml(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/corrupt/stack.yaml"). + WithError(). + TestParser(t, parseStackYaml) +} diff --git a/syft/pkg/cataloger/haskell/test-fixtures/corrupt/stack.yaml b/syft/pkg/cataloger/haskell/test-fixtures/corrupt/stack.yaml new file mode 100644 index 000000000..918d0bce7 --- /dev/null +++ b/syft/pkg/cataloger/haskell/test-fixtures/corrupt/stack.yaml @@ -0,0 +1,6 @@ +flag +extra-package-dbs: [] +packa@sha256:fbcf49ecfc3d4da53e797fd0275264cba776ffa324ee223e2a3f4ec2d2c9c4a6,2165 + - stm-2.5.0.2@sha256:e4dc6473faaa75fbd7eccab4e3ee1d651d75bb0e49946ef0b8b751ccde771a55,2314 +ghc-options: + "$everything": -haddock diff --git a/syft/pkg/cataloger/haskell/test-fixtures/corrupt/stack.yaml.lock b/syft/pkg/cataloger/haskell/test-fixtures/corrupt/stack.yaml.lock new file mode 100644 index 000000000..138e87ad5 --- /dev/null +++ b/syft/pkg/cataloger/haskell/test-fixtures/corrupt/stack.yaml.lock @@ -0,0 +1,8 @@ +packages +-comp +al: + commit: a5847301404583e16d55cd4d051b8e605d704fbc + git: https://github.com/runtimeverification/haskell-backend.git + subdir: kore +snapshots +- complete//raw.github diff --git a/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go b/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go index ae26bb6d1..96bd79450 100644 --- a/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go +++ b/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go @@ -48,7 +48,6 @@ type CatalogTester struct { func NewCatalogTester() *CatalogTester { return &CatalogTester{ - wantErr: require.NoError, locationComparer: cmptest.DefaultLocationComparer, licenseComparer: cmptest.DefaultLicenseComparer, packageStringer: stringPackage, @@ -113,7 +112,6 @@ func (p *CatalogTester) WithEnv(env *generic.Environment) *CatalogTester { } func (p *CatalogTester) WithError() *CatalogTester { - p.assertResultExpectations = true p.wantErr = require.Error return p } @@ -226,7 +224,10 @@ func (p *CatalogTester) IgnoreUnfulfilledPathResponses(paths ...string) *Catalog func (p *CatalogTester) TestParser(t *testing.T, parser generic.Parser) { t.Helper() pkgs, relationships, err := parser(context.Background(), p.resolver, p.env, p.reader) - p.wantErr(t, err) + // only test for errors if explicitly requested + if p.wantErr != nil { + p.wantErr(t, err) + } p.assertPkgs(t, pkgs, relationships) } @@ -247,8 +248,12 @@ func (p *CatalogTester) TestCataloger(t *testing.T, cataloger pkg.Cataloger) { assert.ElementsMatchf(t, p.expectedContentQueries, resolver.AllContentQueries(), "unexpected content queries observed: diff %s", cmp.Diff(p.expectedContentQueries, resolver.AllContentQueries())) } - if p.assertResultExpectations { + // only test for errors if explicitly requested + if p.wantErr != nil { p.wantErr(t, err) + } + + if p.assertResultExpectations { p.assertPkgs(t, pkgs, relationships) } @@ -256,7 +261,7 @@ func (p *CatalogTester) TestCataloger(t *testing.T, cataloger pkg.Cataloger) { a(t, pkgs, relationships) } - if !p.assertResultExpectations && len(p.customAssertions) == 0 { + if !p.assertResultExpectations && len(p.customAssertions) == 0 && p.wantErr == nil { resolver.PruneUnfulfilledPathResponses(p.ignoreUnfulfilledPathResponses, p.ignoreAnyUnfulfilledPaths...) // if we aren't testing the results, we should focus on what was searched for (for glob-centric tests) diff --git a/syft/pkg/cataloger/java/archive_parser.go b/syft/pkg/cataloger/java/archive_parser.go index 740ad0071..dc5ff5f13 100644 --- a/syft/pkg/cataloger/java/archive_parser.go +++ b/syft/pkg/cataloger/java/archive_parser.go @@ -16,6 +16,7 @@ import ( intFile "github.com/anchore/syft/internal/file" "github.com/anchore/syft/internal/licenses" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -133,14 +134,22 @@ func (j *archiveParser) parse(ctx context.Context) ([]pkg.Package, []artifact.Re } pkgs = append(pkgs, auxPkgs...) + var errs error if j.detectNested { // find nested java archive packages nestedPkgs, nestedRelationships, err := j.discoverPkgsFromNestedArchives(ctx, parentPkg) if err != nil { - return nil, nil, err + errs = unknown.Append(errs, j.location, err) } pkgs = append(pkgs, nestedPkgs...) relationships = append(relationships, nestedRelationships...) + } else { + // .jar and .war files are present in archives, are others? or generally just consider them top-level? + nestedArchives := j.fileManifest.GlobMatch(true, "*.jar", "*.war") + if len(nestedArchives) > 0 { + slices.Sort(nestedArchives) + errs = unknown.Appendf(errs, j.location, "nested archives not cataloged: %v", strings.Join(nestedArchives, ", ")) + } } // lastly, add the parent package to the list (assuming the parent exists) @@ -166,7 +175,11 @@ func (j *archiveParser) parse(ctx context.Context) ([]pkg.Package, []artifact.Re p.SetID() } - return pkgs, relationships, nil + if len(pkgs) == 0 { + errs = unknown.Appendf(errs, j.location, "no package identified in archive") + } + + return pkgs, relationships, errs } // discoverMainPackage parses the root Java manifest used as the parent package to all discovered nested packages. @@ -283,14 +296,14 @@ func (j *archiveParser) findLicenseFromJavaMetadata(ctx context.Context, groupID if parsedPom != nil { pomLicenses, err = j.maven.resolveLicenses(ctx, parsedPom.project) if err != nil { - log.WithFields("error", err, "mavenID", j.maven.getMavenID(ctx, parsedPom.project)).Debug("error attempting to resolve pom licenses") + log.WithFields("error", err, "mavenID", j.maven.getMavenID(ctx, parsedPom.project)).Trace("error attempting to resolve pom licenses") } } if err == nil && len(pomLicenses) == 0 { pomLicenses, err = j.maven.findLicenses(ctx, groupID, artifactID, version) if err != nil { - log.WithFields("error", err, "mavenID", mavenID{groupID, artifactID, version}).Debug("error attempting to find licenses") + log.WithFields("error", err, "mavenID", mavenID{groupID, artifactID, version}).Trace("error attempting to find licenses") } } @@ -300,7 +313,7 @@ func (j *archiveParser) findLicenseFromJavaMetadata(ctx context.Context, groupID groupID = strings.Join(packages[:len(packages)-1], ".") pomLicenses, err = j.maven.findLicenses(ctx, groupID, artifactID, version) if err != nil { - log.WithFields("error", err, "mavenID", mavenID{groupID, artifactID, version}).Debug("error attempting to find sub-group licenses") + log.WithFields("error", err, "mavenID", mavenID{groupID, artifactID, version}).Trace("error attempting to find sub-group licenses") } } @@ -630,7 +643,7 @@ func newPackageFromMavenData(ctx context.Context, r *mavenResolver, pomPropertie } if err != nil { - log.WithFields("error", err, "mavenID", mavenID{pomProperties.GroupID, pomProperties.ArtifactID, pomProperties.Version}).Debug("error attempting to resolve licenses") + log.WithFields("error", err, "mavenID", mavenID{pomProperties.GroupID, pomProperties.ArtifactID, pomProperties.Version}).Trace("error attempting to resolve licenses") } licenses := make([]pkg.License, 0) diff --git a/syft/pkg/cataloger/java/archive_parser_test.go b/syft/pkg/cataloger/java/archive_parser_test.go index 2faf003d2..6fa0acc47 100644 --- a/syft/pkg/cataloger/java/archive_parser_test.go +++ b/syft/pkg/cataloger/java/archive_parser_test.go @@ -91,10 +91,12 @@ func TestParseJar(t *testing.T) { fixture string expected map[string]pkg.Package ignoreExtras []string + wantErr require.ErrorAssertionFunc }{ { name: "example-jenkins-plugin", fixture: "test-fixtures/java-builds/packages/example-jenkins-plugin.hpi", + wantErr: require.Error, // there are nested jars, which are not scanned and result in unknown errors ignoreExtras: []string{ "Plugin-Version", // has dynamic date "Built-By", // podman returns the real UID @@ -153,6 +155,7 @@ func TestParseJar(t *testing.T) { { name: "example-java-app-gradle", fixture: "test-fixtures/java-builds/packages/example-java-app-gradle-0.1.0.jar", + wantErr: require.NoError, // no nested jars expected: map[string]pkg.Package{ "example-java-app-gradle": { Name: "example-java-app-gradle", @@ -226,6 +229,7 @@ func TestParseJar(t *testing.T) { { name: "example-java-app-maven", fixture: "test-fixtures/java-builds/packages/example-java-app-maven-0.1.0.jar", + wantErr: require.NoError, // no nested jars ignoreExtras: []string{ "Build-Jdk", // can't guarantee the JDK used at build time "Built-By", // podman returns the real UID @@ -351,13 +355,15 @@ func TestParseJar(t *testing.T) { require.NoError(t, err) actual, _, err := parser.parse(context.Background()) - require.NoError(t, err) + if test.wantErr != nil { + test.wantErr(t, err) + } if len(actual) != len(test.expected) { for _, a := range actual { t.Log(" ", a) } - t.Fatalf("unexpected package count: %d!=%d", len(actual), len(test.expected)) + t.Fatalf("unexpected package count; expected: %d got: %d", len(test.expected), len(actual)) } var parent *pkg.Package @@ -1488,3 +1494,11 @@ func run(t testing.TB, cmd *exec.Cmd) { func ptr[T any](value T) *T { return &value } + +func Test_corruptJarArchive(t *testing.T) { + ap := newGenericArchiveParserAdapter(DefaultArchiveCatalogerConfig()) + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/corrupt/example.jar"). + WithError(). + TestParser(t, ap.parseJavaArchive) +} diff --git a/syft/pkg/cataloger/java/maven_resolver.go b/syft/pkg/cataloger/java/maven_resolver.go index f9d375b8e..f9e373895 100644 --- a/syft/pkg/cataloger/java/maven_resolver.go +++ b/syft/pkg/cataloger/java/maven_resolver.go @@ -79,7 +79,7 @@ func (r *mavenResolver) resolvePropertyValue(ctx context.Context, propertyValue } resolved, err := r.resolveExpression(ctx, resolutionContext, *propertyValue, resolvingProperties) if err != nil { - log.WithFields("error", err, "propertyValue", *propertyValue).Debug("error resolving maven property") + log.WithFields("error", err, "propertyValue", *propertyValue).Trace("error resolving maven property") return "" } return resolved diff --git a/syft/pkg/cataloger/java/parse_pom_xml.go b/syft/pkg/cataloger/java/parse_pom_xml.go index 370ebc2c8..9a5f391d0 100644 --- a/syft/pkg/cataloger/java/parse_pom_xml.go +++ b/syft/pkg/cataloger/java/parse_pom_xml.go @@ -15,6 +15,7 @@ import ( "github.com/anchore/syft/internal" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -41,11 +42,13 @@ func (p pomXMLCataloger) Catalog(ctx context.Context, fileResolver file.Resolver r := newMavenResolver(fileResolver, p.cfg) + var errs error var poms []*gopom.Project for _, pomLocation := range locations { pom, err := readPomFromLocation(fileResolver, pomLocation) if err != nil || pom == nil { log.WithFields("error", err, "pomLocation", pomLocation).Debug("error while reading pom") + errs = unknown.Appendf(errs, pomLocation, "error reading pom.xml: %w", err) continue } @@ -60,7 +63,7 @@ func (p pomXMLCataloger) Catalog(ctx context.Context, fileResolver file.Resolver for _, pom := range poms { pkgs = append(pkgs, processPomXML(ctx, r, pom, r.pomLocations[pom])...) } - return pkgs, nil, nil + return pkgs, nil, errs } func readPomFromLocation(fileResolver file.Resolver, pomLocation file.Location) (*gopom.Project, error) { diff --git a/syft/pkg/cataloger/java/parse_pom_xml_test.go b/syft/pkg/cataloger/java/parse_pom_xml_test.go index 456500490..f80a67628 100644 --- a/syft/pkg/cataloger/java/parse_pom_xml_test.go +++ b/syft/pkg/cataloger/java/parse_pom_xml_test.go @@ -705,3 +705,11 @@ func getCommonsTextExpectedPackages() []pkg.Package { }, } } + +func Test_corruptPomXml(t *testing.T) { + c := NewPomCataloger(DefaultArchiveCatalogerConfig()) + pkgtest.NewCatalogTester(). + FromDirectory(t, "test-fixtures/corrupt"). + WithError(). + TestCataloger(t, c) +} diff --git a/syft/pkg/cataloger/java/tar_wrapped_archive_parser_test.go b/syft/pkg/cataloger/java/tar_wrapped_archive_parser_test.go index 24b1b55f5..089d19eb1 100644 --- a/syft/pkg/cataloger/java/tar_wrapped_archive_parser_test.go +++ b/syft/pkg/cataloger/java/tar_wrapped_archive_parser_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" ) func Test_parseTarWrappedJavaArchive(t *testing.T) { @@ -57,3 +58,11 @@ func Test_parseTarWrappedJavaArchive(t *testing.T) { }) } } + +func Test_corruptTarArchive(t *testing.T) { + ap := newGenericTarWrappedJavaArchiveParser(DefaultArchiveCatalogerConfig()) + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/corrupt/example.tar"). + WithError(). + TestParser(t, ap.parseTarWrappedJavaArchive) +} diff --git a/syft/pkg/cataloger/java/test-fixtures/corrupt/example.jar b/syft/pkg/cataloger/java/test-fixtures/corrupt/example.jar new file mode 100644 index 000000000..8944cbcc0 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/corrupt/example.jar @@ -0,0 +1 @@ +example archive diff --git a/syft/pkg/cataloger/java/test-fixtures/corrupt/example.tar b/syft/pkg/cataloger/java/test-fixtures/corrupt/example.tar new file mode 100644 index 000000000..8944cbcc0 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/corrupt/example.tar @@ -0,0 +1 @@ +example archive diff --git a/syft/pkg/cataloger/java/test-fixtures/corrupt/pom.xml b/syft/pkg/cataloger/java/test-fixtures/corrupt/pom.xml new file mode 100644 index 000000000..11183e1ab --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/corrupt/pom.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/syft/pkg/cataloger/javascript/parse_package_json.go b/syft/pkg/cataloger/javascript/parse_package_json.go index cc628c772..f3f435690 100644 --- a/syft/pkg/cataloger/javascript/parse_package_json.go +++ b/syft/pkg/cataloger/javascript/parse_package_json.go @@ -11,7 +11,6 @@ import ( "github.com/mitchellh/mapstructure" "github.com/anchore/syft/internal" - "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -64,11 +63,8 @@ func parsePackageJSON(_ context.Context, _ file.Resolver, _ *generic.Environment return nil, nil, fmt.Errorf("failed to parse package.json file: %w", err) } - if !p.hasNameAndVersionValues() { - log.Debugf("encountered package.json file without a name and/or version field, ignoring (path=%q)", reader.Path()) - return nil, nil, nil - } - + // always create a package, regardless of having a valid name and/or version, + // a compliance filter later will remove these packages based on compliance rules pkgs = append( pkgs, newPackageJSONPackage(p, reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), @@ -203,10 +199,6 @@ func licensesFromJSON(b []byte) ([]npmPackageLicense, error) { return nil, errors.New("unmarshal failed") } -func (p packageJSON) hasNameAndVersionValues() bool { - return p.Name != "" && p.Version != "" -} - // this supports both windows and unix paths var filepathSeparator = regexp.MustCompile(`[\\/]`) diff --git a/syft/pkg/cataloger/javascript/parse_package_json_test.go b/syft/pkg/cataloger/javascript/parse_package_json_test.go index 5d6ebaf4a..ea0102d98 100644 --- a/syft/pkg/cataloger/javascript/parse_package_json_test.go +++ b/syft/pkg/cataloger/javascript/parse_package_json_test.go @@ -210,10 +210,28 @@ func TestParsePackageJSON(t *testing.T) { } } +func Test_corruptPackageJSON(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/corrupt/package.json"). + WithError(). + TestParser(t, parsePackageJSON) +} + func TestParsePackageJSON_Partial(t *testing.T) { // see https://github.com/anchore/syft/issues/311 const fixtureFile = "test-fixtures/pkg-json/package-partial.json" - pkgtest.TestFileParser(t, fixtureFile, parsePackageJSON, nil, nil) + // raise package.json files as packages with any information we find, these will be filtered out + // 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)), + }, + } + pkgtest.TestFileParser(t, fixtureFile, parsePackageJSON, expectedPkgs, nil) } func Test_pathContainsNodeModulesDirectory(t *testing.T) { diff --git a/syft/pkg/cataloger/javascript/parse_package_lock.go b/syft/pkg/cataloger/javascript/parse_package_lock.go index 1c7564cc3..ec8a2b600 100644 --- a/syft/pkg/cataloger/javascript/parse_package_lock.go +++ b/syft/pkg/cataloger/javascript/parse_package_lock.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -100,7 +101,7 @@ func (a genericPackageLockAdapter) parsePackageLock(_ context.Context, resolver pkg.Sort(pkgs) - return pkgs, nil, nil + return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") } func (licenses *packageLockLicense) UnmarshalJSON(data []byte) (err error) { diff --git a/syft/pkg/cataloger/javascript/parse_package_lock_test.go b/syft/pkg/cataloger/javascript/parse_package_lock_test.go index 98448bf7b..b3ba527bb 100644 --- a/syft/pkg/cataloger/javascript/parse_package_lock_test.go +++ b/syft/pkg/cataloger/javascript/parse_package_lock_test.go @@ -333,3 +333,11 @@ func TestParsePackageLockLicenseWithArray(t *testing.T) { adapter := newGenericPackageLockAdapter(CatalogerConfig{}) pkgtest.TestFileParser(t, fixture, adapter.parsePackageLock, expectedPkgs, expectedRelationships) } + +func Test_corruptPackageLock(t *testing.T) { + gap := newGenericPackageLockAdapter(DefaultCatalogerConfig()) + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/corrupt/package-lock.json"). + WithError(). + TestParser(t, gap.parsePackageLock) +} diff --git a/syft/pkg/cataloger/javascript/parse_pnpm_lock.go b/syft/pkg/cataloger/javascript/parse_pnpm_lock.go index 4936f7a2b..8c7257a38 100644 --- a/syft/pkg/cataloger/javascript/parse_pnpm_lock.go +++ b/syft/pkg/cataloger/javascript/parse_pnpm_lock.go @@ -11,6 +11,7 @@ import ( "gopkg.in/yaml.v3" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -94,7 +95,7 @@ func parsePnpmLock(_ context.Context, resolver file.Resolver, _ *generic.Environ pkg.Sort(pkgs) - return pkgs, nil, nil + return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") } func hasPkg(pkgs []pkg.Package, name, version string) bool { diff --git a/syft/pkg/cataloger/javascript/parse_pnpm_lock_test.go b/syft/pkg/cataloger/javascript/parse_pnpm_lock_test.go index 7c0ed1c4d..8b5ed7d0a 100644 --- a/syft/pkg/cataloger/javascript/parse_pnpm_lock_test.go +++ b/syft/pkg/cataloger/javascript/parse_pnpm_lock_test.go @@ -144,3 +144,10 @@ func TestParsePnpmV6Lock(t *testing.T) { pkgtest.TestFileParser(t, fixture, parsePnpmLock, expectedPkgs, expectedRelationships) } + +func Test_corruptPnpmLock(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/corrupt/pnpm-lock.yaml"). + WithError(). + TestParser(t, parsePnpmLock) +} diff --git a/syft/pkg/cataloger/javascript/parse_yarn_lock.go b/syft/pkg/cataloger/javascript/parse_yarn_lock.go index 73dcd3001..94aa430a4 100644 --- a/syft/pkg/cataloger/javascript/parse_yarn_lock.go +++ b/syft/pkg/cataloger/javascript/parse_yarn_lock.go @@ -8,6 +8,7 @@ import ( "github.com/scylladb/go-set/strset" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -112,7 +113,7 @@ func (a genericYarnLockAdapter) parseYarnLock(_ context.Context, resolver file.R pkg.Sort(pkgs) - return pkgs, nil, nil + return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") } func findPackageName(line string) string { diff --git a/syft/pkg/cataloger/javascript/test-fixtures/corrupt/package-lock.json b/syft/pkg/cataloger/javascript/test-fixtures/corrupt/package-lock.json new file mode 100644 index 000000000..a13d744c1 --- /dev/null +++ b/syft/pkg/cataloger/javascript/test-fixtures/corrupt/package-lock.json @@ -0,0 +1,4 @@ +{ + "requires": true, + "lockfi +} diff --git a/syft/pkg/cataloger/javascript/test-fixtures/corrupt/package.json b/syft/pkg/cataloger/javascript/test-fixtures/corrupt/package.json new file mode 100644 index 000000000..209f9ad58 --- /dev/null +++ b/syft/pkg/cataloger/javascript/test-fixtures/corrupt/package.json @@ -0,0 +1,5 @@ +{ + "version": "6.14.6", + "name"node": "6 >=6.2.0 || 8 || >=9.3.0" + } +} \ No newline at end of file diff --git a/syft/pkg/cataloger/javascript/test-fixtures/corrupt/pnpm-lock.yaml b/syft/pkg/cataloger/javascript/test-fixtures/corrupt/pnpm-lock.yaml new file mode 100644 index 000000000..5717c62b4 --- /dev/null +++ b/syft/pkg/cataloger/javascript/test-fixtures/corrupt/pnpm-lock.yaml @@ -0,0 +1,7 @@ +lockfileVersion: 5.4 + +specifi +lution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + dev: true + + # removed other packages diff --git a/syft/pkg/cataloger/kernel/cataloger.go b/syft/pkg/cataloger/kernel/cataloger.go index d0cc4d131..877e9819b 100644 --- a/syft/pkg/cataloger/kernel/cataloger.go +++ b/syft/pkg/cataloger/kernel/cataloger.go @@ -6,9 +6,8 @@ package kernel import ( "context" - "github.com/hashicorp/go-multierror" - "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -62,7 +61,7 @@ func (l linuxKernelCataloger) Catalog(ctx context.Context, resolver file.Resolve kernelPackages, kernelRelationships, err := generic.NewCataloger(l.Name()).WithParserByGlobs(parseLinuxKernelFile, kernelArchiveGlobs...).Catalog(ctx, resolver) if err != nil { - errs = multierror.Append(errs, err) + errs = unknown.Join(errs, err) } allRelationships = append(allRelationships, kernelRelationships...) @@ -71,7 +70,7 @@ func (l linuxKernelCataloger) Catalog(ctx context.Context, resolver file.Resolve if l.cfg.CatalogModules { modulePackages, moduleRelationships, err := generic.NewCataloger(l.Name()).WithParserByGlobs(parseLinuxKernelModuleFile, kernelModuleGlobs...).Catalog(ctx, resolver) if err != nil { - errs = multierror.Append(errs, err) + errs = unknown.Join(errs, err) } allPackages = append(allPackages, modulePackages...) diff --git a/syft/pkg/cataloger/lua/parse_rockspec.go b/syft/pkg/cataloger/lua/parse_rockspec.go index a11709fa8..de109e77e 100644 --- a/syft/pkg/cataloger/lua/parse_rockspec.go +++ b/syft/pkg/cataloger/lua/parse_rockspec.go @@ -2,6 +2,7 @@ package lua import ( "context" + "fmt" "strings" "github.com/anchore/syft/internal/log" @@ -30,7 +31,7 @@ func parseRockspec(_ context.Context, _ file.Resolver, _ *generic.Environment, r doc, err := parseRockspecData(reader) if err != nil { log.WithFields("error", err).Trace("unable to parse Rockspec app") - return nil, nil, nil + return nil, nil, fmt.Errorf("unable to parse Rockspec app: %w", err) } var name, version, license, homepage, description, url string diff --git a/syft/pkg/cataloger/lua/parse_rockspec_test.go b/syft/pkg/cataloger/lua/parse_rockspec_test.go index f429a9dc7..a85cda58c 100644 --- a/syft/pkg/cataloger/lua/parse_rockspec_test.go +++ b/syft/pkg/cataloger/lua/parse_rockspec_test.go @@ -106,3 +106,10 @@ func TestParseRockspec(t *testing.T) { }) } } + +func Test_corruptRockspec(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/corrupt/bad-1.23.0-0.rockspec"). + WithError(). + TestParser(t, parseRockspec) +} diff --git a/syft/pkg/cataloger/lua/test-fixtures/corrupt/bad-1.23.0-0.rockspec b/syft/pkg/cataloger/lua/test-fixtures/corrupt/bad-1.23.0-0.rockspec new file mode 100644 index 000000000..d2ed1d025 --- /dev/null +++ b/syft/pkg/cataloger/lua/test-fixtures/corrupt/bad-1.23.0-0.rockspec @@ -0,0 +1,5 @@ +package = {"kon + +3.7.0-0" +rockspec_fo} +} diff --git a/syft/pkg/cataloger/php/parse_composer_lock.go b/syft/pkg/cataloger/php/parse_composer_lock.go index 4abb66c24..5348e6ffc 100644 --- a/syft/pkg/cataloger/php/parse_composer_lock.go +++ b/syft/pkg/cataloger/php/parse_composer_lock.go @@ -7,6 +7,7 @@ import ( "fmt" "io" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -48,5 +49,5 @@ func parseComposerLock(_ context.Context, _ file.Resolver, _ *generic.Environmen } } - return pkgs, nil, nil + return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") } diff --git a/syft/pkg/cataloger/php/parse_composer_lock_test.go b/syft/pkg/cataloger/php/parse_composer_lock_test.go index ae01097e2..1da97c42d 100644 --- a/syft/pkg/cataloger/php/parse_composer_lock_test.go +++ b/syft/pkg/cataloger/php/parse_composer_lock_test.go @@ -113,3 +113,10 @@ func TestParseComposerFileLock(t *testing.T) { } pkgtest.TestFileParser(t, fixture, parseComposerLock, expectedPkgs, expectedRelationships) } + +func Test_corruptComposerLock(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/glob-paths/src/composer.lock"). + WithError(). + TestParser(t, parseComposerLock) +} diff --git a/syft/pkg/cataloger/php/parse_installed_json.go b/syft/pkg/cataloger/php/parse_installed_json.go index f1498d931..b7c7d9d32 100644 --- a/syft/pkg/cataloger/php/parse_installed_json.go +++ b/syft/pkg/cataloger/php/parse_installed_json.go @@ -7,6 +7,7 @@ import ( "fmt" "io" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -69,5 +70,5 @@ func parseInstalledJSON(_ context.Context, _ file.Resolver, _ *generic.Environme } } - return pkgs, nil, nil + return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") } diff --git a/syft/pkg/cataloger/php/parse_installed_json_test.go b/syft/pkg/cataloger/php/parse_installed_json_test.go index abc29863c..7e0c06c32 100644 --- a/syft/pkg/cataloger/php/parse_installed_json_test.go +++ b/syft/pkg/cataloger/php/parse_installed_json_test.go @@ -142,3 +142,10 @@ func TestParseInstalledJsonComposerV1(t *testing.T) { }) } } + +func Test_corruptInstalledJSON(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/glob-paths/src/installed.json"). + WithError(). + TestParser(t, parseInstalledJSON) +} diff --git a/syft/pkg/cataloger/php/parse_pecl_serialized_test.go b/syft/pkg/cataloger/php/parse_pecl_serialized_test.go index 7f685ffda..84f84ea72 100644 --- a/syft/pkg/cataloger/php/parse_pecl_serialized_test.go +++ b/syft/pkg/cataloger/php/parse_pecl_serialized_test.go @@ -33,3 +33,10 @@ func TestParsePeclSerialized(t *testing.T) { } pkgtest.TestFileParser(t, fixture, parsePeclSerialized, expectedPkgs, expectedRelationships) } + +func Test_corruptPecl(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/glob-paths/php/.registry/.channel.pecl.php.net/memcached.reg"). + WithError(). + TestParser(t, parseComposerLock) +} diff --git a/syft/pkg/cataloger/python/parse_pipfile_lock_test.go b/syft/pkg/cataloger/python/parse_pipfile_lock_test.go index 60ec99c70..051bfd78a 100644 --- a/syft/pkg/cataloger/python/parse_pipfile_lock_test.go +++ b/syft/pkg/cataloger/python/parse_pipfile_lock_test.go @@ -80,3 +80,10 @@ func TestParsePipFileLock(t *testing.T) { pkgtest.TestFileParser(t, fixture, parsePipfileLock, expectedPkgs, expectedRelationships) } + +func Test_corruptPipfileLock(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/glob-paths/src/Pipfile.lock"). + WithError(). + TestParser(t, parsePipfileLock) +} diff --git a/syft/pkg/cataloger/python/parse_poetry_lock.go b/syft/pkg/cataloger/python/parse_poetry_lock.go index 84e67ddb5..2b75f51b8 100644 --- a/syft/pkg/cataloger/python/parse_poetry_lock.go +++ b/syft/pkg/cataloger/python/parse_poetry_lock.go @@ -8,6 +8,7 @@ import ( "github.com/BurntSushi/toml" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -57,7 +58,7 @@ func parsePoetryLock(_ context.Context, _ file.Resolver, _ *generic.Environment, // since we would never expect to create relationships for packages across multiple poetry.lock files // we should do this on a file parser level (each poetry.lock) instead of a cataloger level (across all // poetry.lock files) - return pkgs, dependency.Resolve(poetryLockDependencySpecifier, pkgs), nil + return pkgs, dependency.Resolve(poetryLockDependencySpecifier, pkgs), unknown.IfEmptyf(pkgs, "unable to determine packages") } func poetryLockPackages(reader file.LocationReadCloser) ([]pkg.Package, error) { diff --git a/syft/pkg/cataloger/python/parse_poetry_lock_test.go b/syft/pkg/cataloger/python/parse_poetry_lock_test.go index 1a6c1beb7..0cb0030a2 100644 --- a/syft/pkg/cataloger/python/parse_poetry_lock_test.go +++ b/syft/pkg/cataloger/python/parse_poetry_lock_test.go @@ -81,3 +81,10 @@ func TestParsePoetryLock(t *testing.T) { pkgtest.TestFileParser(t, fixture, parsePoetryLock, expectedPkgs, expectedRelationships) } + +func Test_corruptPoetryLock(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/glob-paths/src/poetry.lock"). + WithError(). + TestParser(t, parsePoetryLock) +} diff --git a/syft/pkg/cataloger/python/parse_requirements.go b/syft/pkg/cataloger/python/parse_requirements.go index 38bbde3e8..7d5d1d8a4 100644 --- a/syft/pkg/cataloger/python/parse_requirements.go +++ b/syft/pkg/cataloger/python/parse_requirements.go @@ -13,6 +13,7 @@ import ( "github.com/anchore/syft/internal" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -94,6 +95,7 @@ func newRequirementsParser(cfg CatalogerConfig) requirementsParser { // parseRequirementsTxt takes a Python requirements.txt file, returning all Python packages that are locked to a // specific version. func (rp requirementsParser) parseRequirementsTxt(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { + var errs error var packages []pkg.Package scanner := bufio.NewScanner(reader) @@ -126,6 +128,7 @@ func (rp requirementsParser) parseRequirementsTxt(_ context.Context, _ file.Reso req := newRequirement(line) if req == nil { log.WithFields("path", reader.RealPath).Warnf("unable to parse requirements.txt line: %q", line) + errs = unknown.Appendf(errs, reader, "unable to parse requirements.txt line: %q", line) continue } @@ -134,6 +137,7 @@ func (rp requirementsParser) parseRequirementsTxt(_ context.Context, _ file.Reso if version == "" { log.WithFields("path", reader.RealPath).Tracef("unable to determine package version in requirements.txt line: %q", line) + errs = unknown.Appendf(errs, reader, "unable to determine package version in requirements.txt line: %q", line) continue } @@ -158,7 +162,7 @@ func (rp requirementsParser) parseRequirementsTxt(_ context.Context, _ file.Reso return nil, nil, fmt.Errorf("failed to parse python requirements file: %w", err) } - return packages, nil, nil + return packages, nil, unknown.Join(errs, unknown.IfEmptyf(packages, "unable to determine packages")) } func parseVersion(version string, guessFromConstraint bool) string { diff --git a/syft/pkg/cataloger/python/parse_requirements_test.go b/syft/pkg/cataloger/python/parse_requirements_test.go index cd796955c..6573b13d6 100644 --- a/syft/pkg/cataloger/python/parse_requirements_test.go +++ b/syft/pkg/cataloger/python/parse_requirements_test.go @@ -353,3 +353,11 @@ func Test_parseVersion(t *testing.T) { }) } } + +func Test_corruptRequirementsTxt(t *testing.T) { + rp := newRequirementsParser(DefaultCatalogerConfig()) + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/glob-paths/src/requirements.txt"). + WithError(). + TestParser(t, rp.parseRequirementsTxt) +} diff --git a/syft/pkg/cataloger/redhat/parse_rpm_archive_test.go b/syft/pkg/cataloger/redhat/parse_rpm_archive_test.go index dddf81a9c..287c63c0b 100644 --- a/syft/pkg/cataloger/redhat/parse_rpm_archive_test.go +++ b/syft/pkg/cataloger/redhat/parse_rpm_archive_test.go @@ -94,3 +94,10 @@ func TestParseRpmFiles(t *testing.T) { }) } } + +func Test_corruptRpmArchive(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/bad/bad.rpm"). + WithError(). + TestParser(t, parseRpmArchive) +} diff --git a/syft/pkg/cataloger/redhat/parse_rpm_db.go b/syft/pkg/cataloger/redhat/parse_rpm_db.go index 23c5dd487..785b2c9ad 100644 --- a/syft/pkg/cataloger/redhat/parse_rpm_db.go +++ b/syft/pkg/cataloger/redhat/parse_rpm_db.go @@ -9,6 +9,7 @@ import ( rpmdb "github.com/knqyf263/go-rpmdb/pkg" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/linux" @@ -59,11 +60,15 @@ func parseRpmDB(_ context.Context, resolver file.Resolver, env *generic.Environm distro = env.LinuxRelease } + var errs error for _, entry := range pkgList { if entry == nil { continue } + files, err := extractRpmFileRecords(resolver, *entry) + errs = unknown.Join(errs, err) + metadata := pkg.RpmDBEntry{ Name: entry.Name, Version: entry.Version, @@ -74,7 +79,7 @@ func parseRpmDB(_ context.Context, resolver file.Resolver, env *generic.Environm Vendor: entry.Vendor, Size: entry.Size, ModularityLabel: &entry.Modularitylabel, - Files: extractRpmFileRecords(resolver, *entry), + Files: files, Provides: entry.Provides, Requires: entry.Requires, } @@ -89,6 +94,7 @@ func parseRpmDB(_ context.Context, resolver file.Resolver, env *generic.Environm if !pkg.IsValid(&p) { log.WithFields("location", reader.RealPath, "pkg", fmt.Sprintf("%s@%s", entry.Name, entry.Version)). Warn("ignoring invalid package found in RPM DB") + errs = unknown.Appendf(errs, reader, "invalild package found; name: %s, version: %s", entry.Name, entry.Version) continue } @@ -96,7 +102,11 @@ func parseRpmDB(_ context.Context, resolver file.Resolver, env *generic.Environm allPkgs = append(allPkgs, p) } - return allPkgs, nil, nil + if errs == nil && len(allPkgs) == 0 { + errs = fmt.Errorf("unable to determine packages") + } + + return allPkgs, nil, errs } // The RPM naming scheme is [name]-[version]-[release]-[arch], where version is implicitly expands to [epoch]:[version]. @@ -112,13 +122,13 @@ func toELVersion(epoch *int, version, release string) string { return fmt.Sprintf("%s-%s", version, release) } -func extractRpmFileRecords(resolver file.PathResolver, entry rpmdb.PackageInfo) []pkg.RpmFileRecord { +func extractRpmFileRecords(resolver file.PathResolver, entry rpmdb.PackageInfo) ([]pkg.RpmFileRecord, error) { var records = make([]pkg.RpmFileRecord, 0) files, err := entry.InstalledFiles() if err != nil { log.Warnf("unable to parse listing of installed files for RPM DB entry: %s", err.Error()) - return records + return records, fmt.Errorf("unable to parse listing of installed files for RPM DB entry: %w", err) } for _, record := range files { @@ -138,5 +148,5 @@ func extractRpmFileRecords(resolver file.PathResolver, entry rpmdb.PackageInfo) }) } } - return records + return records, nil } diff --git a/syft/pkg/cataloger/redhat/parse_rpm_db_test.go b/syft/pkg/cataloger/redhat/parse_rpm_db_test.go index a1da93618..7572642c8 100644 --- a/syft/pkg/cataloger/redhat/parse_rpm_db_test.go +++ b/syft/pkg/cataloger/redhat/parse_rpm_db_test.go @@ -214,6 +214,13 @@ func TestToElVersion(t *testing.T) { } } +func Test_corruptRpmDbEntry(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/glob-paths/usr/lib/sysimage/rpm/Packages.db"). + WithError(). + TestParser(t, parseRpmDB) +} + func intRef(i int) *int { return &i } diff --git a/syft/pkg/cataloger/redhat/parse_rpm_manifest.go b/syft/pkg/cataloger/redhat/parse_rpm_manifest.go index 9c0185aef..3e44ba8fd 100644 --- a/syft/pkg/cataloger/redhat/parse_rpm_manifest.go +++ b/syft/pkg/cataloger/redhat/parse_rpm_manifest.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -53,5 +54,5 @@ func parseRpmManifest(_ context.Context, _ file.Resolver, _ *generic.Environment allPkgs = append(allPkgs, p) } - return allPkgs, nil, nil + return allPkgs, nil, unknown.IfEmptyf(allPkgs, "unable to determine packages") } diff --git a/syft/pkg/cataloger/ruby/parse_gemfile_lock.go b/syft/pkg/cataloger/ruby/parse_gemfile_lock.go index 6c5432db8..748727bcc 100644 --- a/syft/pkg/cataloger/ruby/parse_gemfile_lock.go +++ b/syft/pkg/cataloger/ruby/parse_gemfile_lock.go @@ -7,6 +7,7 @@ import ( "github.com/scylladb/go-set/strset" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -54,7 +55,7 @@ func parseGemFileLockEntries(_ context.Context, _ file.Resolver, _ *generic.Envi if err := scanner.Err(); err != nil { return nil, nil, err } - return pkgs, nil, nil + return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") } func isDependencyLine(line string) bool { diff --git a/syft/pkg/cataloger/rust/cataloger_test.go b/syft/pkg/cataloger/rust/cataloger_test.go index 494b8cfbf..3a7a356db 100644 --- a/syft/pkg/cataloger/rust/cataloger_test.go +++ b/syft/pkg/cataloger/rust/cataloger_test.go @@ -97,3 +97,10 @@ func Test_AuditBinaryCataloger_Globs(t *testing.T) { }) } } + +func Test_corruptAuditBinary(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/glob-paths/partial-binary"). + WithError(). + TestParser(t, parseAuditBinary) +} diff --git a/syft/pkg/cataloger/rust/parse_audit_binary.go b/syft/pkg/cataloger/rust/parse_audit_binary.go index afa09a058..25525e916 100644 --- a/syft/pkg/cataloger/rust/parse_audit_binary.go +++ b/syft/pkg/cataloger/rust/parse_audit_binary.go @@ -3,6 +3,7 @@ package rust import ( "context" "errors" + "fmt" rustaudit "github.com/microsoft/go-rustaudit" @@ -23,21 +24,22 @@ func parseAuditBinary(_ context.Context, _ file.Resolver, _ *generic.Environment return nil, nil, err } - for _, versionInfo := range parseAuditBinaryEntry(unionReader, reader.RealPath) { + infos, err := parseAuditBinaryEntry(unionReader, reader.RealPath) + for _, versionInfo := range infos { pkgs = append(pkgs, newPackagesFromAudit(reader.Location, versionInfo)...) } - return pkgs, nil, nil + return pkgs, nil, err } // scanFile scans file to try to report the Rust crate dependencies -func parseAuditBinaryEntry(reader unionreader.UnionReader, filename string) []rustaudit.VersionInfo { +func parseAuditBinaryEntry(reader unionreader.UnionReader, filename string) ([]rustaudit.VersionInfo, error) { // NOTE: multiple readers are returned to cover universal binaries, which are files // with more than one binary readers, err := unionreader.GetReaders(reader) if err != nil { log.Warnf("rust cataloger: failed to open a binary: %v", err) - return nil + return nil, fmt.Errorf("rust cataloger: failed to open a binary: %w", err) } var versionInfos []rustaudit.VersionInfo @@ -48,14 +50,14 @@ func parseAuditBinaryEntry(reader unionreader.UnionReader, filename string) []ru if errors.Is(err, rustaudit.ErrNoRustDepInfo) { // since the cataloger can only select executables and not distinguish if they are a Rust-compiled // binary, we should not show warnings/logs in this case. - return nil + return nil, nil } log.Tracef("rust cataloger: unable to read dependency information (file=%q): %v", filename, err) - return nil + return nil, fmt.Errorf("rust cataloger: unable to read dependency information: %w", err) } versionInfos = append(versionInfos, versionInfo) } - return versionInfos + return versionInfos, nil } diff --git a/syft/pkg/cataloger/rust/parse_cargo_lock.go b/syft/pkg/cataloger/rust/parse_cargo_lock.go index d1ef3db12..01e9fd87e 100644 --- a/syft/pkg/cataloger/rust/parse_cargo_lock.go +++ b/syft/pkg/cataloger/rust/parse_cargo_lock.go @@ -6,6 +6,7 @@ import ( "github.com/pelletier/go-toml" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -46,5 +47,5 @@ func parseCargoLock(_ context.Context, _ file.Resolver, _ *generic.Environment, ) } - return pkgs, nil, nil + return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") } diff --git a/syft/pkg/cataloger/rust/parse_cargo_lock_test.go b/syft/pkg/cataloger/rust/parse_cargo_lock_test.go index 6e12fb809..423929779 100644 --- a/syft/pkg/cataloger/rust/parse_cargo_lock_test.go +++ b/syft/pkg/cataloger/rust/parse_cargo_lock_test.go @@ -191,3 +191,10 @@ func TestParseCargoLock(t *testing.T) { pkgtest.TestFileParser(t, fixture, parseCargoLock, expectedPkgs, expectedRelationships) } + +func Test_corruptCargoLock(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/glob-paths/src/Cargo.lock"). + WithError(). + TestParser(t, parseCargoLock) +} diff --git a/syft/pkg/cataloger/sbom/cataloger_test.go b/syft/pkg/cataloger/sbom/cataloger_test.go index ad6aea71d..e53b14ae7 100644 --- a/syft/pkg/cataloger/sbom/cataloger_test.go +++ b/syft/pkg/cataloger/sbom/cataloger_test.go @@ -450,3 +450,10 @@ func Test_Cataloger_Globs(t *testing.T) { }) } } + +func Test_corruptSBOM(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/glob-paths/app.spdx.json"). + WithError(). + TestParser(t, parseSBOM) +} diff --git a/syft/pkg/cataloger/swift/parse_package_resolved.go b/syft/pkg/cataloger/swift/parse_package_resolved.go index cba7f54b3..4fc3965c9 100644 --- a/syft/pkg/cataloger/swift/parse_package_resolved.go +++ b/syft/pkg/cataloger/swift/parse_package_resolved.go @@ -8,6 +8,7 @@ import ( "io" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -71,7 +72,7 @@ func parsePackageResolved(_ context.Context, _ file.Resolver, _ *generic.Environ if packageResolvedData["version"] == nil { log.Trace("no version found in Package.resolved file, skipping") - return nil, nil, nil + return nil, nil, fmt.Errorf("no version found in Package.resolved file") } version, ok := packageResolvedData["version"].(float64) @@ -97,7 +98,7 @@ func parsePackageResolved(_ context.Context, _ file.Resolver, _ *generic.Environ ), ) } - return pkgs, nil, nil + return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") } func pinsForVersion(data map[string]interface{}, version float64) ([]packagePin, error) { diff --git a/syft/pkg/cataloger/swift/parse_package_resolved_test.go b/syft/pkg/cataloger/swift/parse_package_resolved_test.go index 499e705f6..bf16d7542 100644 --- a/syft/pkg/cataloger/swift/parse_package_resolved_test.go +++ b/syft/pkg/cataloger/swift/parse_package_resolved_test.go @@ -134,3 +134,10 @@ func TestParsePackageResolved_versionNotANumber(t *testing.T) { pkgtest.NewCatalogTester().FromFile(t, fixture).WithError().TestParser(t, parsePackageResolved) } + +func Test_corruptPackageResolved(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/bad-version-packages.resolved"). + WithError(). + TestParser(t, parsePackageResolved) +} diff --git a/syft/pkg/cataloger/swift/parse_podfile_lock.go b/syft/pkg/cataloger/swift/parse_podfile_lock.go index 680dd0caa..43803a9f8 100644 --- a/syft/pkg/cataloger/swift/parse_podfile_lock.go +++ b/syft/pkg/cataloger/swift/parse_podfile_lock.go @@ -8,6 +8,7 @@ import ( "gopkg.in/yaml.v3" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -71,5 +72,5 @@ func parsePodfileLock(_ context.Context, _ file.Resolver, _ *generic.Environment ) } - return pkgs, nil, nil + return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") } diff --git a/syft/pkg/cataloger/swift/parse_podfile_lock_test.go b/syft/pkg/cataloger/swift/parse_podfile_lock_test.go index 4a3ec2bbc..0abdd0d7c 100644 --- a/syft/pkg/cataloger/swift/parse_podfile_lock_test.go +++ b/syft/pkg/cataloger/swift/parse_podfile_lock_test.go @@ -273,3 +273,10 @@ func TestParsePodfileLock(t *testing.T) { pkgtest.TestFileParser(t, fixture, parsePodfileLock, expectedPkgs, expectedRelationships) } + +func Test_corruptPodfile(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, "test-fixtures/glob-paths/src/Podfile.lock"). + WithError(). + TestParser(t, parsePodfileLock) +} diff --git a/syft/sbom/sbom.go b/syft/sbom/sbom.go index ba3f95f3d..1c8cbc60f 100644 --- a/syft/sbom/sbom.go +++ b/syft/sbom/sbom.go @@ -26,6 +26,7 @@ type Artifacts struct { FileContents map[file.Coordinates]string FileLicenses map[file.Coordinates][]file.License Executables map[file.Coordinates]file.Executable + Unknowns map[file.Coordinates][]string LinuxDistribution *linux.Release } @@ -62,6 +63,9 @@ func (s SBOM) AllCoordinates() []file.Coordinates { for coordinates := range s.Artifacts.FileDigests { set.Add(coordinates) } + for coordinates := range s.Artifacts.Unknowns { + set.Add(coordinates) + } for _, relationship := range s.Relationships { for _, coordinates := range extractCoordinates(relationship) { set.Add(coordinates) diff --git a/test/cli/test-fixtures/image-unknowns/Dockerfile b/test/cli/test-fixtures/image-unknowns/Dockerfile new file mode 100644 index 000000000..503f6808d --- /dev/null +++ b/test/cli/test-fixtures/image-unknowns/Dockerfile @@ -0,0 +1,3 @@ +FROM alpine@sha256:c5c5fda71656f28e49ac9c5416b3643eaa6a108a8093151d6d1afc9463be8e33 +RUN rm -rf /lib/apk/db/installed +COPY . /home/files diff --git a/test/cli/test-fixtures/image-unknowns/exe b/test/cli/test-fixtures/image-unknowns/exe new file mode 100644 index 000000000..e69de29bb diff --git a/test/cli/test-fixtures/image-unknowns/executable-script b/test/cli/test-fixtures/image-unknowns/executable-script new file mode 100755 index 000000000..07c90f31c --- /dev/null +++ b/test/cli/test-fixtures/image-unknowns/executable-script @@ -0,0 +1,2 @@ +#!/bin/sh +echo "hello" diff --git a/test/cli/test-fixtures/image-unknowns/package-lock.json b/test/cli/test-fixtures/image-unknowns/package-lock.json new file mode 100644 index 000000000..6649985c5 --- /dev/null +++ b/test/cli/test-fixtures/image-unknowns/package-lock.json @@ -0,0 +1,3 @@ +invalid [{ + +}] \ No newline at end of file diff --git a/test/cli/test-fixtures/image-unknowns/unextracted.tar.gz b/test/cli/test-fixtures/image-unknowns/unextracted.tar.gz new file mode 100644 index 000000000..e69de29bb diff --git a/test/cli/test-fixtures/image-unknowns/unextracted.zip b/test/cli/test-fixtures/image-unknowns/unextracted.zip new file mode 100644 index 000000000..e69de29bb diff --git a/test/cli/test-fixtures/image-unknowns/unknown-readable.jar b/test/cli/test-fixtures/image-unknowns/unknown-readable.jar new file mode 100644 index 0000000000000000000000000000000000000000..a4defd8b54f2c8d6d4ca6ce5e1d326c2d14e9d18 GIT binary patch literal 209 zcmWIWW@Zs#-~hsFVaFmEpgJ|J0ew`sW^a`JOuw9&pOz?8%eikC+$&yxBQg%r4%R1S$fV7vRmvB*Kia g3t0|i7Yw{@1hI&)Il!Bh4WyJ22m^t17Kp Date: Wed, 9 Oct 2024 08:06:49 -0400 Subject: [PATCH 250/284] chore(deps): bump actions/upload-artifact from 4.4.0 to 4.4.1 (#3309) --- .github/workflows/benchmark-testing.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/benchmark-testing.yaml b/.github/workflows/benchmark-testing.yaml index ea29b9927..7735a2299 100644 --- a/.github/workflows/benchmark-testing.yaml +++ b/.github/workflows/benchmark-testing.yaml @@ -39,7 +39,7 @@ jobs: OUTPUT="${OUTPUT//$'\r'/'%0D'}" # URL encode all '\r' characters echo "result=$OUTPUT" >> $GITHUB_OUTPUT - - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + - uses: actions/upload-artifact@604373da6381bf24206979c74d06a550515601b9 # v4.4.1 with: name: benchmark-test-results path: test/results/**/* From 56ed1312475d8a085a20537edf3bcb14d0579bb1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Oct 2024 08:07:14 -0400 Subject: [PATCH 251/284] chore(deps): bump actions/checkout from 4.2.0 to 4.2.1 (#3308) --- .github/workflows/benchmark-testing.yaml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/detect-schema-changes.yaml | 2 +- .github/workflows/release-version-file.yaml | 2 +- .github/workflows/release.yaml | 4 ++-- .../workflows/test-fixture-cache-publish.yaml | 2 +- .github/workflows/update-bootstrap-tools.yml | 2 +- .../workflows/update-cpe-dictionary-index.yml | 2 +- .github/workflows/update-stereoscope-release.yml | 2 +- .github/workflows/validations.yaml | 16 ++++++++-------- 10 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/benchmark-testing.yaml b/.github/workflows/benchmark-testing.yaml index 7735a2299..fc0fd5966 100644 --- a/.github/workflows/benchmark-testing.yaml +++ b/.github/workflows/benchmark-testing.yaml @@ -17,7 +17,7 @@ jobs: # the job by event. steps: - name: Checkout code - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Bootstrap environment uses: ./.github/actions/bootstrap diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 40cdaa41f..c87f64936 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -36,7 +36,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 - name: Install Go uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 #v5.0.2 diff --git a/.github/workflows/detect-schema-changes.yaml b/.github/workflows/detect-schema-changes.yaml index 77e211a56..3058795ba 100644 --- a/.github/workflows/detect-schema-changes.yaml +++ b/.github/workflows/detect-schema-changes.yaml @@ -30,7 +30,7 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 - run: python .github/scripts/labeler.py env: diff --git a/.github/workflows/release-version-file.yaml b/.github/workflows/release-version-file.yaml index cc18ef418..5e18b5fde 100644 --- a/.github/workflows/release-version-file.yaml +++ b/.github/workflows/release-version-file.yaml @@ -20,7 +20,7 @@ jobs: release: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 - name: Update version file run: make ci-release-version-file diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index b581dc147..4ce1db1d5 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -15,7 +15,7 @@ jobs: environment: release runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 - name: Check if running on main if: github.ref != 'refs/heads/main' @@ -105,7 +105,7 @@ jobs: # required for goreleaser signs section with cosign id-token: write steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 with: fetch-depth: 0 diff --git a/.github/workflows/test-fixture-cache-publish.yaml b/.github/workflows/test-fixture-cache-publish.yaml index bd23cf1ce..f5b1c4afa 100644 --- a/.github/workflows/test-fixture-cache-publish.yaml +++ b/.github/workflows/test-fixture-cache-publish.yaml @@ -18,7 +18,7 @@ jobs: permissions: packages: write steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 - name: Bootstrap environment uses: ./.github/actions/bootstrap diff --git a/.github/workflows/update-bootstrap-tools.yml b/.github/workflows/update-bootstrap-tools.yml index 04bbeb261..adf415797 100644 --- a/.github/workflows/update-bootstrap-tools.yml +++ b/.github/workflows/update-bootstrap-tools.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'anchore/syft' # only run for main repo steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 - name: Bootstrap environment uses: ./.github/actions/bootstrap diff --git a/.github/workflows/update-cpe-dictionary-index.yml b/.github/workflows/update-cpe-dictionary-index.yml index 5f7de622c..9b492c619 100644 --- a/.github/workflows/update-cpe-dictionary-index.yml +++ b/.github/workflows/update-cpe-dictionary-index.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'anchore/syft' # only run for main repo steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 - name: Bootstrap environment uses: ./.github/actions/bootstrap diff --git a/.github/workflows/update-stereoscope-release.yml b/.github/workflows/update-stereoscope-release.yml index 6ea3bb6fa..002e3a84e 100644 --- a/.github/workflows/update-stereoscope-release.yml +++ b/.github/workflows/update-stereoscope-release.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'anchore/syft' # only run for main repo steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 #v5.0.2 with: diff --git a/.github/workflows/validations.yaml b/.github/workflows/validations.yaml index 9ec3e39ef..b33d039aa 100644 --- a/.github/workflows/validations.yaml +++ b/.github/workflows/validations.yaml @@ -17,7 +17,7 @@ jobs: name: "Static analysis" runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -31,7 +31,7 @@ jobs: name: "Unit tests" runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -47,7 +47,7 @@ jobs: name: "Integration tests" runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -65,7 +65,7 @@ jobs: name: "Build snapshot artifacts" runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -95,7 +95,7 @@ jobs: needs: [Build-Snapshot-Artifacts] runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -141,7 +141,7 @@ jobs: - name: Install Cosign uses: sigstore/cosign-installer@v3.7.0 - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -178,7 +178,7 @@ jobs: needs: [Build-Snapshot-Artifacts] runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -215,7 +215,7 @@ jobs: - Acceptance-Mac - Cli-Linux steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 - name: Delete snapshot cache run: gh cache delete "snapshot-build-${{ github.run_id }}" From 5d165e0230403821efd0608500b7cdd1e66316c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Oct 2024 08:07:36 -0400 Subject: [PATCH 252/284] chore(deps): bump github/codeql-action from 3.26.11 to 3.26.12 (#3307) --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c87f64936..7426f84b0 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@6db8d6351fd0be61f9ed8ebd12ccd35dcec51fea #v3.26.11 + uses: github/codeql-action/init@c36620d31ac7c881962c3d9dd939c40ec9434f2b #v3.26.12 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@6db8d6351fd0be61f9ed8ebd12ccd35dcec51fea #v3.26.11 + uses: github/codeql-action/autobuild@c36620d31ac7c881962c3d9dd939c40ec9434f2b #v3.26.12 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@6db8d6351fd0be61f9ed8ebd12ccd35dcec51fea #v3.26.11 + uses: github/codeql-action/analyze@c36620d31ac7c881962c3d9dd939c40ec9434f2b #v3.26.12 From 5d068f30c009d2af2b106384b2e5118ba9b3e60a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Oct 2024 06:01:06 -0400 Subject: [PATCH 253/284] chore(deps): bump actions/cache from 4.1.0 to 4.1.1 (#3312) --- .github/workflows/benchmark-testing.yaml | 2 +- .github/workflows/validations.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/benchmark-testing.yaml b/.github/workflows/benchmark-testing.yaml index fc0fd5966..d53a4d4a8 100644 --- a/.github/workflows/benchmark-testing.yaml +++ b/.github/workflows/benchmark-testing.yaml @@ -23,7 +23,7 @@ jobs: uses: ./.github/actions/bootstrap - name: Restore base benchmark result - uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 #v4.1.0 + uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 #v4.1.1 with: path: test/results/benchmark-main.txt # use base sha for PR or new commit hash for main push in benchmark result key diff --git a/.github/workflows/validations.yaml b/.github/workflows/validations.yaml index b33d039aa..ab4f7cf4c 100644 --- a/.github/workflows/validations.yaml +++ b/.github/workflows/validations.yaml @@ -78,7 +78,7 @@ jobs: # why not use actions/upload-artifact? It is very slow (3 minutes to upload ~600MB of data, vs 10 seconds with this approach). # see https://github.com/actions/upload-artifact/issues/199 for more info - name: Upload snapshot artifacts - uses: actions/cache/save@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 #v4.1.0 + uses: actions/cache/save@3624ceb22c1c5a301c8db4169662070a689d9ea8 #v4.1.1 with: # we need to preserve the snapshot data itself as well as the task data that confirms if the # snapshot build is stale or not. Otherwise the downstream jobs will attempt to rebuild the snapshot @@ -104,7 +104,7 @@ jobs: - name: Download snapshot build id: snapshot-cache - uses: actions/cache/restore@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 #v4.1.0 + uses: actions/cache/restore@3624ceb22c1c5a301c8db4169662070a689d9ea8 #v4.1.1 with: path: | snapshot @@ -152,7 +152,7 @@ jobs: - name: Download snapshot build id: snapshot-cache - uses: actions/cache/restore@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 #v4.1.0 + uses: actions/cache/restore@3624ceb22c1c5a301c8db4169662070a689d9ea8 #v4.1.1 with: path: | snapshot @@ -187,7 +187,7 @@ jobs: - name: Download snapshot build id: snapshot-cache - uses: actions/cache/restore@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 #v4.1.0 + uses: actions/cache/restore@3624ceb22c1c5a301c8db4169662070a689d9ea8 #v4.1.1 with: path: | snapshot From 223a52d07e337615e3da1d856ebf687d19eab8c1 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Thu, 10 Oct 2024 06:03:55 -0400 Subject: [PATCH 254/284] chore(deps): update stereoscope to 5bc91bf166769e43d8d0f86c02e877c55eb04aed (#3313) --- go.mod | 21 ++++++++++++--------- go.sum | 47 ++++++++++++++++++++++++++--------------------- 2 files changed, 38 insertions(+), 30 deletions(-) diff --git a/go.mod b/go.mod index 58c3c35b0..11878bab0 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f - github.com/anchore/stereoscope v0.0.4-0.20241005180410-efa76446cc1c + github.com/anchore/stereoscope v0.0.4-0.20241009113113-5bc91bf16676 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // we are hinting brotli to latest due to warning when installing archiver v3: // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption @@ -101,8 +101,8 @@ require ( github.com/DataDog/zstd v1.5.5 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.3.0 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/Microsoft/hcsshim v0.11.4 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/Microsoft/hcsshim v0.11.7 // indirect github.com/ProtonMail/go-crypto v1.0.0 // indirect github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect github.com/andybalholm/brotli v1.0.4 // indirect @@ -115,12 +115,15 @@ require ( github.com/charmbracelet/x/term v0.2.0 // indirect github.com/cloudflare/circl v1.3.8 // indirect github.com/containerd/cgroups v1.1.0 // indirect - github.com/containerd/containerd v1.7.11 // indirect + github.com/containerd/containerd v1.7.22 // indirect + github.com/containerd/containerd/api v1.7.19 // indirect github.com/containerd/continuity v0.4.2 // indirect + github.com/containerd/errdefs v0.1.0 // indirect github.com/containerd/fifo v1.1.0 // indirect github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect - github.com/containerd/ttrpc v1.2.2 // indirect + github.com/containerd/ttrpc v1.2.5 // indirect github.com/containerd/typeurl/v2 v2.1.1 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect @@ -146,7 +149,7 @@ require ( github.com/go-restruct/restruct v1.2.0-alpha // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -175,14 +178,15 @@ require ( github.com/moby/locker v1.0.1 // indirect github.com/moby/sys/sequential v0.5.0 // indirect github.com/moby/sys/signal v0.7.0 // indirect + github.com/moby/sys/user v0.3.0 // indirect + github.com/moby/sys/userns v0.1.0 // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/termenv v0.15.2 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect github.com/nwaples/rardecode v1.1.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect - github.com/opencontainers/runc v1.1.14 // indirect - github.com/opencontainers/runtime-spec v1.1.0-rc.1 // indirect + github.com/opencontainers/runtime-spec v1.1.0 // indirect github.com/opencontainers/selinux v1.11.0 // indirect github.com/pborman/indent v1.2.1 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect @@ -232,7 +236,6 @@ require ( golang.org/x/sys v0.26.0 // indirect golang.org/x/term v0.25.0 // indirect golang.org/x/text v0.19.0 // indirect - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect google.golang.org/grpc v1.62.1 // indirect diff --git a/go.sum b/go.sum index e9a2d1f35..d5dca70e5 100644 --- a/go.sum +++ b/go.sum @@ -74,10 +74,10 @@ github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lpr github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= -github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/Microsoft/hcsshim v0.11.7 h1:vl/nj3Bar/CvJSYo7gIQPyRWc9f3c6IeSNavBTSZNZQ= +github.com/Microsoft/hcsshim v0.11.7/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= @@ -115,8 +115,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f h1:B/E9ixKNCasntpoch61NDaQyGPDXLEJlL+B9B/PbdbA= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.4-0.20241005180410-efa76446cc1c h1:JXezMk8fF5ns4AgRGW49SGfoRgDjJHsDmcpNw272jkU= -github.com/anchore/stereoscope v0.0.4-0.20241005180410-efa76446cc1c/go.mod h1:GMupz2FoBhy5RTTmawU06c2pZxgVTceahLWiwJef2uI= +github.com/anchore/stereoscope v0.0.4-0.20241009113113-5bc91bf16676 h1:o5oECsO9cYDJUAySqFP/LAwf5IjgYLWN1s9QxqK7Ong= +github.com/anchore/stereoscope v0.0.4-0.20241009113113-5bc91bf16676/go.mod h1:qucLN/JB7xdMyRVRfdGriw6jFOo7AEnz+ei/i/2uKSs= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= @@ -190,18 +190,24 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= -github.com/containerd/containerd v1.7.11 h1:lfGKw3eU35sjV0aG2eYZTiwFEY1pCzxdzicHP3SZILw= -github.com/containerd/containerd v1.7.11/go.mod h1:5UluHxHTX2rdvYuZ5OJTC5m/KJNs0Zs9wVoJm9zf5ZE= +github.com/containerd/containerd v1.7.22 h1:nZuNnNRA6T6jB975rx2RRNqqH2k6ELYKDZfqTHqwyy0= +github.com/containerd/containerd v1.7.22/go.mod h1:e3Jz1rYRUZ2Lt51YrH9Rz0zPyJBOlSvB3ghr2jbVD8g= +github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA= +github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig= github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM= +github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0= github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= -github.com/containerd/ttrpc v1.2.2 h1:9vqZr0pxwOF5koz6N0N3kJ0zDHokrcPxIR/ZR2YFtOs= -github.com/containerd/ttrpc v1.2.2/go.mod h1:sIT6l32Ph/H9cvnJsfXM5drIVzTr5A2flTf1G5tYZak= +github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oLU= +github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4= github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -359,8 +365,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= @@ -581,6 +587,10 @@ github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5 github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI= github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= +github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= +github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= +github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -609,10 +619,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= -github.com/opencontainers/runc v1.1.14 h1:rgSuzbmgz5DUJjeSnw337TxDbRuqjs6iqQck/2weR6w= -github.com/opencontainers/runc v1.1.14/go.mod h1:E4C2z+7BxR7GHXp0hAY53mek+x49X1LjPNeMTfRGvOA= -github.com/opencontainers/runtime-spec v1.1.0-rc.1 h1:wHa9jroFfKGQqFHj0I1fMRKLl0pfj+ynAqBxo3v6u9w= -github.com/opencontainers/runtime-spec v1.1.0-rc.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg= +github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -655,7 +663,6 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= @@ -705,7 +712,6 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= @@ -834,8 +840,8 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMey go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= -go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= @@ -1062,7 +1068,6 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= From b62b0cb80095d78f3e03c38c62ead3a04cdf6a93 Mon Sep 17 00:00:00 2001 From: Alan Pope Date: Thu, 10 Oct 2024 15:28:55 +0100 Subject: [PATCH 255/284] [docs] Add mastodon link to README.md (#3306) Hello friends. This follows the same pattern as the other badges at the top of the readme. It adds the mastodon link to the Syft account. This also means that the link back here from the Mastodon account's profile page will show as 'Validated' once landed, which gives more authenticity to the account. Signed-off-by: Alan Pope --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index cf4d361c5..5170cde2b 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@  GitHub go.mod Go version   License: Apache-2.0   Join our Discourse  +  Follow on Mastodon 

![syft-demo](https://user-images.githubusercontent.com/590471/90277200-2a253000-de33-11ea-893f-32c219eea11a.gif) From 0c71bf23c51e3fc77ae115dc4a6148cb5b94bea3 Mon Sep 17 00:00:00 2001 From: William Murphy Date: Thu, 10 Oct 2024 13:11:45 -0400 Subject: [PATCH 256/284] docs: clearer deprecation message for --file (#3310) It's not clear to users that they shoudl use --output FORMAT=PATH instead of --file. Directly suggest the FORMAT=PATH syntax. Signed-off-by: Will Murphy --- cmd/syft/internal/options/output_file.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/syft/internal/options/output_file.go b/cmd/syft/internal/options/output_file.go index cf8e5632b..64e7abb39 100644 --- a/cmd/syft/internal/options/output_file.go +++ b/cmd/syft/internal/options/output_file.go @@ -28,7 +28,7 @@ func (o *OutputFile) AddFlags(flags clio.FlagSet) { if pfp, ok := flags.(fangs.PFlagSetProvider); ok { flagSet := pfp.PFlagSet() - flagSet.Lookup("file").Deprecated = "use: output" + flagSet.Lookup("file").Deprecated = "use: --output FORMAT=PATH" } } } From fbff87fc6d580d3ed6c43d6e9a2cc8a29a04ae77 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Fri, 11 Oct 2024 05:17:01 -0400 Subject: [PATCH 257/284] shorten release docs (#3318) Signed-off-by: Alex Goodman --- RELEASE.md | 99 +++++++----------------------------------------------- 1 file changed, 13 insertions(+), 86 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 3e9ba7ab0..8bf7f5c89 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,5 +1,16 @@ # Release +A release of syft comprises: +- a new semver git tag from the current tip of the main branch +- a new [github release](https://github.com/anchore/syft/releases) with a changelog and archived binary assets +- docker images published to `ghcr.io` and `dockerhub`, including multi architecture images + manifest +- [`anchore/homebrew-syft`](https://github.com/anchore/homebrew-syft) tap updated to point to assets in the latest github release + +Ideally releasing should be done often with small increments when possible. Unless a +breaking change is blocking the release, or no fixes/features have been merged, a good +target release cadence is between every 1 or 2 weeks. + + ## Creating a release This release process itself should be as automated as possible, and has only a few steps: @@ -9,16 +20,10 @@ This release process itself should be as automated as possible, and has only a f you can abort and adjust the labels on the PRs and issues to be included in the release and re-run the release trigger command. -1. A release admin must approve the release on the GitHub Actions release pipeline run page. +1. A release admin must approve the release on the GitHub Actions [release pipeline](https://github.com/anchore/syft/actions/workflows/release.yaml) run page. Once approved, the release pipeline will generate all assets and publish a GitHub Release. -1. If there is a release Milestone, close it. - -Ideally releasing should be done often with small increments when possible. Unless a -breaking change is blocking the release, or no fixes/features have been merged, a good -target release cadence is between every 1 or 2 weeks. - - + ## Retracting a release If a release is found to be problematic, it can be retracted with the following steps: @@ -32,81 +37,3 @@ If a release is found to be problematic, it can be retracted with the following in the go proxy, which will cause confusion when trying to reuse the tag later (the H1 hash will not match and there will be a warning when users try to pull the new release). - -## Background - -A good release process has the following qualities: - -1. There is a way to plan what should be in a release -1. There is a way to see what is actually in a release -1. Allow for different kinds of releases (major breaking vs backwards compatible enhancements vs patch updates) -1. Specify a repeatable way to build and publish software artifacts - - -### Planning a release - -To indicate a set of features to be released together add each issue to an in-repository -Milestone named with major-minor version to be released (e.g. `v0.1`). It is OK for other -features to be in the release that were not originally planned, and these issues and PRs -do not need to be added to the Milestone in question. Only the set of features that, when -completed, would allow the release to be considered complete. A Milestone is only used to: - -- Plan what is desired to be in a release -- Track progress to indicate when we may be ready to cut a new release - -Not all releases need to be planned. For instance, patch releases for fixes should be -released when they are ready and when releasing would not interfere with another current -release (where some partial or breaking features have already been merged). - -Unless necessary, feature releases should be small and frequent, which may obviate the -need for regular release planning under a Milestone. - - -### What is in a release - -Milestones are specifically for planning a release, not necessarily tracking all changes -that a release may bring (and more importantly, not all releases are necessarily planned -either). - -This is one of the (many) reasons for a Changelog. A good Changelog lists changes grouped -by the type of change (new, enhancement, deprecation, breaking, bug fix, security fix), in -chronological order (within groups), linking the PR where the change was made in the -Changelog line. Furthermore, there should be a place to see all released versions, the -release date for each release, the semantic version of the release, and the set of changes -for each release. - -**This project auto-generates the Changelog contents for each current release and posts the -generated contents to the GitHub Release page**. Leveraging the GitHub Releases feature -allows GitHub to manage the Changelog on each release outside of the git source tree while -still being hosted with the released assets. - -The Changelog is generated from the metadata from in-repository issues and PRs, using -labels to guide what kind of change each item is (e.g. breaking, new feature, bug fix, -etx). Only issues/PRs with select labels are included in the Changelog, and only if the -issue/PR was created after the last release. Additional labels are used to exclude items -from the Changelog. - -The above suggestions imply that we should: - -- Ensure there is a sufficient title for each PR and issue title to be included in the - Changelog -- The appropriate label is applied to PRs and/or issues to drive specific change type - sections (deprecated, breaking, security, bug, etc) - -**With this approach as we cultivate good organization of PRs and issues we automatically -get an equally good Changelog.** - - -### Major, minor, and patch releases - -The latest version of the tool is the only supported version, which implies that multiple -parallel release branches will not be a regular process (if ever). Multiple releases can -be planned in parallel, however, only one can be actively developed at a time. That is, if -PRs attached to a release Milestone have been merged into the main branch, that release is -now the "next" release. **This implies that the source of truth for release lies with the -git log and Changelog, not with the release Milestones** (which are purely for planning and -tracking). - -Semantic versioning should be used to indicate breaking changes, new features, and fixes. -The exception to this is `< 1.0`, where the major version is not bumped for breaking changes, -instead the minor version indicates both new features and breaking changes. From c2c8c793d2ba6bee90b5fa1a2369912d76304a79 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Oct 2024 05:17:35 -0400 Subject: [PATCH 258/284] chore(deps): bump actions/upload-artifact from 4.4.1 to 4.4.3 (#3314) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.4.1 to 4.4.3. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/604373da6381bf24206979c74d06a550515601b9...b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/benchmark-testing.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/benchmark-testing.yaml b/.github/workflows/benchmark-testing.yaml index d53a4d4a8..f704868f0 100644 --- a/.github/workflows/benchmark-testing.yaml +++ b/.github/workflows/benchmark-testing.yaml @@ -39,7 +39,7 @@ jobs: OUTPUT="${OUTPUT//$'\r'/'%0D'}" # URL encode all '\r' characters echo "result=$OUTPUT" >> $GITHUB_OUTPUT - - uses: actions/upload-artifact@604373da6381bf24206979c74d06a550515601b9 # v4.4.1 + - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: benchmark-test-results path: test/results/**/* From 6124d72a297dcc2125e9435decdf40e4be910873 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Oct 2024 10:09:14 -0400 Subject: [PATCH 259/284] chore(deps): bump github.com/bmatcuk/doublestar/v4 from 4.6.1 to 4.7.0 (#3321) Bumps [github.com/bmatcuk/doublestar/v4](https://github.com/bmatcuk/doublestar) from 4.6.1 to 4.7.0. - [Release notes](https://github.com/bmatcuk/doublestar/releases) - [Commits](https://github.com/bmatcuk/doublestar/compare/v4.6.1...v4.7.0) --- updated-dependencies: - dependency-name: github.com/bmatcuk/doublestar/v4 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 11878bab0..67bc09e9b 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( // we are hinting brotli to latest due to warning when installing archiver v3: // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 - github.com/bmatcuk/doublestar/v4 v4.6.1 + github.com/bmatcuk/doublestar/v4 v4.7.0 github.com/charmbracelet/bubbles v0.20.0 github.com/charmbracelet/bubbletea v1.1.1 github.com/charmbracelet/lipgloss v0.13.0 diff --git a/go.sum b/go.sum index d5dca70e5..5c43b4615 100644 --- a/go.sum +++ b/go.sum @@ -145,8 +145,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I= -github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/bmatcuk/doublestar/v4 v4.7.0 h1:0ETcwHpDTeJqc6K4DuVL3jF34rlZiiH6+TNmwkDm3hE= +github.com/bmatcuk/doublestar/v4 v4.7.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= From 84877369e5162b5b72ec3438852c8bdda5906eac Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Fri, 11 Oct 2024 12:30:20 -0400 Subject: [PATCH 260/284] chore(deps): update stereoscope to c04af061af62ab3ba6ab6760613526eaa7fcb163 (#3319) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: kzantow <3009477+kzantow@users.noreply.github.com> --- go.mod | 12 +++++++----- go.sum | 20 ++++++++++---------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 67bc09e9b..232fe7702 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/anchore/syft -go 1.22.0 +go 1.22.5 + +toolchain go1.22.8 require ( github.com/CycloneDX/cyclonedx-go v0.9.1 @@ -17,7 +19,7 @@ require ( github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f - github.com/anchore/stereoscope v0.0.4-0.20241009113113-5bc91bf16676 + github.com/anchore/stereoscope v0.0.4-0.20241010201852-c04af061af62 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // we are hinting brotli to latest due to warning when installing archiver v3: // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption @@ -127,7 +129,7 @@ require ( github.com/containerd/typeurl/v2 v2.1.1 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/docker/cli v27.1.1+incompatible // indirect + github.com/docker/cli v27.3.1+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-connections v0.4.0 // indirect @@ -210,7 +212,7 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.19.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/sylabs/sif/v2 v2.17.1 // indirect + github.com/sylabs/sif/v2 v2.19.1 // indirect github.com/sylabs/squashfs v1.0.0 // indirect github.com/therootcompany/xz v1.0.1 // indirect github.com/tidwall/gjson v1.17.0 // indirect @@ -239,7 +241,7 @@ require ( golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect google.golang.org/grpc v1.62.1 // indirect - google.golang.org/protobuf v1.33.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect diff --git a/go.sum b/go.sum index 5c43b4615..46a7dfce9 100644 --- a/go.sum +++ b/go.sum @@ -115,8 +115,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f h1:B/E9ixKNCasntpoch61NDaQyGPDXLEJlL+B9B/PbdbA= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.4-0.20241009113113-5bc91bf16676 h1:o5oECsO9cYDJUAySqFP/LAwf5IjgYLWN1s9QxqK7Ong= -github.com/anchore/stereoscope v0.0.4-0.20241009113113-5bc91bf16676/go.mod h1:qucLN/JB7xdMyRVRfdGriw6jFOo7AEnz+ei/i/2uKSs= +github.com/anchore/stereoscope v0.0.4-0.20241010201852-c04af061af62 h1:PR/euQRQ0JVSnhYTxkD/tfW/i7rFWh8qsKuNHSbITRc= +github.com/anchore/stereoscope v0.0.4-0.20241010201852-c04af061af62/go.mod h1:H3zzV5nO9ngEUytbRNWiVyw+/613+oFtHPeurVaAGPA= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= @@ -231,8 +231,8 @@ github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da/go.mod h1:B3tI9iGHi4i github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2oNn0GkeZE= -github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v27.3.1+incompatible h1:qEGdFBF3Xu6SCvCYhc7CzaQTlBmqDuzxPDpigSyeKQQ= +github.com/docker/cli v27.3.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= @@ -698,8 +698,8 @@ github.com/sassoftware/go-rpmutils v0.4.0/go.mod h1:3goNWi7PGAT3/dlql2lv3+MSN5jN github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e h1:7q6NSFZDeGfvvtIRwBrU/aegEYJYmvev0cHAwo17zZQ= github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd78rljTxKAnTDPFqXSGxvETQnJyuSOQwsHycqfs= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624Y= -github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI= +github.com/sebdah/goldie/v2 v2.5.5 h1:rx1mwF95RxZ3/83sdS4Yp7t2C5TCokvWP4TBRbAyEWY= +github.com/sebdah/goldie/v2 v2.5.5/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI= github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d h1:RQqyEogx5J6wPdoxqL132b100j8KjcVHO1c0KLRoIhc= github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d/go.mod h1:PegD7EVqlN88z7TpCqH92hHP+GBpfomGCCnw1PFtNOA= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= @@ -762,8 +762,8 @@ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/sylabs/sif/v2 v2.17.1 h1:p6Sl0LWyShXBj2SBsS1dMOMIMrZHe8pwBnBrYt6uo4M= -github.com/sylabs/sif/v2 v2.17.1/go.mod h1:XUGB6AQUXGkms3qPOPdevctT3lBLRLWZNWHVnt5HMKE= +github.com/sylabs/sif/v2 v2.19.1 h1:1eeMmFc8elqJe60ZiWwXgL3gMheb0IP4GmNZ4q0IEA0= +github.com/sylabs/sif/v2 v2.19.1/go.mod h1:U1SUhvl8X1JIxAylC0DYz1fa/Xba6EMZD1dGPGBH83E= github.com/sylabs/squashfs v1.0.0 h1:xAyMS21ogglkuR5HaY55PCfqY3H32ma9GkasTYo28Zg= github.com/sylabs/squashfs v1.0.0/go.mod h1:rhWzvgefq1X+R+LZdts10hfMsTg3g74OfGunW8tvg/4= github.com/terminalstatic/go-xsd-validate v0.1.5 h1:RqpJnf6HGE2CB/lZB1A8BYguk8uRtcvYAPLCF15qguo= @@ -1315,8 +1315,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 8095f7b8c14d2b2abf08c9516c7617c08e9fc319 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Sun, 13 Oct 2024 10:53:58 -0400 Subject: [PATCH 261/284] chore(deps): update stereoscope to 92e97a1cf36d162bad51ccc6aba0cce7a4dcfbf4 (#3322) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: kzantow <3009477+kzantow@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 232fe7702..638918b06 100644 --- a/go.mod +++ b/go.mod @@ -19,12 +19,12 @@ require ( github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f - github.com/anchore/stereoscope v0.0.4-0.20241010201852-c04af061af62 + github.com/anchore/stereoscope v0.0.4-0.20241012085857-92e97a1cf36d github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // we are hinting brotli to latest due to warning when installing archiver v3: // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 - github.com/bmatcuk/doublestar/v4 v4.7.0 + github.com/bmatcuk/doublestar/v4 v4.7.1 github.com/charmbracelet/bubbles v0.20.0 github.com/charmbracelet/bubbletea v1.1.1 github.com/charmbracelet/lipgloss v0.13.0 diff --git a/go.sum b/go.sum index 46a7dfce9..b16e5fee4 100644 --- a/go.sum +++ b/go.sum @@ -115,8 +115,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f h1:B/E9ixKNCasntpoch61NDaQyGPDXLEJlL+B9B/PbdbA= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.4-0.20241010201852-c04af061af62 h1:PR/euQRQ0JVSnhYTxkD/tfW/i7rFWh8qsKuNHSbITRc= -github.com/anchore/stereoscope v0.0.4-0.20241010201852-c04af061af62/go.mod h1:H3zzV5nO9ngEUytbRNWiVyw+/613+oFtHPeurVaAGPA= +github.com/anchore/stereoscope v0.0.4-0.20241012085857-92e97a1cf36d h1:KxTT8dRbN0Zlqpfmae2Zeh58TjTudD4Sp8K7nxWQcJc= +github.com/anchore/stereoscope v0.0.4-0.20241012085857-92e97a1cf36d/go.mod h1:Z3WLp10tFyp04UyGDXg8t+pK++riciVZyflK3YXwZXo= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= @@ -145,8 +145,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bmatcuk/doublestar/v4 v4.7.0 h1:0ETcwHpDTeJqc6K4DuVL3jF34rlZiiH6+TNmwkDm3hE= -github.com/bmatcuk/doublestar/v4 v4.7.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q= +github.com/bmatcuk/doublestar/v4 v4.7.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= From e962c10da7e3656b514b5e654f4c94e05616d7eb Mon Sep 17 00:00:00 2001 From: Weston Steimel Date: Mon, 14 Oct 2024 13:41:34 +0000 Subject: [PATCH 262/284] fix: improve go binary semver extraction for traefik (#3325) Improves the go cataloger semver extraction logic to include getting the release version of traefik. This is based off of the regex pattern that already existed in the traefik binary classifier. Signed-off-by: Weston Steimel --- syft/pkg/cataloger/golang/parse_go_binary.go | 2 +- syft/pkg/cataloger/golang/parse_go_binary_test.go | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/syft/pkg/cataloger/golang/parse_go_binary.go b/syft/pkg/cataloger/golang/parse_go_binary.go index bf3a6d722..91957f19d 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary.go +++ b/syft/pkg/cataloger/golang/parse_go_binary.go @@ -196,7 +196,7 @@ func (c *goBinaryCataloger) makeGoMainPackage(resolver file.Resolver, mod *exten // this is checking for (.L)? because at least one binary seems to have \xA0L preceding the version string, but for some reason // this is unable to be matched by the regex here as \x00\xA0L; // the only thing that seems to work is to just look for version strings following both \x00 and \x00.L for now -var semverPattern = regexp.MustCompile(`\x00(.L)?(?Pv?(\d+\.\d+\.\d+[-\w]*[+\w]*))\x00`) +var semverPattern = regexp.MustCompile(`(\x00|\x{FFFD})(.L)?(?Pv?(\d+\.\d+\.\d+[-\w]*[+\w]*))\x00`) func (c *goBinaryCataloger) findMainModuleVersion(metadata *pkg.GolangBinaryBuildinfoEntry, gbs pkg.KeyValues, reader io.ReadSeekCloser) string { vcsVersion, hasVersion := gbs.Get("vcs.revision") diff --git a/syft/pkg/cataloger/golang/parse_go_binary_test.go b/syft/pkg/cataloger/golang/parse_go_binary_test.go index 75659ae65..b2af3ffca 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary_test.go +++ b/syft/pkg/cataloger/golang/parse_go_binary_test.go @@ -1305,6 +1305,14 @@ func Test_extractVersionFromContents(t *testing.T) { contents: strings.NewReader("\x0e\x74\x5a\x3b\x00\x00\xa0\x4cv1.9.5\x00\x00"), want: "v1.9.5", }, + { + // 06168a34: f98f b0be 332e 312e 3200 0000 636f 6d74 ....3.1.2...comt from /usr/local/bin/traefik + // in traefik:v3.1.2@sha256:3f92eba47bd4bfda91d47b72d16fef2d7ae15db61a92b2057cf0cb389f8938f6 + // TODO: eventually use something for managing snippets, similar to what's used with binary classifier tests + name: "parse traefik version", + contents: strings.NewReader("\xf9\x8f\xb0\xbe\x33\x2e\x31\x2e\x32\x00\x00\x00\x63\x6f\x6d\x74"), + want: "3.1.2", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { From f6e5405eb8f51fa4d93010b8fbdcb8a02dc9da81 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 09:42:20 -0400 Subject: [PATCH 263/284] chore(deps): update CPE dictionary index (#3323) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: wagoodman <590471+wagoodman@users.noreply.github.com> --- .../dictionary/data/cpe-index.json | 116 ++++++++++++++++-- 1 file changed, 107 insertions(+), 9 deletions(-) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index 620c92698..89e1d9fb2 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -5839,7 +5839,7 @@ "cpe:2.3:a:python-scciclient_project:python-scciclient:*:*:*:*:*:python:*:*" ], "pytorch-lightning": [ - "cpe:2.3:a:pytorchlightning:pytorch_lightning:*:*:*:*:*:python:*:*" + "cpe:2.3:a:lightningai:pytorch_lightning:*:*:*:*:*:python:*:*" ], "rencode": [ "cpe:2.3:a:rencode_project:rencode:*:*:*:*:*:python:*:*" @@ -6346,6 +6346,9 @@ "show_in_browser": [ "cpe:2.3:a:jonathan_leung:show_in_browser:*:*:*:*:*:ruby:*:*" ], + "sidekiq-unique-jobs": [ + "cpe:2.3:a:mhenrixon:sidekiq-unique-jobs:*:*:*:*:*:ruby:*:*" + ], "simple_captcha2": [ "cpe:2.3:a:simple_captcha2_project:simple_captcha2:*:*:*:*:*:ruby:*:*" ], @@ -7010,6 +7013,9 @@ "404like": [ "cpe:2.3:a:404like_project:404like:*:*:*:*:*:wordpress:*:*" ], + "404page": [ + "cpe:2.3:a:nerdpress:smart_custom_404_error_page:*:*:*:*:*:wordpress:*:*" + ], "4ecps-webforms": [ "cpe:2.3:a:jumpdemand:4ecps_web_forms:*:*:*:*:*:wordpress:*:*" ], @@ -7343,6 +7349,9 @@ "advanced-ajax-page-loader": [ "cpe:2.3:a:advanced_ajax_page_loader_project:advanced_ajax_page_loader:*:*:*:*:*:wordpress:*:*" ], + "advanced-backgrounds": [ + "cpe:2.3:a:wpbackgrounds:advanced_wordpress_backgrounds:*:*:*:*:*:wordpress:*:*" + ], "advanced-booking-calendar": [ "cpe:2.3:a:elbtide:advanced_booking_calendar:*:*:*:*:*:wordpress:*:*" ], @@ -7490,6 +7499,9 @@ "albo-pretorio-on-line": [ "cpe:2.3:a:albo_pretorio_on_line_project:albo_pretorio_on_line:*:*:*:*:*:wordpress:*:*" ], + "album-and-image-gallery-plus-lightbox": [ + "cpe:2.3:a:essentialplugin:album_and_image_gallery_plus_lightbox:*:*:*:*:free:wordpress:*:*" + ], "alfred-click-collect": [ "cpe:2.3:a:alfred24_click_\\\u0026_collect_project:alfred24_click_\\\u0026_collect:*:*:*:*:*:wordpress:*:*" ], @@ -7622,6 +7634,9 @@ "analytics-cat": [ "cpe:2.3:a:fatcatapps:analytics_cat:*:*:*:*:*:wordpress:*:*" ], + "analytics-insights": [ + "cpe:2.3:a:deconf:analytics_insights:*:*:*:*:*:wordpress:*:*" + ], "analytics-tracker": [ "cpe:2.3:a:analytics_tracker_project:analytics_tracker:*:*:*:*:*:wordpress:*:*" ], @@ -7730,6 +7745,9 @@ "ari-adminer": [ "cpe:2.3:a:ari-soft:ari_adminer:*:*:*:*:*:wordpress:*:*" ], + "ari-cf7-connector": [ + "cpe:2.3:a:ari-soft:contact_form_7_connector:*:*:*:*:*:wordpress:*:*" + ], "ari-fancy-lightbox": [ "cpe:2.3:a:ari-soft:ari_fancy_lightbox:*:*:*:*:*:wordpress:*:*" ], @@ -7918,7 +7936,8 @@ "cpe:2.3:a:aysproextensions:popup_like:*:*:*:*:*:wordpress:*:*" ], "ays-popup-box": [ - "cpe:2.3:a:ays-pro:popup_box:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:ays-pro:popup_box:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:ays-pro:popup_box:*:*:*:*:pro:wordpress:*:*" ], "azurecurve-toggle-showhide": [ "cpe:2.3:a:azurecurve:toggle_show\\/hide:*:*:*:*:*:wordpress:*:*" @@ -7926,6 +7945,9 @@ "b2bking-wholesale-for-woocommerce": [ "cpe:2.3:a:webwizards:b2bking:*:*:*:*:*:wordpress:*:*" ], + "ba-book-everything": [ + "cpe:2.3:a:ba-booking:ba_book_everything:*:*:*:*:*:wordpress:*:*" + ], "ba-plus-before-after-image-slider-free": [ "cpe:2.3:a:aluka:ba_plus:*:*:*:*:*:wordpress:*:*" ], @@ -8198,7 +8220,8 @@ ], "booking": [ "cpe:2.3:a:booking_calendar_project:booking_calendar:*:*:*:*:*:wordpress:*:*", - "cpe:2.3:a:wpbookingcalendar:booking_calendar:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:wpbookingcalendar:booking_calendar:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpbookingcalendar:wp_booking_calendar:*:*:*:*:*:wordpress:*:*" ], "booking-and-rental-manager-for-woocommerce": [ "cpe:2.3:a:magepeople:booking_\\\u0026_rental_manager:*:*:*:*:*:wordpress:*:*" @@ -9618,6 +9641,9 @@ "demo-awesome": [ "cpe:2.3:a:theme4press:demo_awesome:*:*:*:*:*:wordpress:*:*" ], + "demo-importer-plus": [ + "cpe:2.3:a:kraftplugins:demo_importer_plus:*:*:*:*:*:wordpress:*:*" + ], "democracy-poll": [ "cpe:2.3:a:wp-kama:democracy_poll:*:*:*:*:*:wordpress:*:*" ], @@ -10239,7 +10265,8 @@ "cpe:2.3:a:wpdeveloper:essential_addons_for_elementor:*:*:*:*:*:wordpress:*:*" ], "essential-blocks": [ - "cpe:2.3:a:wpdeveloper:essential_blocks:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:wpdeveloper:essential_blocks:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpdeveloper:essential_blocks:*:*:*:*:free:wordpress:*:*" ], "essential-content-types": [ "cpe:2.3:a:catchplugins:essential_content_types:*:*:*:*:*:wordpress:*:*" @@ -10262,6 +10289,9 @@ "eu-cookie-law": [ "cpe:2.3:a:eu_cookie_law_project:eu_cookie_law:*:*:*:*:*:wordpress:*:*" ], + "eu-vat-for-woocommerce": [ + "cpe:2.3:a:wpfactory:eu\\/uk_vat_manager_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], "eupago-gateway-for-woocommerce": [ "cpe:2.3:a:eupago:eupago_gateway_woocommerce:*:*:*:*:*:wordpress:*:*" ], @@ -10323,8 +10353,7 @@ "cpe:2.3:a:e-dynamics:events_made_easy:*:*:*:*:*:wordpress:*:*" ], "events-manager": [ - "cpe:2.3:a:pixelite:events_manager:*:*:*:*:*:wordpress:*:*", - "cpe:2.3:a:wp-events-plugin:events_manager:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:pixelite:events_manager:*:*:*:*:*:wordpress:*:*" ], "ever-compare": [ "cpe:2.3:a:hasthemes:ever_compare:*:*:*:*:*:wordpress:*:*" @@ -10598,6 +10627,9 @@ "final-tiles-grid-gallery-lite": [ "cpe:2.3:a:machothemes:image_photo_gallery_final_tiles_grid:*:*:*:*:*:wordpress:*:*" ], + "finale-woocommerce-sales-countdown-timer-discount": [ + "cpe:2.3:a:xlplugins:finale:*:*:*:*:lite:wordpress:*:*" + ], "find-and-replace-all": [ "cpe:2.3:a:find_and_replace_all_project:find_and_replace_all:*:*:*:*:*:wordpress:*:*" ], @@ -10607,6 +10639,9 @@ "find-my-blocks": [ "cpe:2.3:a:find_my_blocks_project:find_my_blocks:*:*:*:*:*:wordpress:*:*" ], + "fish-and-ships": [ + "cpe:2.3:a:wp-centrics:fish_and_ships:*:*:*:*:*:wordpress:*:*" + ], "fitness-calculators": [ "cpe:2.3:a:codeinitiator:fitness_calculators:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:codeinitiator:fitness_calculators_plugin:*:*:*:*:*:wordpress:*:*" @@ -11273,6 +11308,9 @@ "gsheetconnector-wpforms": [ "cpe:2.3:a:gsheetconnector:wpforms_google_sheet_connector:*:*:*:*:free:wordpress:*:*" ], + "gtm-server-side": [ + "cpe:2.3:a:stape:gtm_server_side:*:*:*:*:*:wordpress:*:*" + ], "gtmetrix-for-wordpress": [ "cpe:2.3:a:gtmetrix:gtmetrix:*:*:*:*:*:wordpress:*:*" ], @@ -11370,6 +11408,9 @@ "heateor-social-login": [ "cpe:2.3:a:heateor:social_login:*:*:*:*:*:wordpress:*:*" ], + "hello-world": [ + "cpe:2.3:a:kau-boys:hello_world:*:*:*:*:*:wordpress:*:*" + ], "helloprint": [ "cpe:2.3:a:helloprint:helloprint:*:*:*:*:*:wordpress:*:*" ], @@ -11856,6 +11897,9 @@ "iubenda-cookie-law-solution": [ "cpe:2.3:a:iubenda:iubenda-cookie-law-solution:*:*:*:*:*:wordpress:*:*" ], + "iworks-pwa": [ + "cpe:2.3:a:iworks:pwa:*:*:*:*:*:wordpress:*:*" + ], "iwp-client": [ "cpe:2.3:a:revmakx:infinitewp_client:*:*:*:*:*:wordpress:*:*" ], @@ -12186,6 +12230,9 @@ "leira-cron-jobs": [ "cpe:2.3:a:leira:cron_jobs:*:*:*:*:*:wordpress:*:*" ], + "leira-roles": [ + "cpe:2.3:a:leira:roles_\\\u0026_capabilities:*:*:*:*:*:wordpress:*:*" + ], "letterpress": [ "cpe:2.3:a:themeqx:letterpress:*:*:*:*:*:wordpress:*:*" ], @@ -12248,7 +12295,7 @@ "cpe:2.3:a:link_juice_keeper_project:link_juice_keeper:*:*:*:*:*:wordpress:*:*" ], "link-library": [ - "cpe:2.3:a:link_library_project:link_library:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:ylefebvre:link_library:*:*:*:*:*:wordpress:*:*" ], "link-log": [ "cpe:2.3:a:perafox:link_log:*:*:*:*:*:wordpress:*:*", @@ -12381,6 +12428,9 @@ "cpe:2.3:a:custom_popup_builder_project:custom_popup_builder:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:popup_\\|_custom_popup_builder_project:popup_\\|_custom_popup_builder:*:*:*:*:*:wordpress:*:*" ], + "magazine-blocks": [ + "cpe:2.3:a:themegrill:magazine_blocks:*:*:*:*:*:wordpress:*:*" + ], "mage-eventpress": [ "cpe:2.3:a:mage-people:event_manager_and_tickets_selling_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], @@ -12424,6 +12474,9 @@ "mailchimp-subscribe-sm": [ "cpe:2.3:a:pluginops:mailchimp_subscribe_form:*:*:*:*:*:wordpress:*:*" ], + "mailchimp-top-bar": [ + "cpe:2.3:a:ibericode:mailchimp_top_bar:*:*:*:*:*:wordpress:*:*" + ], "mailcwp": [ "cpe:2.3:a:mailcwp_project:mailcwp:*:*:*:*:*:wordpress:*:*" ], @@ -12524,6 +12577,9 @@ "martins-link-network": [ "cpe:2.3:a:martinstools:free_\\\u0026_easy_link_building:*:*:*:*:*:wordpress:*:*" ], + "mas-static-content": [ + "cpe:2.3:a:madrasthemes:mas_static_content:*:*:*:*:*:wordpress:*:*" + ], "mashsharer": [ "cpe:2.3:a:social_media_share_buttons_project:social_media_share_buttons:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:wpchill:mashshare:*:*:*:*:*:wordpress:*:*" @@ -12639,6 +12695,9 @@ "member-hero": [ "cpe:2.3:a:memberhero:member_hero:*:*:*:*:*:wordpress:*:*" ], + "memberful-wp": [ + "cpe:2.3:a:memberful:memberful:*:*:*:*:*:wordpress:*:*" + ], "memberlite-shortcodes": [ "cpe:2.3:a:strangerstudios:memberlite_shortcodes:*:*:*:*:*:wordpress:*:*" ], @@ -13525,6 +13584,9 @@ "pdf-print": [ "cpe:2.3:a:bestwebsoft:pdf_\\\u0026_print:*:*:*:*:*:wordpress:*:*" ], + "pdf-thumbnail-generator": [ + "cpe:2.3:a:kubiq:pdf_thumbnail_generator:*:*:*:*:*:wordpress:*:*" + ], "pdf-viewer-block": [ "cpe:2.3:a:gutenberg_pdf_viewer_block_project:gutenberg_pdf_viewer_block:*:*:*:*:*:wordpress:*:*" ], @@ -13666,7 +13728,7 @@ "cpe:2.3:a:pixabay_images_project:pixabay_images:*:*:*:*:*:wordpress:*:*" ], "pixelyoursite": [ - "cpe:2.3:a:pixelyoursite:pixelyoursite:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:pixelyoursite:pixelyoursite:*:*:*:*:-:wordpress:*:*" ], "pixtypes": [ "cpe:2.3:a:pixelgrade:pixtypes:*:*:*:*:*:wordpress:*:*" @@ -13758,6 +13820,9 @@ "poptin": [ "cpe:2.3:a:poptin:popups:*:*:*:*:*:wordpress:*:*" ], + "popularis-extra": [ + "cpe:2.3:a:themes4wp:popularis_extra:*:*:*:*:*:wordpress:*:*" + ], "popup-anything-on-click": [ "cpe:2.3:a:essentialplugin:popup_anything:*:*:*:*:*:wordpress:*:*" ], @@ -14529,6 +14594,9 @@ "revision-manager-tmc": [ "cpe:2.3:a:jetplugs:revision_manager_tmc:*:*:*:*:*:wordpress:*:*" ], + "revolut-gateway-for-woocommerce": [ + "cpe:2.3:a:revolut:revolut_gateway_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], "rezgo": [ "cpe:2.3:a:rezgo:rezgo_online_booking:*:*:*:*:*:wordpress:*:*" ], @@ -14586,6 +14654,9 @@ "rsfirewall": [ "cpe:2.3:a:rsjoomla:rsfirewall\\!:*:*:*:*:*:wordpress:*:*" ], + "rss-feed-post-generator-echo": [ + "cpe:2.3:a:coderevolution:echo_rss_feed_post_generator:*:*:*:*:*:wordpress:*:*" + ], "rss-feed-widget": [ "cpe:2.3:a:rss_feed_widget_project:rss_feed_widget:*:*:*:*:*:wordpress:*:*" ], @@ -15041,6 +15112,9 @@ "simple-e-commerce-shopping-cart": [ "cpe:2.3:a:simple-e-commerce-shopping-cart_project:simple-e-commerce-shopping-cart:*:*:*:*:*:wordpress:*:*" ], + "simple-embed-code": [ + "cpe:2.3:a:davidartiss:code_embed:*:*:*:*:*:wordpress:*:*" + ], "simple-event-planner": [ "cpe:2.3:a:press_tigers:simple_event_planner:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:presstigers:simple_event_planner:*:*:*:*:*:wordpress:*:*" @@ -15383,6 +15457,9 @@ "smart-logo-showcase-lite": [ "cpe:2.3:a:accesspressthemes:smart_logo_showcase_lite:*:*:*:*:*:wordpress:*:*" ], + "smart-manager-for-wp-e-commerce": [ + "cpe:2.3:a:storeapps:smart_manager:*:*:*:*:*:wordpress:*:*" + ], "smart-marketing-for-wp": [ "cpe:2.3:a:e-goi:smart_marketing_sms_and_newsletters_forms:*:*:*:*:*:*:*:*" ], @@ -15401,6 +15478,9 @@ "smartcrawl-seo": [ "cpe:2.3:a:wpmudev:smartcrawl:*:*:*:*:*:wordpress:*:*" ], + "smartsearchwp": [ + "cpe:2.3:a:smartsearchwp:smartsearchwp:*:*:*:*:*:wordpress:*:*" + ], "smartsoftbutton-widget-de-botones-de-chat": [ "cpe:2.3:a:smartsoft:button_widget_smartsoft:*:*:*:*:*:wordpress:*:*" ], @@ -15961,7 +16041,7 @@ "cpe:2.3:a:thank_me_later_project:thank_me_later:*:*:*:*:*:wordpress:*:*" ], "the-events-calendar": [ - "cpe:2.3:a:tri:the_events_calendar:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:stellarwp:the_events_calendar:*:*:*:*:*:wordpress:*:*" ], "the-hackers-diet": [ "cpe:2.3:a:wp-plugins:the_hackers_diet:*:*:*:*:*:wordpress:*:*" @@ -16369,6 +16449,9 @@ "uncanny-automator": [ "cpe:2.3:a:uncannyowl:uncanny_automator:*:*:*:*:*:wordpress:*:*" ], + "uncanny-learndash-groups": [ + "cpe:2.3:a:uncannyowl:uncanny_groups_for_learndash:*:*:*:*:*:wordpress:*:*" + ], "uncanny-learndash-toolkit": [ "cpe:2.3:a:uncannyowl:uncanny_toolkit_for_learndash:*:*:*:*:*:*:*:*", "cpe:2.3:a:uncannyowl:uncanny_toolkit_for_learndash:*:*:*:*:*:wordpress:*:*" @@ -17083,6 +17166,9 @@ "woo-thank-you-page-customizer": [ "cpe:2.3:a:villatheme:thank_you_page_customizer_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], + "woo-thank-you-page-nextmove-lite": [ + "cpe:2.3:a:xlplugins:nextmove:*:*:*:*:lite:wordpress:*:*" + ], "woo-tranzila-gateway": [ "cpe:2.3:a:antonbond:woocommerce_tranzila_payment_gateway:*:*:*:*:*:wordpress:*:*" ], @@ -17157,6 +17243,9 @@ "woocommerce-multi-currency": [ "cpe:2.3:a:villatheme:woocommerce_multi_currency:*:*:*:*:*:wordpress:*:*" ], + "woocommerce-multilingual": [ + "cpe:2.3:a:onthegosystems:woocommerce_multilingual_\\\u0026_multicurrency:*:*:*:*:*:wordpress:*:*" + ], "woocommerce-payments": [ "cpe:2.3:a:automattic:woopayments:*:*:*:*:*:wordpress:*:*" ], @@ -18327,6 +18416,9 @@ "wp-songbook": [ "cpe:2.3:a:wp_songbook_project:wp_songbook:*:*:*:*:*:wordpress:*:*" ], + "wp-sort-order": [ + "cpe:2.3:a:androidbubble:wp_sort_order:*:*:*:*:*:wordpress:*:*" + ], "wp-source-control": [ "cpe:2.3:a:wp_content_source_control_project:wp_content_source_control:*:*:-:-:-:wordpress:*:*" ], @@ -18519,6 +18611,9 @@ "wp-voting-contest": [ "cpe:2.3:a:ohiowebtech:wp_voting_contest:*:*:*:*:*:wordpress:*:*" ], + "wp-wc-affiliate-program": [ + "cpe:2.3:a:redefiningtheweb:affiliate_pro:*:*:*:*:*:wordpress:*:*" + ], "wp-whatsapp": [ "cpe:2.3:a:ninjateam:wp_chat_app:*:*:*:*:*:wordpress:*:*" ], @@ -18874,6 +18969,9 @@ "ymc-smart-filter": [ "cpe:2.3:a:ymc-22:filter_\\\u0026_grids:*:*:*:*:*:wordpress:*:*" ], + "yml-for-yandex-market": [ + "cpe:2.3:a:icopydoc:yml_for_yandex_market:*:*:*:*:*:wordpress:*:*" + ], "yookassa": [ "cpe:2.3:a:yookassa:yukassa_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], From 67faca42082d6511c1a992e32166e8198813f6c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:06:08 +0000 Subject: [PATCH 264/284] chore(deps): bump github/codeql-action from 3.26.12 to 3.26.13 (#3327) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.12 to 3.26.13. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/c36620d31ac7c881962c3d9dd939c40ec9434f2b...f779452ac5af1c261dce0346a8f964149f49322b) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 7426f84b0..a188c3e89 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@c36620d31ac7c881962c3d9dd939c40ec9434f2b #v3.26.12 + uses: github/codeql-action/init@f779452ac5af1c261dce0346a8f964149f49322b #v3.26.13 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@c36620d31ac7c881962c3d9dd939c40ec9434f2b #v3.26.12 + uses: github/codeql-action/autobuild@f779452ac5af1c261dce0346a8f964149f49322b #v3.26.13 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c36620d31ac7c881962c3d9dd939c40ec9434f2b #v3.26.12 + uses: github/codeql-action/analyze@f779452ac5af1c261dce0346a8f964149f49322b #v3.26.13 From 39146aaf626c98767e7644049e30f3eb4e5a078c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 11:46:47 -0400 Subject: [PATCH 265/284] chore(deps): bump anchore/sbom-action from 0.17.2 to 0.17.3 (#3326) Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.17.2 to 0.17.3. - [Release notes](https://github.com/anchore/sbom-action/releases) - [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md) - [Commits](https://github.com/anchore/sbom-action/compare/61119d458adab75f756bc0b9e4bde25725f86a7a...f5e124a5e5e1d497a692818ae907d3c45829d033) --- updated-dependencies: - dependency-name: anchore/sbom-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 4ce1db1d5..a32578845 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -148,7 +148,7 @@ jobs: # for updating brew formula in anchore/homebrew-syft GITHUB_BREW_TOKEN: ${{ secrets.ANCHOREOPS_GITHUB_OSS_WRITE_TOKEN }} - - uses: anchore/sbom-action@61119d458adab75f756bc0b9e4bde25725f86a7a #v0.17.2 + - uses: anchore/sbom-action@f5e124a5e5e1d497a692818ae907d3c45829d033 #v0.17.3 continue-on-error: true with: artifact-name: sbom.spdx.json From 7c69367b659661b95b29de08988c47128fddc35c Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 20:03:16 +0000 Subject: [PATCH 266/284] chore(deps): update stereoscope to 93f8a11331e3d50f751e4d0ec5b63f3df309e9e5 (#3331) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: willmurphyscode <12529630+willmurphyscode@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 638918b06..310978064 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f - github.com/anchore/stereoscope v0.0.4-0.20241012085857-92e97a1cf36d + github.com/anchore/stereoscope v0.0.4-0.20241014194013-93f8a11331e3 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // we are hinting brotli to latest due to warning when installing archiver v3: // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption @@ -142,7 +142,7 @@ require ( github.com/felixge/fgprof v0.9.3 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.4 // indirect + github.com/gabriel-vasile/mimetype v1.4.6 // indirect github.com/gkampitakis/ciinfo v0.3.0 // indirect github.com/gkampitakis/go-diff v1.3.2 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect diff --git a/go.sum b/go.sum index b16e5fee4..197d65b14 100644 --- a/go.sum +++ b/go.sum @@ -115,8 +115,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f h1:B/E9ixKNCasntpoch61NDaQyGPDXLEJlL+B9B/PbdbA= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.4-0.20241012085857-92e97a1cf36d h1:KxTT8dRbN0Zlqpfmae2Zeh58TjTudD4Sp8K7nxWQcJc= -github.com/anchore/stereoscope v0.0.4-0.20241012085857-92e97a1cf36d/go.mod h1:Z3WLp10tFyp04UyGDXg8t+pK++riciVZyflK3YXwZXo= +github.com/anchore/stereoscope v0.0.4-0.20241014194013-93f8a11331e3 h1:sF/L724uET1+jtLq8gW17dNVTkwEzWfgNqRe4+vCclg= +github.com/anchore/stereoscope v0.0.4-0.20241014194013-93f8a11331e3/go.mod h1:6r1peOb9avE+aRy73/RSnCaf1DAj1N9xJUwi6zKmNtA= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= @@ -288,8 +288,8 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I= -github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s= +github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc= +github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/github/go-spdx/v2 v2.3.2 h1:IfdyNHTqzs4zAJjXdVQfRnxt1XMfycXoHBE2Vsm1bjs= github.com/github/go-spdx/v2 v2.3.2/go.mod h1:2ZxKsOhvBp+OYBDlsGnUMcchLeo2mrpEBn2L1C+U3IQ= From 5c0df6386f38303fd2e0fc5c26d54b6313e5d4b0 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 21:37:26 +0000 Subject: [PATCH 267/284] chore(deps): update stereoscope to 1cc8a41d447d0d092699be2b700b8ba62e870434 (#3332) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: willmurphyscode <12529630+willmurphyscode@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 310978064..1e977fc3f 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f - github.com/anchore/stereoscope v0.0.4-0.20241014194013-93f8a11331e3 + github.com/anchore/stereoscope v0.0.4-0.20241014212552-1cc8a41d447d github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // we are hinting brotli to latest due to warning when installing archiver v3: // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption @@ -117,10 +117,10 @@ require ( github.com/charmbracelet/x/term v0.2.0 // indirect github.com/cloudflare/circl v1.3.8 // indirect github.com/containerd/cgroups v1.1.0 // indirect - github.com/containerd/containerd v1.7.22 // indirect + github.com/containerd/containerd v1.7.23 // indirect github.com/containerd/containerd/api v1.7.19 // indirect github.com/containerd/continuity v0.4.2 // indirect - github.com/containerd/errdefs v0.1.0 // indirect + github.com/containerd/errdefs v0.3.0 // indirect github.com/containerd/fifo v1.1.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect diff --git a/go.sum b/go.sum index 197d65b14..094d536ed 100644 --- a/go.sum +++ b/go.sum @@ -115,8 +115,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f h1:B/E9ixKNCasntpoch61NDaQyGPDXLEJlL+B9B/PbdbA= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.4-0.20241014194013-93f8a11331e3 h1:sF/L724uET1+jtLq8gW17dNVTkwEzWfgNqRe4+vCclg= -github.com/anchore/stereoscope v0.0.4-0.20241014194013-93f8a11331e3/go.mod h1:6r1peOb9avE+aRy73/RSnCaf1DAj1N9xJUwi6zKmNtA= +github.com/anchore/stereoscope v0.0.4-0.20241014212552-1cc8a41d447d h1:2izWGTrTGfOh3RS/BV6SqCjDh5sWC2ezOVB9mvYTNCY= +github.com/anchore/stereoscope v0.0.4-0.20241014212552-1cc8a41d447d/go.mod h1:pTHFcI/hFgBQ1R1fljEG1WMQavBRjuzgi+sZ4jotwko= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= @@ -190,14 +190,14 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= -github.com/containerd/containerd v1.7.22 h1:nZuNnNRA6T6jB975rx2RRNqqH2k6ELYKDZfqTHqwyy0= -github.com/containerd/containerd v1.7.22/go.mod h1:e3Jz1rYRUZ2Lt51YrH9Rz0zPyJBOlSvB3ghr2jbVD8g= +github.com/containerd/containerd v1.7.23 h1:H2CClyUkmpKAGlhQp95g2WXHfLYc7whAuvZGBNYOOwQ= +github.com/containerd/containerd v1.7.23/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw= github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA= github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig= github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= -github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM= -github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0= +github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4= +github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= From 138c6e34205b0a6778c2b5c1441f5d8e13f2cfea Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 12:45:07 +0000 Subject: [PATCH 268/284] chore(deps): update stereoscope to 1cc8a41d447d0d092699be2b700b8ba62e870434 (#3334) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: willmurphyscode <12529630+willmurphyscode@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1e977fc3f..07336b72e 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f - github.com/anchore/stereoscope v0.0.4-0.20241014212552-1cc8a41d447d + github.com/anchore/stereoscope v0.0.4 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // we are hinting brotli to latest due to warning when installing archiver v3: // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption diff --git a/go.sum b/go.sum index 094d536ed..74e576963 100644 --- a/go.sum +++ b/go.sum @@ -115,8 +115,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f h1:B/E9ixKNCasntpoch61NDaQyGPDXLEJlL+B9B/PbdbA= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.4-0.20241014212552-1cc8a41d447d h1:2izWGTrTGfOh3RS/BV6SqCjDh5sWC2ezOVB9mvYTNCY= -github.com/anchore/stereoscope v0.0.4-0.20241014212552-1cc8a41d447d/go.mod h1:pTHFcI/hFgBQ1R1fljEG1WMQavBRjuzgi+sZ4jotwko= +github.com/anchore/stereoscope v0.0.4 h1:la/3dA55fX1gU8bcykgYoS0aiqZKulTgmV1CDnDTVtU= +github.com/anchore/stereoscope v0.0.4/go.mod h1:pTHFcI/hFgBQ1R1fljEG1WMQavBRjuzgi+sZ4jotwko= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= From 754cebee6414c614acf03ee0f87abfcf6176e051 Mon Sep 17 00:00:00 2001 From: William Murphy Date: Tue, 15 Oct 2024 08:50:47 -0400 Subject: [PATCH 269/284] fix: stop some log.Warn spam due parsing an empty string as a CPE (#3330) * chore: don't try to parse empty string as CPE Signed-off-by: Will Murphy * chore: improve OS name and version extraction from ELF metadata Signed-off-by: Will Murphy --------- Signed-off-by: Will Murphy --- syft/pkg/cataloger/binary/elf_package.go | 34 +++++++++++++++--------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/syft/pkg/cataloger/binary/elf_package.go b/syft/pkg/cataloger/binary/elf_package.go index 99a989752..81e4384d1 100644 --- a/syft/pkg/cataloger/binary/elf_package.go +++ b/syft/pkg/cataloger/binary/elf_package.go @@ -27,19 +27,7 @@ func newELFPackage(metadata elfBinaryPackageNotes, locations file.LocationSet) p func packageURL(metadata elfBinaryPackageNotes) string { var qualifiers []packageurl.Qualifier - os := metadata.OS - osVersion := metadata.OSVersion - - var atts cpe.Attributes - atts, err := cpe.NewAttributes(metadata.OSCPE) - if err != nil { - log.WithFields("error", err).Warn("unable to parse cpe attributes for elf binary package") - } - // only "upgrade" the OS information if there is something more specific to use in it's place - if os == "" && osVersion == "" || os == "" && atts.Version != "" || atts.Product != "" && osVersion == "" { - os = atts.Product - osVersion = atts.Version - } + os, osVersion := osNameAndVersionFromMetadata(metadata) if os != "" { osQualifier := os @@ -70,6 +58,26 @@ func packageURL(metadata elfBinaryPackageNotes) string { ).ToString() } +func osNameAndVersionFromMetadata(metadata elfBinaryPackageNotes) (string, string) { + os := metadata.OS + osVersion := metadata.OSVersion + + if os != "" && osVersion != "" { + return os, osVersion + } + + if metadata.OSCPE == "" { + return "", "" + } + + attrs, err := cpe.NewAttributes(metadata.OSCPE) + if err != nil { + log.WithFields("error", err).Trace("unable to parse cpe attributes for elf binary package") + return "", "" + } + return attrs.Product, attrs.Version +} + const alpmType = "alpm" func purlDistroType(ty string) string { From d7194bb00fa0b0b7e3d4fd25c18c6585088ab2f7 Mon Sep 17 00:00:00 2001 From: Weston Steimel Date: Wed, 16 Oct 2024 16:43:50 +0000 Subject: [PATCH 270/284] fix: improve mariadb binary classifer to detect older versions (#3339) With older versions of mariadb the binary name was `mysql`, so this adjusts the binary classifier to additionally search for the expected version pattern in `mysql` binaries. Signed-off-by: Weston Steimel --- syft/pkg/cataloger/binary/classifiers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index eb936a93a..fdd7a6ab3 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -351,7 +351,7 @@ func DefaultClassifiers() []Classifier { }, { Class: "mariadb-binary", - FileGlob: "**/mariadb", + FileGlob: "**/{mariadb,mysql}", EvidenceMatcher: FileContentsVersionMatcher( // 10.6.15-MariaDB `(?m)(?P[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)-MariaDB`), From 80c8bc1afbbd1760fb359eb3026297e5fac1cdb0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:44:07 -0400 Subject: [PATCH 271/284] chore(deps): bump anchore/sbom-action from 0.17.3 to 0.17.4 (#3340) Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.17.3 to 0.17.4. - [Release notes](https://github.com/anchore/sbom-action/releases) - [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md) - [Commits](https://github.com/anchore/sbom-action/compare/f5e124a5e5e1d497a692818ae907d3c45829d033...8d0a6505bf28ced3e85154d13dc6af83299e13f1) --- updated-dependencies: - dependency-name: anchore/sbom-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a32578845..0d9b3ca09 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -148,7 +148,7 @@ jobs: # for updating brew formula in anchore/homebrew-syft GITHUB_BREW_TOKEN: ${{ secrets.ANCHOREOPS_GITHUB_OSS_WRITE_TOKEN }} - - uses: anchore/sbom-action@f5e124a5e5e1d497a692818ae907d3c45829d033 #v0.17.3 + - uses: anchore/sbom-action@8d0a6505bf28ced3e85154d13dc6af83299e13f1 #v0.17.4 continue-on-error: true with: artifact-name: sbom.spdx.json From 5b9601d9c64ccf7f4244844e6802b520deca541f Mon Sep 17 00:00:00 2001 From: Weston Steimel Date: Thu, 17 Oct 2024 12:01:40 +0000 Subject: [PATCH 272/284] fix: use official CPE for linux kernel (#3343) Signed-off-by: Weston Steimel --- syft/pkg/cataloger/kernel/cataloger_test.go | 2 ++ syft/pkg/cataloger/kernel/package.go | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/syft/pkg/cataloger/kernel/cataloger_test.go b/syft/pkg/cataloger/kernel/cataloger_test.go index 2d0e66878..a440c7981 100644 --- a/syft/pkg/cataloger/kernel/cataloger_test.go +++ b/syft/pkg/cataloger/kernel/cataloger_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/cpe" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" @@ -22,6 +23,7 @@ func Test_KernelCataloger(t *testing.T) { ), 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)}, Metadata: pkg.LinuxKernel{ Name: "", Architecture: "x86", diff --git a/syft/pkg/cataloger/kernel/package.go b/syft/pkg/cataloger/kernel/package.go index 2d3123ffa..28e9d6a99 100644 --- a/syft/pkg/cataloger/kernel/package.go +++ b/syft/pkg/cataloger/kernel/package.go @@ -4,12 +4,26 @@ import ( "strings" "github.com/anchore/packageurl-go" + "github.com/anchore/syft/syft/cpe" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" ) const linuxKernelPackageName = "linux-kernel" +func createLinuxKernelCPEs(version string) []cpe.CPE { + c := cpe.NewWithAny() + c.Part = "o" + c.Product = "linux_kernel" + c.Vendor = "linux" + c.Version = version + if cpe.ValidateString(c.String()) != nil { + return nil + } + + return []cpe.CPE{{Attributes: c, Source: cpe.NVDDictionaryLookupSource}} +} + func newLinuxKernelPackage(metadata pkg.LinuxKernel, archiveLocation file.Location) pkg.Package { p := pkg.Package{ Name: linuxKernelPackageName, @@ -18,6 +32,7 @@ func newLinuxKernelPackage(metadata pkg.LinuxKernel, archiveLocation file.Locati PURL: packageURL(linuxKernelPackageName, metadata.Version), Type: pkg.LinuxKernelPkg, Metadata: metadata, + CPEs: createLinuxKernelCPEs(metadata.Version), } p.SetID() From f2646d01562b0c745973e57394002245cb0082ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Oct 2024 09:58:16 -0400 Subject: [PATCH 273/284] chore(deps): bump github.com/adrg/xdg from 0.5.0 to 0.5.1 (#3344) Bumps [github.com/adrg/xdg](https://github.com/adrg/xdg) from 0.5.0 to 0.5.1. - [Release notes](https://github.com/adrg/xdg/releases) - [Commits](https://github.com/adrg/xdg/compare/v0.5.0...v0.5.1) --- updated-dependencies: - dependency-name: github.com/adrg/xdg dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 07336b72e..c4fba8ebb 100644 --- a/go.mod +++ b/go.mod @@ -91,7 +91,7 @@ require google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirec require ( github.com/BurntSushi/toml v1.4.0 github.com/OneOfOne/xxhash v1.2.8 - github.com/adrg/xdg v0.5.0 + github.com/adrg/xdg v0.5.1 github.com/magiconair/properties v1.8.7 golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 ) diff --git a/go.sum b/go.sum index 74e576963..d2747fb31 100644 --- a/go.sum +++ b/go.sum @@ -87,8 +87,8 @@ github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpH github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/acobaugh/osrelease v0.1.0 h1:Yb59HQDGGNhCj4suHaFQQfBps5wyoKLSSX/J/+UifRE= github.com/acobaugh/osrelease v0.1.0/go.mod h1:4bFEs0MtgHNHBrmHCt67gNisnabCRAlzdVasCEGHTWY= -github.com/adrg/xdg v0.5.0 h1:dDaZvhMXatArP1NPHhnfaQUqWBLBsmx1h1HXQdMoFCY= -github.com/adrg/xdg v0.5.0/go.mod h1:dDdY4M4DF9Rjy4kHPeNL+ilVF+p2lK8IdM9/rTSGcI4= +github.com/adrg/xdg v0.5.1 h1:Im8iDbEFARltY09yOJlSGu4Asjk2vF85+3Dyru8uJ0U= +github.com/adrg/xdg v0.5.1/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= From 7adbdfe624157ba2acb2406a250cdc921e2e0fad Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Thu, 17 Oct 2024 10:05:18 -0400 Subject: [PATCH 274/284] chore(deps): update stereoscope to 9e57bce5efeb0ffe27770dd0b8eb2eef8b38512f (#3338) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: kzantow <3009477+kzantow@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c4fba8ebb..1e115f68f 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f - github.com/anchore/stereoscope v0.0.4 + github.com/anchore/stereoscope v0.0.5-0.20241015153345-9e57bce5efeb github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // we are hinting brotli to latest due to warning when installing archiver v3: // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption diff --git a/go.sum b/go.sum index d2747fb31..c79857ecd 100644 --- a/go.sum +++ b/go.sum @@ -115,8 +115,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f h1:B/E9ixKNCasntpoch61NDaQyGPDXLEJlL+B9B/PbdbA= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.4 h1:la/3dA55fX1gU8bcykgYoS0aiqZKulTgmV1CDnDTVtU= -github.com/anchore/stereoscope v0.0.4/go.mod h1:pTHFcI/hFgBQ1R1fljEG1WMQavBRjuzgi+sZ4jotwko= +github.com/anchore/stereoscope v0.0.5-0.20241015153345-9e57bce5efeb h1:yCFQfICLjqx2CK7Tjmxb+gj0OlZx1sRKnHOpKF3tsh8= +github.com/anchore/stereoscope v0.0.5-0.20241015153345-9e57bce5efeb/go.mod h1:pTHFcI/hFgBQ1R1fljEG1WMQavBRjuzgi+sZ4jotwko= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= From 326754509791f55d051bb9808009de1e2fc0add5 Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Thu, 17 Oct 2024 10:05:38 -0400 Subject: [PATCH 275/284] chore(deps): update tools to latest versions (#3342) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.binny.yaml b/.binny.yaml index 9f13016b0..9c42f2b25 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -111,7 +111,7 @@ tools: # used for triggering a release - name: gh version: - want: v2.58.0 + want: v2.59.0 method: github-release with: repo: cli/cli From 56dbb342ef9dc0bf65bba7db869fe967f9243390 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Fri, 18 Oct 2024 14:47:02 -0400 Subject: [PATCH 276/284] update to latest packageurl-go (#3347) Signed-off-by: Alex Goodman --- go.mod | 2 +- go.sum | 4 ++-- syft/pkg/cataloger/alpine/package_test.go | 2 +- syft/pkg/cataloger/arch/package_test.go | 2 +- syft/pkg/cataloger/debian/package_test.go | 4 ++-- syft/pkg/cataloger/redhat/package_test.go | 4 ++-- syft/pkg/language_test.go | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 1e115f68f..02bc69171 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b - github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f + github.com/anchore/packageurl-go v0.1.1-0.20241018175412-5c22e6360c4f github.com/anchore/stereoscope v0.0.5-0.20241015153345-9e57bce5efeb github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // we are hinting brotli to latest due to warning when installing archiver v3: diff --git a/go.sum b/go.sum index c79857ecd..79092dcb0 100644 --- a/go.sum +++ b/go.sum @@ -113,8 +113,8 @@ github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 h1:VzprUTpc0v github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04/go.mod h1:6dK64g27Qi1qGQZ67gFmBFvEHScy0/C8qhQhNe5B5pQ= github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZVsCYMrIZBpFxwV26CbsuoEh5muXD5I1Ods= github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= -github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f h1:B/E9ixKNCasntpoch61NDaQyGPDXLEJlL+B9B/PbdbA= -github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= +github.com/anchore/packageurl-go v0.1.1-0.20241018175412-5c22e6360c4f h1:dAQPIrQ3a5PBqZeZ+B9NGZsGmodk4NO9OjDIsQmQyQM= +github.com/anchore/packageurl-go v0.1.1-0.20241018175412-5c22e6360c4f/go.mod h1:KoYIv7tdP5+CC9VGkeZV4/vGCKsY55VvoG+5dadg4YI= github.com/anchore/stereoscope v0.0.5-0.20241015153345-9e57bce5efeb h1:yCFQfICLjqx2CK7Tjmxb+gj0OlZx1sRKnHOpKF3tsh8= github.com/anchore/stereoscope v0.0.5-0.20241015153345-9e57bce5efeb/go.mod h1:pTHFcI/hFgBQ1R1fljEG1WMQavBRjuzgi+sZ4jotwko= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= diff --git a/syft/pkg/cataloger/alpine/package_test.go b/syft/pkg/cataloger/alpine/package_test.go index 78cc77417..ea453806a 100644 --- a/syft/pkg/cataloger/alpine/package_test.go +++ b/syft/pkg/cataloger/alpine/package_test.go @@ -112,7 +112,7 @@ func Test_PackageURL(t *testing.T) { ID: "alpine", VersionID: "3.4.6", }, - expected: "pkg:apk/alpine/p@v?arch=a&upstream=origin&distro=alpine-3.4.6", + expected: "pkg:apk/alpine/p@v?arch=a&distro=alpine-3.4.6&upstream=origin", }, { name: "wolfi distro", diff --git a/syft/pkg/cataloger/arch/package_test.go b/syft/pkg/cataloger/arch/package_test.go index 47a097898..5139bde27 100644 --- a/syft/pkg/cataloger/arch/package_test.go +++ b/syft/pkg/cataloger/arch/package_test.go @@ -108,7 +108,7 @@ func Test_PackageURL(t *testing.T) { ID: "arch", BuildID: "rolling", }, - expected: "pkg:alpm/arch/p@v?arch=a&upstream=origin&distro=arch-rolling", + expected: "pkg:alpm/arch/p@v?arch=a&distro=arch-rolling&upstream=origin", }, } diff --git a/syft/pkg/cataloger/debian/package_test.go b/syft/pkg/cataloger/debian/package_test.go index 87c7728b9..a52659739 100644 --- a/syft/pkg/cataloger/debian/package_test.go +++ b/syft/pkg/cataloger/debian/package_test.go @@ -81,7 +81,7 @@ func Test_packageURL(t *testing.T) { Source: "s", Version: "v", }, - expected: "pkg:deb/debian/p@v?upstream=s&distro=debian-11", + expected: "pkg:deb/debian/p@v?distro=debian-11&upstream=s", }, { name: "with upstream qualifier with source pkg name and version info", @@ -98,7 +98,7 @@ func Test_packageURL(t *testing.T) { Version: "v", SourceVersion: "2.3", }, - expected: "pkg:deb/debian/p@v?upstream=s%402.3&distro=debian-11", + expected: "pkg:deb/debian/p@v?distro=debian-11&upstream=s%402.3", }, } diff --git a/syft/pkg/cataloger/redhat/package_test.go b/syft/pkg/cataloger/redhat/package_test.go index cc24d7d48..c05af2f5f 100644 --- a/syft/pkg/cataloger/redhat/package_test.go +++ b/syft/pkg/cataloger/redhat/package_test.go @@ -43,7 +43,7 @@ func Test_packageURL(t *testing.T) { Release: "r", Epoch: intRef(1), }, - expected: "pkg:rpm/centos/p@v-r?arch=a&epoch=1&distro=centos-7", + expected: "pkg:rpm/centos/p@v-r?arch=a&distro=centos-7&epoch=1", }, { name: "missing distro", @@ -67,7 +67,7 @@ func Test_packageURL(t *testing.T) { Release: "r", SourceRpm: "sourcerpm", }, - expected: "pkg:rpm/redhat/p@v-r?upstream=sourcerpm&distro=rhel-8.4", + expected: "pkg:rpm/redhat/p@v-r?distro=rhel-8.4&upstream=sourcerpm", }, } diff --git a/syft/pkg/language_test.go b/syft/pkg/language_test.go index d5ce5af26..c90ddf932 100644 --- a/syft/pkg/language_test.go +++ b/syft/pkg/language_test.go @@ -87,7 +87,7 @@ func TestLanguageFromPURL(t *testing.T) { want: Lua, }, { - purl: "pkg:opam/ocaml-base-compiler@ 5.2.0", + purl: "pkg:opam/ocaml-base-compiler@5.2.0", want: OCaml, }, } From 5a37b4a9966e312c782d01726e2660e7df0ecffc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 14:02:07 +0000 Subject: [PATCH 277/284] chore(deps): bump github.com/jedib0t/go-pretty/v6 from 6.6.0 to 6.6.1 (#3361) Bumps [github.com/jedib0t/go-pretty/v6](https://github.com/jedib0t/go-pretty) from 6.6.0 to 6.6.1. - [Release notes](https://github.com/jedib0t/go-pretty/releases) - [Commits](https://github.com/jedib0t/go-pretty/compare/v6.6.0...v6.6.1) --- updated-dependencies: - dependency-name: github.com/jedib0t/go-pretty/v6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 02bc69171..b4c416712 100644 --- a/go.mod +++ b/go.mod @@ -48,7 +48,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 github.com/iancoleman/strcase v0.3.0 github.com/invopop/jsonschema v0.7.0 - github.com/jedib0t/go-pretty/v6 v6.6.0 + github.com/jedib0t/go-pretty/v6 v6.6.1 github.com/jinzhu/copier v0.4.0 github.com/kastenhq/goversion v0.0.0-20230811215019-93b2f8823953 github.com/knqyf263/go-rpmdb v0.1.1 diff --git a/go.sum b/go.sum index 79092dcb0..3eddf95c7 100644 --- a/go.sum +++ b/go.sum @@ -483,8 +483,8 @@ github.com/invopop/jsonschema v0.7.0 h1:2vgQcBz1n256N+FpX3Jq7Y17AjYt46Ig3zIWyy77 github.com/invopop/jsonschema v0.7.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jedib0t/go-pretty/v6 v6.6.0 h1:wmZVuAcEkZRT+Aq1xXpE8IGat4vE5WXOMmBpbQqERXw= -github.com/jedib0t/go-pretty/v6 v6.6.0/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= +github.com/jedib0t/go-pretty/v6 v6.6.1 h1:iJ65Xjb680rHcikRj6DSIbzCex2huitmc7bDtxYVWyc= +github.com/jedib0t/go-pretty/v6 v6.6.1/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= From e38825a0a2186478659f5d504b781167e1ad098e Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 10:04:25 -0400 Subject: [PATCH 278/284] chore(deps): update CPE dictionary index (#3358) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: wagoodman <590471+wagoodman@users.noreply.github.com> --- .../dictionary/data/cpe-index.json | 80 ++++++++++++++++--- 1 file changed, 70 insertions(+), 10 deletions(-) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index 89e1d9fb2..816206aea 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -100,6 +100,9 @@ "github.com/sap/cloud-security-client-go": [ "cpe:2.3:a:sap:cloud-security-client-go:*:*:*:*:*:go:*:*" ], + "github.com/satori/go.uuid": [ + "cpe:2.3:a:satori:uuid:*:*:*:*:*:go:*:*" + ], "github.com/sigstore/gitsign": [ "cpe:2.3:a:sigstore:gitsign:*:*:*:*:*:go:*:*" ], @@ -2934,7 +2937,7 @@ "cpe:2.3:a:electron-packager_project:electron-packager:*:*:*:*:*:node.js:*:*" ], "elliptic": [ - "cpe:2.3:a:elliptic_project:elliptic:*:*:*:*:*:node.js:*:*" + "cpe:2.3:a:indutny:elliptic:*:*:*:*:*:node.js:*:*" ], "embedza": [ "cpe:2.3:a:embedza_project:embedza:*:*:*:*:*:node.js:*:*" @@ -5691,6 +5694,9 @@ "jw.util": [ "cpe:2.3:a:python:jw.util:*:*:*:*:*:python:*:*" ], + "jwcrypto": [ + "cpe:2.3:a:latchset:jwcrypto:*:*:*:*:*:*:*:*" + ], "keep": [ "cpe:2.3:a:keep_project:keep:*:*:*:*:*:*:*:*" ], @@ -8185,6 +8191,9 @@ "blogger-importer": [ "cpe:2.3:a:wordpress:blogger_importer:*:*:*:*:*:wordpress:*:*" ], + "blogintroduction-wordpress-plugin": [ + "cpe:2.3:a:kimhuebel:blog_introduction:*:*:*:*:*:wordpress:*:*" + ], "blogmentor": [ "cpe:2.3:a:auburnforest:blogmentor:*:*:*:*:*:wordpress:*:*" ], @@ -9352,6 +9361,9 @@ "cssable-countdown": [ "cpe:2.3:a:dmonnier:cssable_countdown:*:*:*:*:*:wordpress:*:*" ], + "cssjockey-add-ons": [ + "cpe:2.3:a:cssjockey:wp_builder:*:*:*:*:*:wordpress:*:*" + ], "csv-import-export": [ "cpe:2.3:a:csv-import-export_project:csv-import-export:*:*:*:*:*:wordpress:*:*" ], @@ -9374,6 +9386,9 @@ "cube-slider": [ "cpe:2.3:a:webpsilon:cube_slider:*:*:*:*:*:wordpress:*:*" ], + "curatorio": [ + "cpe:2.3:a:curator:curator.io:*:*:*:*:*:wordpress:*:*" + ], "currency-converter-calculator": [ "cpe:2.3:a:currencyratetoday:currency_converter_calculator:*:*:*:*:*:wordpress:*:*" ], @@ -10122,11 +10137,14 @@ "cpe:2.3:a:elementor:elementor_page_builder:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:elementor:elementor_page_builder:*:*:*:*:pro:wordpress:*:*", "cpe:2.3:a:elementor:page_builder:*:*:*:*:*:wordpress:*:*", - "cpe:2.3:a:elementor:website_builder:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:elementor:website_builder:*:*:*:*:free:wordpress:*:*" ], "elementor-pro": [ "cpe:2.3:a:elementor:elementor_pro:*:*:*:*:*:wordpress:*:*" ], + "elementskit": [ + "cpe:2.3:a:wpmet:elementskit:*:*:*:*:pro:wordpress:*:*" + ], "elementskit-lite": [ "cpe:2.3:a:wpmet:elements_kit_elementor_addons:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:wpmet:elementskit_elementor_addons:*:*:*:*:*:wordpress:*:*" @@ -10338,7 +10356,8 @@ "cpe:2.3:a:eventify_project:eventify:*:*:*:*:*:wordpress:*:*" ], "eventon-lite": [ - "cpe:2.3:a:myeventon:eventon-lite:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:myeventon:eventon-lite:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:myeventon:eventon:*:*:*:*:lite:wordpress:*:*" ], "eventprime-event-calendar-management": [ "cpe:2.3:a:metagauss:eventprime:*:*:*:*:*:wordpress:*:*" @@ -10692,6 +10711,9 @@ "cpe:2.3:a:floating_social_bar_project:floating_social_bar:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:wpbeginner:floating_social_bar:*:*:*:*:wordpress:*:*:*" ], + "floating-social-buttons": [ + "cpe:2.3:a:click2check:floating_social_buttons:*:*:*:*:*:wordpress:*:*" + ], "floating-social-media-icon": [ "cpe:2.3:a:acurax:floating_social_media_icon:*:*:*:*:*:wordpress:*:*" ], @@ -10756,10 +10778,11 @@ "cpe:2.3:a:fivestarplugins:five_star_restaurant_menu:*:*:*:*:*:wordpress:*:*" ], "foogallery": [ - "cpe:2.3:a:fooplugins:foogallery:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:fooplugins:foogallery:*:*:*:*:-:wordpress:*:*", + "cpe:2.3:a:fooplugins:foogallery:*:*:*:*:premium:wordpress:*:*" ], "foogallery-premium": [ - "cpe:2.3:a:fooplugins:foogallery:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:fooplugins:foogallery:*:*:*:*:-:wordpress:*:*" ], "football-leagues-by-anwppro": [ "cpe:2.3:a:anwp:football_leagues:*:*:*:*:free:wordpress:*:*", @@ -11754,6 +11777,9 @@ "inline-google-spreadsheet-viewer": [ "cpe:2.3:a:inline_google_spreadsheet_viewer_project:inline_google_spreadsheet_viewer:*:*:*:*:*:wordpress:*:*" ], + "inline-svg-elementor": [ + "cpe:2.3:a:namogo:elementor_inline_svg:*:*:*:*:*:wordpress:*:*" + ], "inline-tweet-sharer": [ "cpe:2.3:a:winwar:inline_tweet_sharer:*:*:*:*:*:wordpress:*:*" ], @@ -12481,6 +12507,7 @@ "cpe:2.3:a:mailcwp_project:mailcwp:*:*:*:*:*:wordpress:*:*" ], "mailin": [ + "cpe:2.3:a:brevo:newsletter\\,_smtp\\,_email_marketing_and_subscribe:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:sendinblue:newsletter\\,_smtp\\,_email_marketing_and_subscribe:*:*:*:*:*:wordpress:*:*" ], "mailmunch": [ @@ -12611,6 +12638,9 @@ "maxbuttons": [ "cpe:2.3:a:maxfoundry:maxbuttons:*:*:*:*:*:wordpress:*:*" ], + "maximum-products-per-user-for-woocommerce": [ + "cpe:2.3:a:wpfactory:maximum_products_per_user_for_woocommerce:*:*:*:*:free:wordpress:*:*" + ], "maz-loader": [ "cpe:2.3:a:feataholic:maz_loader:*:*:*:*:*:wordpress:*:*" ], @@ -13116,6 +13146,9 @@ "new-image-gallery": [ "cpe:2.3:a:awplife:image_gallery:*:*:*:*:*:wordpress:*:*" ], + "new-order-notification-for-woocommerce": [ + "cpe:2.3:a:mrebabi:new_order_notification_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], "new-user-approve": [ "cpe:2.3:a:wpexperts:new_user_approve:*:*:*:*:*:wordpress:*:*" ], @@ -13232,6 +13265,9 @@ "notification": [ "cpe:2.3:a:bracketspace:notification:*:*:*:*:*:wordpress:*:*" ], + "notification-for-telegram": [ + "cpe:2.3:a:andreamarinucci:notification_for_telegram:*:*:*:*:*:wordpress:*:*" + ], "notificationx": [ "cpe:2.3:a:wpdeveloper:notificationx:*:*:*:*:*:wordpress:*:*" ], @@ -13794,7 +13830,8 @@ "cpe:2.3:a:ays-pro:poll_maker:*:*:*:*:*:wordpress:*:*" ], "poll-wp": [ - "cpe:2.3:a:total-soft:responsive_poll:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:total-soft:responsive_poll:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:total-soft:ts_poll:*:*:*:*:*:wordpress:*:*" ], "polldaddy": [ "cpe:2.3:a:automattic:crowdsignal_dashboard:*:*:*:*:*:wordpress:*:*" @@ -14081,6 +14118,9 @@ "process-steps-template-designer": [ "cpe:2.3:a:coolplugins:process_steps_template_designer:*:*:*:*:*:wordpress:*:*" ], + "product-blocks": [ + "cpe:2.3:a:wpxpo:wowstore:*:*:*:*:free:wordpress:*:*" + ], "product-carousel-slider-for-woocommerce": [ "cpe:2.3:a:aazztech:woocommerce_product_carousel_slider:*:*:*:*:*:wordpress:*:*" ], @@ -14191,6 +14231,9 @@ "q2w3-post-order": [ "cpe:2.3:a:q2w3:q2w3_post_order:*:*:*:*:*:wordpress:*:*" ], + "qa-heatmap-analytics": [ + "cpe:2.3:a:quarka:qa_analytics:*:*:*:*:*:wordpress:*:*" + ], "qi-addons-for-elementor": [ "cpe:2.3:a:qodeinteractive:qi_addons_for_elementor:*:*:*:*:*:wordpress:*:*" ], @@ -15535,6 +15578,9 @@ "social-buttons-pack": [ "cpe:2.3:a:bestwebsoft:social_buttons_pack:*:*:*:*:*:wordpress:*:*" ], + "social-icons-widget-by-wpzoom": [ + "cpe:2.3:a:wpzoom:social_icons_widget:*:*:*:*:free:wordpress:*:*" + ], "social-locker": [ "cpe:2.3:a:byonepress:social_locker:*:*:*:*:*:wordpress:*:*" ], @@ -16136,6 +16182,9 @@ "thumbs-rating": [ "cpe:2.3:a:quicoto:thumbs_rating:*:*:*:*:*:wordpress:*:*" ], + "ti-woocommerce-wishlist": [ + "cpe:2.3:a:templateinvaders:ti_woocommerce_wishlist:*:*:*:*:free:wordpress:*:*" + ], "tickera-event-ticketing-system": [ "cpe:2.3:a:tickera:tickera:*:*:*:*:*:wordpress:*:*" ], @@ -16314,6 +16363,9 @@ "two-factor-authentication": [ "cpe:2.3:a:simbahosting:two-factor-authentication:*:*:*:*:*:wordpress:*:*" ], + "two-factor-login-telegram": [ + "cpe:2.3:a:dueclic:wp_2fa_with_telegram:*:*:*:*:*:wordpress:*:*" + ], "typebot": [ "cpe:2.3:a:typebot:typebot:*:*:*:*:*:wordpress:*:*" ], @@ -16481,7 +16533,7 @@ "cpe:2.3:a:unitecms:unlimited_addons_for_wpbakery_page_builder:*:*:*:*:*:wordpress:*:*" ], "unlimited-elements-for-elementor": [ - "cpe:2.3:a:unlimited-elements:unlimited_elements_for_elementor_\\(free_widgets\\,_addons\\,_templates\\):*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:unlimited-elements:unlimited_elements_for_elementor:*:*:*:*:*:wordpress:*:*" ], "unlimited-popups": [ "cpe:2.3:a:unlimited_popups_project:unlimited_popups:*:*:*:*:*:wordpress:*:*" @@ -16972,6 +17024,9 @@ "whizz": [ "cpe:2.3:a:browserweb:whizz:*:*:*:*:*:wordpress:*:*" ], + "wholesale-pricing-woocommerce": [ + "cpe:2.3:a:wpfactory:quantity_dynamic_pricing_\\\u0026_bulk_discounts_for_woocommerce:*:*:*:*:free:wordpress:*:*" + ], "whydowork-adsense": [ "cpe:2.3:a:whydowork_adsense_project:whydowork_adsense:*:*:*:*:*:wordpress:*:*" ], @@ -17193,6 +17248,7 @@ ], "woocommerce": [ "cpe:2.3:a:woocommerce:woocommerce:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:woocommerce:woocommerce:*:*:*:*:free:wordpress:*:*", "cpe:2.3:a:woothemes:woocommerce:*:*:*:*:*:wordpress:*:*" ], "woocommerce-abandoned-cart": [ @@ -17408,7 +17464,7 @@ "cpe:2.3:a:wp_admin_logo_changer_project:wp_admin_logo_changer:*:*:*:*:*:wordpress:*:*" ], "wp-advanced-search": [ - "cpe:2.3:a:wp-advanced-search_project:wp-advanced-search:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:internet-formation:wp-advanced-search:*:*:*:*:*:wordpress:*:*" ], "wp-airbnb-review-slider": [ "cpe:2.3:a:ljapps:wp_airbnb_review_slider:*:*:*:*:*:wordpress:*:*" @@ -17793,10 +17849,11 @@ "cpe:2.3:a:surniaulula:jsm_file_get_contents\\(\\)_shortcode:*:*:*:*:*:wordpress:*:*" ], "wp-file-manager": [ + "cpe:2.3:a:filemanagerpro:file_manager:*:*:*:*:free:wordpress:*:*", "cpe:2.3:a:webdesi9:file_manager:*:*:*:*:*:wordpress:*:*" ], "wp-file-manager-pro": [ - "cpe:2.3:a:filemanagerpro:file_manager_pro:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:filemanagerpro:file_manager:*:*:*:*:pro:wordpress:*:*" ], "wp-file-upload": [ "cpe:2.3:a:iptanus:wordpress_file_upload:*:*:*:*:*:wordpress:*:*" @@ -18509,6 +18566,9 @@ "wp-terms-popup": [ "cpe:2.3:a:linksoftwarellc:wp_terms_popup:*:*:*:*:*:wordpress:*:*" ], + "wp-testimonial-widget": [ + "cpe:2.3:a:starkdigital:wp_testimonial_widget:*:*:*:*:*:wordpress:*:*" + ], "wp-testing": [ "cpe:2.3:a:psychological_tests_\\\u0026_quizzes_project:psychological_tests_\\\u0026_quizzes:*:*:*:*:*:wordpress:*:*" ], @@ -19020,7 +19080,7 @@ "cpe:2.3:a:stefanoai:widget_responsive_for_youtube:*:*:*:*:*:wordpress:*:*" ], "youzify": [ - "cpe:2.3:a:kainelabs:youzify:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:kainelabs:youzify:*:*:*:*:free:wordpress:*:*" ], "yt-player": [ "cpe:2.3:a:video_player_for_youtube_project:video_player_for_youtube:*:*:*:*:*:wordpress:*:*" From 14355aac2157482fc6d4dc34a608f779912e6d2b Mon Sep 17 00:00:00 2001 From: "anchore-actions-token-generator[bot]" <102182147+anchore-actions-token-generator[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 10:05:43 -0400 Subject: [PATCH 279/284] chore(deps): update stereoscope to a38c93517fc7d67ca1af826ac529a06c05b571d2 (#3357) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: kzantow <3009477+kzantow@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b4c416712..2dc477853 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b github.com/anchore/packageurl-go v0.1.1-0.20241018175412-5c22e6360c4f - github.com/anchore/stereoscope v0.0.5-0.20241015153345-9e57bce5efeb + github.com/anchore/stereoscope v0.0.5-0.20241018131503-a38c93517fc7 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // we are hinting brotli to latest due to warning when installing archiver v3: // go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption diff --git a/go.sum b/go.sum index 3eddf95c7..c4f66295d 100644 --- a/go.sum +++ b/go.sum @@ -115,8 +115,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.1.1-0.20241018175412-5c22e6360c4f h1:dAQPIrQ3a5PBqZeZ+B9NGZsGmodk4NO9OjDIsQmQyQM= github.com/anchore/packageurl-go v0.1.1-0.20241018175412-5c22e6360c4f/go.mod h1:KoYIv7tdP5+CC9VGkeZV4/vGCKsY55VvoG+5dadg4YI= -github.com/anchore/stereoscope v0.0.5-0.20241015153345-9e57bce5efeb h1:yCFQfICLjqx2CK7Tjmxb+gj0OlZx1sRKnHOpKF3tsh8= -github.com/anchore/stereoscope v0.0.5-0.20241015153345-9e57bce5efeb/go.mod h1:pTHFcI/hFgBQ1R1fljEG1WMQavBRjuzgi+sZ4jotwko= +github.com/anchore/stereoscope v0.0.5-0.20241018131503-a38c93517fc7 h1:CBKDfuMWKRt12EnKtgT/an9FQSQI83mOU1KT57z81IU= +github.com/anchore/stereoscope v0.0.5-0.20241018131503-a38c93517fc7/go.mod h1:wH79ZauZcd3erKPocg9+qhDC6Q/z125sD+Isi4d61a4= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= From e4e985b9b05b9570648399adf292ab7f659b4cef Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Mon, 21 Oct 2024 12:17:12 -0400 Subject: [PATCH 280/284] Create single license scanner for all catalogers (#3348) * add single license scanner instance Signed-off-by: Alex Goodman * rename testing license scanner Signed-off-by: Alex Goodman --------- Signed-off-by: Alex Goodman --- internal/licenses/context.go | 18 +++++ internal/licenses/parser.go | 45 ------------ internal/licenses/scanner.go | 68 +++++++++++++++++++ internal/licenses/search.go | 28 ++++++++ syft/create_sbom.go | 4 ++ syft/pkg/cataloger/generic/cataloger.go | 4 +- syft/pkg/cataloger/golang/licenses.go | 30 ++++---- syft/pkg/cataloger/golang/licenses_test.go | 24 ++++--- syft/pkg/cataloger/golang/package.go | 8 +-- syft/pkg/cataloger/golang/parse_go_binary.go | 28 ++++++-- .../cataloger/golang/parse_go_binary_test.go | 6 +- syft/pkg/cataloger/golang/parse_go_mod.go | 13 ++-- syft/pkg/cataloger/java/archive_parser.go | 64 +++++++++-------- .../pkg/cataloger/java/archive_parser_test.go | 28 +++++--- syft/pkg/cataloger/python/package.go | 42 ++++++------ syft/pkg/cataloger/python/parse_wheel_egg.go | 15 +++- 16 files changed, 277 insertions(+), 148 deletions(-) create mode 100644 internal/licenses/context.go delete mode 100644 internal/licenses/parser.go create mode 100644 internal/licenses/scanner.go create mode 100644 internal/licenses/search.go diff --git a/internal/licenses/context.go b/internal/licenses/context.go new file mode 100644 index 000000000..9a1224dae --- /dev/null +++ b/internal/licenses/context.go @@ -0,0 +1,18 @@ +package licenses + +import ( + "context" +) + +type licenseScannerKey struct{} + +func SetContextLicenseScanner(ctx context.Context, s Scanner) context.Context { + return context.WithValue(ctx, licenseScannerKey{}, s) +} + +func ContextLicenseScanner(ctx context.Context) Scanner { + if s, ok := ctx.Value(licenseScannerKey{}).(Scanner); ok { + return s + } + return NewDefaultScanner() +} diff --git a/internal/licenses/parser.go b/internal/licenses/parser.go deleted file mode 100644 index c9f77d567..000000000 --- a/internal/licenses/parser.go +++ /dev/null @@ -1,45 +0,0 @@ -package licenses - -import ( - "io" - - "github.com/google/licensecheck" - - "github.com/anchore/syft/syft/file" - "github.com/anchore/syft/syft/license" - "github.com/anchore/syft/syft/pkg" -) - -const ( - coverageThreshold = 75 - unknownLicenseType = "UNKNOWN" -) - -// Parse scans the contents of a license file to attempt to determine the type of license it is -func Parse(reader io.Reader, l file.Location) (licenses []pkg.License, err error) { - licenses = make([]pkg.License, 0) - contents, err := io.ReadAll(reader) - if err != nil { - return nil, err - } - - scanner, err := licensecheck.NewScanner(licensecheck.BuiltinLicenses()) - if err != nil { - return nil, err - } - - cov := scanner.Scan(contents) - if cov.Percent < coverageThreshold { - // unknown or no licenses here? - return licenses, nil - } - - for _, m := range cov.Match { - lic := pkg.NewLicenseFromLocations(m.ID, l) - lic.Type = license.Concluded - - licenses = append(licenses, lic) - } - - return licenses, nil -} diff --git a/internal/licenses/scanner.go b/internal/licenses/scanner.go new file mode 100644 index 000000000..5efb1d3a3 --- /dev/null +++ b/internal/licenses/scanner.go @@ -0,0 +1,68 @@ +package licenses + +import ( + "context" + "io" + + "github.com/google/licensecheck" + + "github.com/anchore/syft/internal/log" +) + +const coverageThreshold = 75 // determined by experimentation + +type Scanner interface { + IdentifyLicenseIDs(context.Context, io.Reader) ([]string, error) +} + +var _ Scanner = (*scanner)(nil) + +type scanner struct { + coverageThreshold float64 // between 0 and 100 + scanner func([]byte) licensecheck.Coverage +} + +// NewDefaultScanner returns a scanner that uses a new instance of the default licensecheck package scanner. +func NewDefaultScanner() Scanner { + s, err := licensecheck.NewScanner(licensecheck.BuiltinLicenses()) + if err != nil { + log.WithFields("error", err).Trace("unable to create default license scanner") + s = nil + } + return &scanner{ + coverageThreshold: coverageThreshold, + scanner: s.Scan, + } +} + +// TestingOnlyScanner returns a scanner that uses the built-in license scanner from the licensecheck package. +// THIS IS ONLY MEANT FOR TEST CODE, NOT PRODUCTION CODE. +func TestingOnlyScanner() Scanner { + return &scanner{ + coverageThreshold: coverageThreshold, + scanner: licensecheck.Scan, + } +} + +func (s scanner) IdentifyLicenseIDs(_ context.Context, reader io.Reader) ([]string, error) { + if s.scanner == nil { + return nil, nil + } + + content, err := io.ReadAll(reader) + if err != nil { + return nil, err + } + + cov := s.scanner(content) + if cov.Percent < s.coverageThreshold { + // unknown or no licenses here? + return nil, nil + } + + var ids []string + for _, m := range cov.Match { + ids = append(ids, m.ID) + } + return ids, nil +} diff --git a/internal/licenses/search.go b/internal/licenses/search.go new file mode 100644 index 000000000..47dc14e45 --- /dev/null +++ b/internal/licenses/search.go @@ -0,0 +1,28 @@ +package licenses + +import ( + "context" + + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/license" + "github.com/anchore/syft/syft/pkg" +) + +// Search scans the contents of a license file to attempt to determine the type of license it is +func Search(ctx context.Context, scanner Scanner, reader file.LocationReadCloser) (licenses []pkg.License, err error) { + licenses = make([]pkg.License, 0) + + ids, err := scanner.IdentifyLicenseIDs(ctx, reader) + if err != nil { + return nil, err + } + + for _, id := range ids { + lic := pkg.NewLicenseFromLocations(id, reader.Location) + lic.Type = license.Concluded + + licenses = append(licenses, lic) + } + + return licenses, nil +} diff --git a/syft/create_sbom.go b/syft/create_sbom.go index 3e4010eea..1e526fd90 100644 --- a/syft/create_sbom.go +++ b/syft/create_sbom.go @@ -9,6 +9,7 @@ import ( "github.com/scylladb/go-set/strset" "github.com/anchore/syft/internal/bus" + "github.com/anchore/syft/internal/licenses" "github.com/anchore/syft/internal/sbomsync" "github.com/anchore/syft/internal/task" "github.com/anchore/syft/syft/artifact" @@ -60,6 +61,9 @@ func CreateSBOM(ctx context.Context, src source.Source, cfg *CreateSBOMConfig) ( }, } + // inject a single license scanner for all package cataloging tasks into context + ctx = licenses.SetContextLicenseScanner(ctx, licenses.NewDefaultScanner()) + catalogingProgress := monitorCatalogingTask(src.ID(), taskGroups) packageCatalogingProgress := monitorPackageCatalogingTask() diff --git a/syft/pkg/cataloger/generic/cataloger.go b/syft/pkg/cataloger/generic/cataloger.go index f955ed350..db23fad73 100644 --- a/syft/pkg/cataloger/generic/cataloger.go +++ b/syft/pkg/cataloger/generic/cataloger.go @@ -154,7 +154,7 @@ func (c *Cataloger) Catalog(ctx context.Context, resolver file.Resolver) ([]pkg. var relationships []artifact.Relationship var errs error - logger := log.Nested("cataloger", c.upstreamCataloger) + lgr := log.Nested("cataloger", c.upstreamCataloger) env := Environment{ // TODO: consider passing into the cataloger, this would affect the cataloger interface (and all implementations). This can be deferred until later. @@ -166,7 +166,7 @@ func (c *Cataloger) Catalog(ctx context.Context, resolver file.Resolver) ([]pkg. log.WithFields("path", location.RealPath).Trace("parsing file contents") - discoveredPackages, discoveredRelationships, err := invokeParser(ctx, resolver, location, logger, parser, &env) + discoveredPackages, discoveredRelationships, err := invokeParser(ctx, resolver, location, lgr, parser, &env) if err != nil { // parsers may return errors and valid packages / relationships errs = unknown.Append(errs, location, err) diff --git a/syft/pkg/cataloger/golang/licenses.go b/syft/pkg/cataloger/golang/licenses.go index 0b02c6581..402a01448 100644 --- a/syft/pkg/cataloger/golang/licenses.go +++ b/syft/pkg/cataloger/golang/licenses.go @@ -3,6 +3,7 @@ package golang import ( "archive/zip" "bytes" + "context" "fmt" "io" "io/fs" @@ -79,9 +80,9 @@ func remotesForModule(proxies []string, noProxy []string, module string) []strin return proxies } -func (c *goLicenseResolver) getLicenses(resolver file.Resolver, moduleName, moduleVersion string) ([]pkg.License, error) { +func (c *goLicenseResolver) getLicenses(ctx context.Context, scanner licenses.Scanner, resolver file.Resolver, moduleName, moduleVersion string) ([]pkg.License, error) { // search the scan target first, ignoring local and remote sources - goLicenses, err := c.findLicensesInSource(resolver, + goLicenses, err := c.findLicensesInSource(ctx, scanner, resolver, fmt.Sprintf(`**/go/pkg/mod/%s@%s/*`, processCaps(moduleName), moduleVersion), ) if err != nil || len(goLicenses) > 0 { @@ -90,7 +91,7 @@ func (c *goLicenseResolver) getLicenses(resolver file.Resolver, moduleName, modu // look in the local host mod directory... if c.opts.SearchLocalModCacheLicenses { - goLicenses, err = c.getLicensesFromLocal(moduleName, moduleVersion) + goLicenses, err = c.getLicensesFromLocal(ctx, scanner, moduleName, moduleVersion) if err != nil || len(goLicenses) > 0 { return toPkgLicenses(goLicenses), err } @@ -98,13 +99,13 @@ func (c *goLicenseResolver) getLicenses(resolver file.Resolver, moduleName, modu // download from remote sources if c.opts.SearchRemoteLicenses { - goLicenses, err = c.getLicensesFromRemote(moduleName, moduleVersion) + goLicenses, err = c.getLicensesFromRemote(ctx, scanner, moduleName, moduleVersion) } return toPkgLicenses(goLicenses), err } -func (c *goLicenseResolver) getLicensesFromLocal(moduleName, moduleVersion string) ([]goLicense, error) { +func (c *goLicenseResolver) getLicensesFromLocal(ctx context.Context, scanner licenses.Scanner, moduleName, moduleVersion string) ([]goLicense, error) { if c.localModCacheDir == nil { return nil, nil } @@ -120,10 +121,10 @@ func (c *goLicenseResolver) getLicensesFromLocal(moduleName, moduleVersion strin // if we're running against a directory on the filesystem, it may not include the // user's homedir / GOPATH, so we defer to using the localModCacheResolver // we use $GOPATH/pkg/mod to avoid leaking information about the user's system - return c.findLicensesInFS("file://$GOPATH/pkg/mod/"+subdir+"/", dir) + return c.findLicensesInFS(ctx, scanner, "file://$GOPATH/pkg/mod/"+subdir+"/", dir) } -func (c *goLicenseResolver) getLicensesFromRemote(moduleName, moduleVersion string) ([]goLicense, error) { +func (c *goLicenseResolver) getLicensesFromRemote(ctx context.Context, scanner licenses.Scanner, moduleName, moduleVersion string) ([]goLicense, error) { return c.licenseCache.Resolve(fmt.Sprintf("%s/%s", moduleName, moduleVersion), func() ([]goLicense, error) { proxies := remotesForModule(c.opts.Proxies, c.opts.NoProxy, moduleName) @@ -132,11 +133,11 @@ func (c *goLicenseResolver) getLicensesFromRemote(moduleName, moduleVersion stri return nil, err } - return c.findLicensesInFS(urlPrefix, fsys) + return c.findLicensesInFS(ctx, scanner, urlPrefix, fsys) }) } -func (c *goLicenseResolver) findLicensesInFS(urlPrefix string, fsys fs.FS) ([]goLicense, error) { +func (c *goLicenseResolver) findLicensesInFS(ctx context.Context, scanner licenses.Scanner, urlPrefix string, fsys fs.FS) ([]goLicense, error) { var out []goLicense err := fs.WalkDir(fsys, ".", func(filePath string, d fs.DirEntry, err error) error { if err != nil { @@ -156,7 +157,8 @@ func (c *goLicenseResolver) findLicensesInFS(urlPrefix string, fsys fs.FS) ([]go return nil } defer internal.CloseAndLogError(rdr, filePath) - parsed, err := licenses.Parse(rdr, file.NewLocation(filePath)) + + parsed, err := licenses.Search(ctx, scanner, file.NewLocationReadCloser(file.NewLocation(filePath), rdr)) if err != nil { log.Debugf("error parsing license file %s: %v", filePath, err) return nil @@ -174,7 +176,7 @@ func (c *goLicenseResolver) findLicensesInFS(urlPrefix string, fsys fs.FS) ([]go return out, err } -func (c *goLicenseResolver) findLicensesInSource(resolver file.Resolver, globMatch string) ([]goLicense, error) { +func (c *goLicenseResolver) findLicensesInSource(ctx context.Context, scanner licenses.Scanner, resolver file.Resolver, globMatch string) ([]goLicense, error) { var out []goLicense locations, err := resolver.FilesByGlob(globMatch) if err != nil { @@ -182,7 +184,7 @@ func (c *goLicenseResolver) findLicensesInSource(resolver file.Resolver, globMat } for _, l := range locations { - parsed, err := c.parseLicenseFromLocation(l, resolver) + parsed, err := c.parseLicenseFromLocation(ctx, scanner, l, resolver) if err != nil { return nil, err } @@ -200,7 +202,7 @@ func (c *goLicenseResolver) findLicensesInSource(resolver file.Resolver, globMat return out, nil } -func (c *goLicenseResolver) parseLicenseFromLocation(l file.Location, resolver file.Resolver) ([]goLicense, error) { +func (c *goLicenseResolver) parseLicenseFromLocation(ctx context.Context, scanner licenses.Scanner, l file.Location, resolver file.Resolver) ([]goLicense, error) { var out []goLicense fileName := path.Base(l.RealPath) if c.lowerLicenseFileNames.Has(strings.ToLower(fileName)) { @@ -209,7 +211,7 @@ func (c *goLicenseResolver) parseLicenseFromLocation(l file.Location, resolver f return nil, err } defer internal.CloseAndLogError(contents, l.RealPath) - parsed, err := licenses.Parse(contents, l) + parsed, err := licenses.Search(ctx, scanner, file.NewLocationReadCloser(l, contents)) if err != nil { return nil, err } diff --git a/syft/pkg/cataloger/golang/licenses_test.go b/syft/pkg/cataloger/golang/licenses_test.go index 0ac644faf..0acde6de9 100644 --- a/syft/pkg/cataloger/golang/licenses_test.go +++ b/syft/pkg/cataloger/golang/licenses_test.go @@ -3,6 +3,7 @@ package golang import ( "archive/zip" "bytes" + "context" "fmt" "io/fs" "net/http" @@ -15,6 +16,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/anchore/syft/internal/licenses" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/internal/fileresolver" "github.com/anchore/syft/syft/license" @@ -26,6 +28,8 @@ func Test_LocalLicenseSearch(t *testing.T) { loc2 := file.NewLocation("github.com/!cap!o!r!g/!cap!project@v4.111.5/LICENSE.txt") loc3 := file.NewLocation("github.com/someorg/strangelicense@v1.2.3/LiCeNsE.tXt") + licenseScanner := licenses.TestingOnlyScanner() + tests := []struct { name string version string @@ -78,12 +82,12 @@ func Test_LocalLicenseSearch(t *testing.T) { LocalModCacheDir: filepath.Join(wd, "test-fixtures", "licenses", "pkg", "mod"), }, ) - licenses, err := l.getLicenses(fileresolver.Empty{}, test.name, test.version) + lics, err := l.getLicenses(context.Background(), licenseScanner, fileresolver.Empty{}, test.name, test.version) require.NoError(t, err) - require.Len(t, licenses, 1) + require.Len(t, lics, 1) - require.Equal(t, test.expected, licenses[0]) + require.Equal(t, test.expected, lics[0]) }) } } @@ -92,6 +96,8 @@ func Test_RemoteProxyLicenseSearch(t *testing.T) { loc1 := file.NewLocation("github.com/someorg/somename@v0.3.2/LICENSE") loc2 := file.NewLocation("github.com/!cap!o!r!g/!cap!project@v4.111.5/LICENSE.txt") + licenseScanner := licenses.TestingOnlyScanner() + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { buf := &bytes.Buffer{} uri := strings.TrimPrefix(strings.TrimSuffix(r.RequestURI, ".zip"), "/") @@ -169,12 +175,12 @@ func Test_RemoteProxyLicenseSearch(t *testing.T) { }, ) - licenses, err := l.getLicenses(fileresolver.Empty{}, test.name, test.version) + lics, err := l.getLicenses(context.Background(), licenseScanner, fileresolver.Empty{}, test.name, test.version) require.NoError(t, err) - require.Len(t, licenses, 1) + require.Len(t, lics, 1) - require.Equal(t, test.expected, licenses[0]) + require.Equal(t, test.expected, lics[0]) }) } } @@ -248,7 +254,7 @@ func Test_findVersionPath(t *testing.T) { func Test_walkDirErrors(t *testing.T) { resolver := newGoLicenseResolver("", CatalogerConfig{}) - _, err := resolver.findLicensesInFS("somewhere", badFS{}) + _, err := resolver.findLicensesInFS(context.Background(), licenses.TestingOnlyScanner(), "somewhere", badFS{}) require.Error(t, err) } @@ -266,6 +272,8 @@ func Test_noLocalGoModDir(t *testing.T) { validTmp := t.TempDir() require.NoError(t, os.MkdirAll(filepath.Join(validTmp, "mod@ver"), 0700|os.ModeDir)) + licenseScanner := licenses.TestingOnlyScanner() + tests := []struct { name string dir string @@ -299,7 +307,7 @@ func Test_noLocalGoModDir(t *testing.T) { SearchLocalModCacheLicenses: true, LocalModCacheDir: test.dir, }) - _, err := resolver.getLicensesFromLocal("mod", "ver") + _, err := resolver.getLicensesFromLocal(context.Background(), licenseScanner, "mod", "ver") test.wantErr(t, err) }) } diff --git a/syft/pkg/cataloger/golang/package.go b/syft/pkg/cataloger/golang/package.go index 8946b5f06..c3071420c 100644 --- a/syft/pkg/cataloger/golang/package.go +++ b/syft/pkg/cataloger/golang/package.go @@ -5,21 +5,15 @@ import ( "strings" "github.com/anchore/packageurl-go" - "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" ) -func (c *goBinaryCataloger) newGoBinaryPackage(resolver file.Resolver, dep *debug.Module, mainModule, goVersion, architecture string, buildSettings pkg.KeyValues, cryptoSettings, experiments []string, locations ...file.Location) pkg.Package { +func (c *goBinaryCataloger) newGoBinaryPackage(dep *debug.Module, mainModule, goVersion, architecture string, buildSettings pkg.KeyValues, cryptoSettings, experiments []string, licenses []pkg.License, locations ...file.Location) pkg.Package { if dep.Replace != nil { dep = dep.Replace } - licenses, err := c.licenseResolver.getLicenses(resolver, dep.Path, dep.Version) - if err != nil { - log.Tracef("error getting licenses for golang package: %s %v", dep.Path, err) - } - p := pkg.Package{ Name: dep.Path, Version: dep.Version, diff --git a/syft/pkg/cataloger/golang/parse_go_binary.go b/syft/pkg/cataloger/golang/parse_go_binary.go index 91957f19d..b0fe56a4e 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary.go +++ b/syft/pkg/cataloger/golang/parse_go_binary.go @@ -18,6 +18,7 @@ import ( "golang.org/x/mod/module" "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/licenses" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" @@ -59,9 +60,11 @@ func newGoBinaryCataloger(opts CatalogerConfig) *goBinaryCataloger { } // parseGoBinary catalogs packages found in the "buildinfo" section of a binary built by the go compiler. -func (c *goBinaryCataloger) parseGoBinary(_ context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { +func (c *goBinaryCataloger) parseGoBinary(ctx context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { var pkgs []pkg.Package + licenseScanner := licenses.ContextLicenseScanner(ctx) + unionReader, err := unionreader.GetUnionReader(reader.ReadCloser) if err != nil { return nil, nil, err @@ -73,7 +76,7 @@ func (c *goBinaryCataloger) parseGoBinary(_ context.Context, resolver file.Resol var rels []artifact.Relationship for _, mod := range mods { var depPkgs []pkg.Package - mainPkg, depPkgs := c.buildGoPkgInfo(resolver, reader.Location, mod, mod.arch, unionReader) + mainPkg, depPkgs := c.buildGoPkgInfo(ctx, licenseScanner, resolver, reader.Location, mod, mod.arch, unionReader) if mainPkg != nil { rels = createModuleRelationships(*mainPkg, depPkgs) pkgs = append(pkgs, *mainPkg) @@ -101,7 +104,7 @@ func createModuleRelationships(main pkg.Package, deps []pkg.Package) []artifact. var emptyModule debug.Module var moduleFromPartialPackageBuild = debug.Module{Path: "command-line-arguments"} -func (c *goBinaryCataloger) buildGoPkgInfo(resolver file.Resolver, location file.Location, mod *extendedBuildInfo, arch string, reader io.ReadSeekCloser) (*pkg.Package, []pkg.Package) { +func (c *goBinaryCataloger) buildGoPkgInfo(ctx context.Context, licenseScanner licenses.Scanner, resolver file.Resolver, location file.Location, mod *extendedBuildInfo, arch string, reader io.ReadSeekCloser) (*pkg.Package, []pkg.Package) { if mod == nil { return nil, nil } @@ -116,9 +119,13 @@ func (c *goBinaryCataloger) buildGoPkgInfo(resolver file.Resolver, location file continue } + lics, err := c.licenseResolver.getLicenses(ctx, licenseScanner, resolver, dep.Path, dep.Version) + if err != nil { + log.Tracef("error getting licenses for golang package: %s %v", dep.Path, err) + } + gover, experiments := getExperimentsFromVersion(mod.GoVersion) p := c.newGoBinaryPackage( - resolver, dep, mod.Main.Path, gover, @@ -126,6 +133,7 @@ func (c *goBinaryCataloger) buildGoPkgInfo(resolver file.Resolver, location file nil, mod.cryptoSettings, experiments, + lics, location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ) if pkg.IsValid(&p) { @@ -137,7 +145,7 @@ func (c *goBinaryCataloger) buildGoPkgInfo(resolver file.Resolver, location file return nil, pkgs } - main := c.makeGoMainPackage(resolver, mod, arch, location, reader) + main := c.makeGoMainPackage(ctx, licenseScanner, resolver, mod, arch, location, reader) return &main, pkgs } @@ -152,11 +160,16 @@ func missingMainModule(mod *extendedBuildInfo) bool { return mod.Main == moduleFromPartialPackageBuild } -func (c *goBinaryCataloger) makeGoMainPackage(resolver file.Resolver, mod *extendedBuildInfo, arch string, location file.Location, reader io.ReadSeekCloser) pkg.Package { +func (c *goBinaryCataloger) makeGoMainPackage(ctx context.Context, licenseScanner licenses.Scanner, resolver file.Resolver, mod *extendedBuildInfo, arch string, location file.Location, reader io.ReadSeekCloser) pkg.Package { gbs := getBuildSettings(mod.Settings) + + lics, err := c.licenseResolver.getLicenses(ctx, licenseScanner, resolver, mod.Main.Path, mod.Main.Version) + if err != nil { + log.Tracef("error getting licenses for golang package: %s %v", mod.Main.Path, err) + } + gover, experiments := getExperimentsFromVersion(mod.GoVersion) main := c.newGoBinaryPackage( - resolver, &mod.Main, mod.Main.Path, gover, @@ -164,6 +177,7 @@ func (c *goBinaryCataloger) makeGoMainPackage(resolver file.Resolver, mod *exten gbs, mod.cryptoSettings, experiments, + lics, location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ) diff --git a/syft/pkg/cataloger/golang/parse_go_binary_test.go b/syft/pkg/cataloger/golang/parse_go_binary_test.go index b2af3ffca..565fda090 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary_test.go +++ b/syft/pkg/cataloger/golang/parse_go_binary_test.go @@ -3,6 +3,7 @@ package golang import ( "bufio" "bytes" + "context" "errors" "io" "os" @@ -17,6 +18,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/anchore/syft/internal/licenses" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/internal/fileresolver" "github.com/anchore/syft/syft/internal/unionreader" @@ -167,6 +169,8 @@ func TestBuildGoPkgInfo(t *testing.T) { }, } + licenseScanner := licenses.TestingOnlyScanner() + tests := []struct { name string mod *extendedBuildInfo @@ -1053,7 +1057,7 @@ func TestBuildGoPkgInfo(t *testing.T) { c := newGoBinaryCataloger(DefaultCatalogerConfig()) reader, err := unionreader.GetUnionReader(io.NopCloser(strings.NewReader(test.binaryContent))) require.NoError(t, err) - mainPkg, pkgs := c.buildGoPkgInfo(fileresolver.Empty{}, location, test.mod, test.mod.arch, reader) + mainPkg, pkgs := c.buildGoPkgInfo(context.Background(), licenseScanner, fileresolver.Empty{}, location, test.mod, test.mod.arch, reader) if mainPkg != nil { pkgs = append(pkgs, *mainPkg) } diff --git a/syft/pkg/cataloger/golang/parse_go_mod.go b/syft/pkg/cataloger/golang/parse_go_mod.go index 8faf4acb5..cfb373e90 100644 --- a/syft/pkg/cataloger/golang/parse_go_mod.go +++ b/syft/pkg/cataloger/golang/parse_go_mod.go @@ -11,6 +11,7 @@ import ( "golang.org/x/mod/modfile" "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/licenses" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" @@ -31,9 +32,11 @@ func newGoModCataloger(opts CatalogerConfig) *goModCataloger { // parseGoModFile takes a go.mod and lists all packages discovered. // //nolint:funlen -func (c *goModCataloger) parseGoModFile(_ context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { +func (c *goModCataloger) parseGoModFile(ctx context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { packages := make(map[string]pkg.Package) + licenseScanner := licenses.ContextLicenseScanner(ctx) + contents, err := io.ReadAll(reader) if err != nil { return nil, nil, fmt.Errorf("failed to read go module: %w", err) @@ -50,7 +53,7 @@ func (c *goModCataloger) parseGoModFile(_ context.Context, resolver file.Resolve } for _, m := range f.Require { - licenses, err := c.licenseResolver.getLicenses(resolver, m.Mod.Path, m.Mod.Version) + lics, err := c.licenseResolver.getLicenses(ctx, licenseScanner, resolver, m.Mod.Path, m.Mod.Version) if err != nil { log.Tracef("error getting licenses for package: %s %v", m.Mod.Path, err) } @@ -58,7 +61,7 @@ func (c *goModCataloger) parseGoModFile(_ context.Context, resolver file.Resolve packages[m.Mod.Path] = pkg.Package{ Name: m.Mod.Path, Version: m.Mod.Version, - Licenses: pkg.NewLicenseSet(licenses...), + Licenses: pkg.NewLicenseSet(lics...), Locations: file.NewLocationSet(reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(m.Mod.Path, m.Mod.Version), Language: pkg.Go, @@ -71,7 +74,7 @@ func (c *goModCataloger) parseGoModFile(_ context.Context, resolver file.Resolve // remove any old packages and replace with new ones... for _, m := range f.Replace { - licenses, err := c.licenseResolver.getLicenses(resolver, m.New.Path, m.New.Version) + lics, err := c.licenseResolver.getLicenses(ctx, licenseScanner, resolver, m.New.Path, m.New.Version) if err != nil { log.Tracef("error getting licenses for package: %s %v", m.New.Path, err) } @@ -83,7 +86,7 @@ func (c *goModCataloger) parseGoModFile(_ context.Context, resolver file.Resolve packages[m.New.Path] = pkg.Package{ Name: m.New.Path, Version: m.New.Version, - Licenses: pkg.NewLicenseSet(licenses...), + Licenses: pkg.NewLicenseSet(lics...), Locations: file.NewLocationSet(reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(m.New.Path, m.New.Version), Language: pkg.Go, diff --git a/syft/pkg/cataloger/java/archive_parser.go b/syft/pkg/cataloger/java/archive_parser.go index dc5ff5f13..d084ac375 100644 --- a/syft/pkg/cataloger/java/archive_parser.go +++ b/syft/pkg/cataloger/java/archive_parser.go @@ -4,6 +4,7 @@ import ( "context" "crypto" "fmt" + "io" "os" "path" "slices" @@ -49,14 +50,15 @@ var javaArchiveHashes = []crypto.Hash{ } type archiveParser struct { - fileManifest intFile.ZipFileManifest - location file.Location - archivePath string - contentPath string - fileInfo archiveFilename - detectNested bool - cfg ArchiveCatalogerConfig - maven *mavenResolver + fileManifest intFile.ZipFileManifest + location file.Location + archivePath string + contentPath string + fileInfo archiveFilename + detectNested bool + cfg ArchiveCatalogerConfig + maven *mavenResolver + licenseScanner licenses.Scanner } type genericArchiveParserAdapter struct { @@ -69,7 +71,7 @@ func newGenericArchiveParserAdapter(cfg ArchiveCatalogerConfig) genericArchivePa // parseJavaArchive is a parser function for java archive contents, returning all Java libraries and nested archives. func (gap genericArchiveParserAdapter) parseJavaArchive(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { - parser, cleanupFn, err := newJavaArchiveParser(reader, true, gap.cfg) + parser, cleanupFn, err := newJavaArchiveParser(ctx, reader, true, gap.cfg) // note: even on error, we should always run cleanup functions defer cleanupFn() if err != nil { @@ -88,7 +90,9 @@ func uniquePkgKey(groupID string, p *pkg.Package) string { // newJavaArchiveParser returns a new java archive parser object for the given archive. Can be configured to discover // and parse nested archives or ignore them. -func newJavaArchiveParser(reader file.LocationReadCloser, detectNested bool, cfg ArchiveCatalogerConfig) (*archiveParser, func(), error) { +func newJavaArchiveParser(ctx context.Context, reader file.LocationReadCloser, detectNested bool, cfg ArchiveCatalogerConfig) (*archiveParser, func(), error) { + licenseScanner := licenses.ContextLicenseScanner(ctx) + // fetch the last element of the virtual path virtualElements := strings.Split(reader.Path(), ":") currentFilepath := virtualElements[len(virtualElements)-1] @@ -104,14 +108,15 @@ func newJavaArchiveParser(reader file.LocationReadCloser, detectNested bool, cfg } return &archiveParser{ - fileManifest: fileManifest, - location: reader.Location, - archivePath: archivePath, - contentPath: contentPath, - fileInfo: newJavaArchiveFilename(currentFilepath), - detectNested: detectNested, - cfg: cfg, - maven: newMavenResolver(nil, cfg), + fileManifest: fileManifest, + location: reader.Location, + archivePath: archivePath, + contentPath: contentPath, + fileInfo: newJavaArchiveFilename(currentFilepath), + detectNested: detectNested, + cfg: cfg, + maven: newMavenResolver(nil, cfg), + licenseScanner: licenseScanner, }, cleanupFn, nil } @@ -220,7 +225,7 @@ func (j *archiveParser) discoverMainPackage(ctx context.Context) (*pkg.Package, return nil, err } - name, version, licenses, err := j.discoverNameVersionLicense(ctx, manifest) + name, version, lics, err := j.discoverNameVersionLicense(ctx, manifest) if err != nil { return nil, err } @@ -230,7 +235,7 @@ func (j *archiveParser) discoverMainPackage(ctx context.Context) (*pkg.Package, Name: name, Version: version, Language: pkg.Java, - Licenses: pkg.NewLicenseSet(licenses...), + Licenses: pkg.NewLicenseSet(lics...), Locations: file.NewLocationSet( j.location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), @@ -246,7 +251,7 @@ func (j *archiveParser) discoverMainPackage(ctx context.Context) (*pkg.Package, func (j *archiveParser) discoverNameVersionLicense(ctx context.Context, manifest *pkg.JavaManifest) (string, string, []pkg.License, error) { // we use j.location because we want to associate the license declaration with where we discovered the contents in the manifest // TODO: when we support locations of paths within archives we should start passing the specific manifest location object instead of the top jar - licenses := pkg.NewLicensesFromLocation(j.location, selectLicenses(manifest)...) + lics := pkg.NewLicensesFromLocation(j.location, selectLicenses(manifest)...) /* We should name and version from, in this order: 1. pom.properties if we find exactly 1 @@ -262,25 +267,25 @@ func (j *archiveParser) discoverNameVersionLicense(ctx context.Context, manifest version = selectVersion(manifest, j.fileInfo) } - if len(licenses) == 0 { - fileLicenses, err := j.getLicenseFromFileInArchive() + if len(lics) == 0 { + fileLicenses, err := j.getLicenseFromFileInArchive(ctx) if err != nil { return "", "", nil, err } if fileLicenses != nil { - licenses = append(licenses, fileLicenses...) + lics = append(lics, fileLicenses...) } } // If we didn't find any licenses in the archive so far, we'll try again in Maven Central using groupIDFromJavaMetadata - if len(licenses) == 0 { + if len(lics) == 0 { // Today we don't have a way to distinguish between licenses from the manifest and licenses from the pom.xml // until the file.Location object can support sub-paths (i.e. paths within archives, recursively; issue https://github.com/anchore/syft/issues/2211). // Until then it's less confusing to use the licenses from the pom.xml only if the manifest did not list any. - licenses = j.findLicenseFromJavaMetadata(ctx, groupID, artifactID, version, parsedPom, manifest) + lics = j.findLicenseFromJavaMetadata(ctx, groupID, artifactID, version, parsedPom, manifest) } - return artifactID, version, licenses, nil + return artifactID, version, lics, nil } // findLicenseFromJavaMetadata attempts to find license information from all available maven metadata properties and pom info @@ -446,7 +451,7 @@ func getDigestsFromArchive(archivePath string) ([]file.Digest, error) { return digests, nil } -func (j *archiveParser) getLicenseFromFileInArchive() ([]pkg.License, error) { +func (j *archiveParser) getLicenseFromFileInArchive(ctx context.Context) ([]pkg.License, error) { var fileLicenses []pkg.License for _, filename := range licenses.FileNames() { licenseMatches := j.fileManifest.GlobMatch(true, "/META-INF/"+filename) @@ -463,7 +468,8 @@ func (j *archiveParser) getLicenseFromFileInArchive() ([]pkg.License, error) { for _, licenseMatch := range licenseMatches { licenseContents := contents[licenseMatch] - parsed, err := licenses.Parse(strings.NewReader(licenseContents), j.location) + r := strings.NewReader(licenseContents) + parsed, err := licenses.Search(ctx, j.licenseScanner, file.NewLocationReadCloser(j.location, io.NopCloser(r))) if err != nil { return nil, err } diff --git a/syft/pkg/cataloger/java/archive_parser_test.go b/syft/pkg/cataloger/java/archive_parser_test.go index 6fa0acc47..b0aad4faf 100644 --- a/syft/pkg/cataloger/java/archive_parser_test.go +++ b/syft/pkg/cataloger/java/archive_parser_test.go @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/vifraa/gopom" + "github.com/anchore/syft/internal/licenses" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/license" @@ -30,6 +31,8 @@ import ( func TestSearchMavenForLicenses(t *testing.T) { url := mockMavenRepo(t) + ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.TestingOnlyScanner()) + tests := []struct { name string fixture string @@ -71,6 +74,7 @@ func TestSearchMavenForLicenses(t *testing.T) { // setup parser ap, cleanupFn, err := newJavaArchiveParser( + ctx, file.LocationReadCloser{ Location: file.NewLocation(fixture.Name()), ReadCloser: fixture, @@ -86,6 +90,8 @@ func TestSearchMavenForLicenses(t *testing.T) { } func TestParseJar(t *testing.T) { + ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.TestingOnlyScanner()) + tests := []struct { name string fixture string @@ -347,10 +353,12 @@ func TestParseJar(t *testing.T) { UseNetwork: false, UseMavenLocalRepository: false, } - parser, cleanupFn, err := newJavaArchiveParser(file.LocationReadCloser{ - Location: file.NewLocation(fixture.Name()), - ReadCloser: fixture, - }, false, cfg) + parser, cleanupFn, err := newJavaArchiveParser( + ctx, + file.LocationReadCloser{ + Location: file.NewLocation(fixture.Name()), + ReadCloser: fixture, + }, false, cfg) defer cleanupFn() require.NoError(t, err) @@ -1352,6 +1360,8 @@ func Test_parseJavaArchive_regressions(t *testing.T) { } func Test_deterministicMatchingPomProperties(t *testing.T) { + ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.TestingOnlyScanner()) + tests := []struct { fixture string expected mavenID @@ -1371,10 +1381,12 @@ func Test_deterministicMatchingPomProperties(t *testing.T) { fixture, err := os.Open(fixturePath) require.NoError(t, err) - parser, cleanupFn, err := newJavaArchiveParser(file.LocationReadCloser{ - Location: file.NewLocation(fixture.Name()), - ReadCloser: fixture, - }, false, ArchiveCatalogerConfig{UseNetwork: false}) + parser, cleanupFn, err := newJavaArchiveParser( + ctx, + file.LocationReadCloser{ + Location: file.NewLocation(fixture.Name()), + ReadCloser: fixture, + }, false, ArchiveCatalogerConfig{UseNetwork: false}) defer cleanupFn() require.NoError(t, err) diff --git a/syft/pkg/cataloger/python/package.go b/syft/pkg/cataloger/python/package.go index e574d583a..e7c861256 100644 --- a/syft/pkg/cataloger/python/package.go +++ b/syft/pkg/cataloger/python/package.go @@ -1,6 +1,7 @@ package python import ( + "context" "fmt" "regexp" "strings" @@ -72,7 +73,26 @@ func newPackageForRequirementsWithMetadata(name, version string, metadata pkg.Py return p } -func newPackageForPackage(resolver file.Resolver, m parsedData, sources ...file.Location) pkg.Package { +func newPackageForPackage(m parsedData, licenses pkg.LicenseSet, 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, + } + + p.SetID() + + return p +} + +func findLicenses(ctx context.Context, scanner licenses.Scanner, resolver file.Resolver, m parsedData) pkg.LicenseSet { var licenseSet pkg.LicenseSet switch { @@ -89,7 +109,7 @@ func newPackageForPackage(resolver file.Resolver, m parsedData, sources ...file. if len(found) > 0 { metadataContents, err := resolver.FileContentsByLocation(found[0]) if err == nil { - parsed, err := licenses.Parse(metadataContents, m.LicenseLocation) + parsed, err := licenses.Search(ctx, scanner, file.NewLocationReadCloser(m.LicenseLocation, metadataContents)) if err != nil { log.WithFields("error", err).Tracef("unable to parse a license from the file in %s", m.LicenseLocation.Path()) } @@ -101,23 +121,7 @@ func newPackageForPackage(resolver file.Resolver, m parsedData, sources ...file. } } } - - name := normalize(m.Name) - - p := pkg.Package{ - Name: name, - Version: m.Version, - PURL: packageURL(name, m.Version, &m.PythonPackage), - Locations: file.NewLocationSet(sources...), - Licenses: licenseSet, - Language: pkg.Python, - Type: pkg.PythonPkg, - Metadata: m.PythonPackage, - } - - p.SetID() - - return p + return licenseSet } func packageURL(name, version string, m *pkg.PythonPackage) string { diff --git a/syft/pkg/cataloger/python/parse_wheel_egg.go b/syft/pkg/cataloger/python/parse_wheel_egg.go index 5fe8ad981..2d2b9487c 100644 --- a/syft/pkg/cataloger/python/parse_wheel_egg.go +++ b/syft/pkg/cataloger/python/parse_wheel_egg.go @@ -9,6 +9,7 @@ import ( "path/filepath" "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/licenses" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" @@ -18,7 +19,9 @@ import ( // parseWheelOrEgg takes the primary metadata file reference and returns the python package it represents. Contained // fields are governed by the PyPA core metadata specification (https://packaging.python.org/en/latest/specifications/core-metadata/). -func parseWheelOrEgg(_ context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { +func parseWheelOrEgg(ctx context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { + licenseScanner := licenses.ContextLicenseScanner(ctx) + pd, sources, err := assembleEggOrWheelMetadata(resolver, reader.Location) if err != nil { return nil, nil, err @@ -33,7 +36,13 @@ func parseWheelOrEgg(_ context.Context, resolver file.Resolver, _ *generic.Envir return nil, nil, nil } - pkgs := []pkg.Package{newPackageForPackage(resolver, *pd, sources...)} + pkgs := []pkg.Package{ + newPackageForPackage( + *pd, + findLicenses(ctx, licenseScanner, resolver, *pd), + sources..., + ), + } return pkgs, nil, nil } @@ -60,7 +69,7 @@ func fetchInstalledFiles(resolver file.Resolver, metadataLocation file.Location, // parse the installed-files contents installedFiles, err := parseInstalledFiles(installedFilesContents, metadataLocation.RealPath, sitePackagesRootPath) if err != nil { - log.Warnf("unable to parse installed-files.txt for python package=%+v: %w", metadataLocation.RealPath, err) + log.WithFields("error", err, "path", metadataLocation.RealPath).Trace("unable to parse installed-files.txt for python package") return files, sources, nil } From 2f2afe49aaf1c8806a26eb8a347244f072efed2a Mon Sep 17 00:00:00 2001 From: downstream-sync Date: Mon, 21 Oct 2024 20:14:52 +0000 Subject: [PATCH 281/284] Remove unwanted CI setup Signed-off-by: downstream-sync --- .github/ISSUE_TEMPLATE/bug_report.md | 20 -- .github/ISSUE_TEMPLATE/config.yml | 6 - .github/ISSUE_TEMPLATE/feature_request.md | 15 -- .github/actions/bootstrap/action.yaml | 66 ----- .github/dependabot.yml | 27 -- .github/pull_request_template.md | 25 -- .github/scripts/check_binary_fixture_size.sh | 36 --- .github/scripts/ci-check.sh | 11 - .github/scripts/coverage.py | 36 --- .github/scripts/find_cache_paths.py | 135 ---------- .../scripts/fingerprint_docker_fixtures.py | 70 ----- .github/scripts/go-mod-tidy-check.sh | 30 --- .github/scripts/json-schema-drift-check.sh | 17 -- .github/scripts/labeler.py | 249 ------------------ .github/scripts/labeler_test.py | 72 ----- .github/scripts/trigger-release.sh | 57 ---- .github/scripts/update-version-file.sh | 22 -- .github/workflows/benchmark-testing.yaml | 62 ----- .github/workflows/codeql-analysis.yml | 73 ----- .github/workflows/dependabot-automation.yaml | 10 - .github/workflows/detect-schema-changes.yaml | 54 ---- .github/workflows/oss-project-board-add.yaml | 18 -- .github/workflows/release-version-file.yaml | 31 --- .github/workflows/release.yaml | 171 ------------ .../remove-awaiting-response-label.yaml | 11 - .../workflows/test-fixture-cache-publish.yaml | 39 --- .github/workflows/update-bootstrap-tools.yml | 65 ----- .../workflows/update-cpe-dictionary-index.yml | 55 ---- .../workflows/update-stereoscope-release.yml | 57 ---- .github/workflows/validations.yaml | 223 ---------------- 30 files changed, 1763 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md delete mode 100644 .github/ISSUE_TEMPLATE/config.yml delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md delete mode 100644 .github/actions/bootstrap/action.yaml delete mode 100644 .github/dependabot.yml delete mode 100644 .github/pull_request_template.md delete mode 100755 .github/scripts/check_binary_fixture_size.sh delete mode 100755 .github/scripts/ci-check.sh delete mode 100755 .github/scripts/coverage.py delete mode 100755 .github/scripts/find_cache_paths.py delete mode 100755 .github/scripts/fingerprint_docker_fixtures.py delete mode 100755 .github/scripts/go-mod-tidy-check.sh delete mode 100755 .github/scripts/json-schema-drift-check.sh delete mode 100755 .github/scripts/labeler.py delete mode 100755 .github/scripts/labeler_test.py delete mode 100755 .github/scripts/trigger-release.sh delete mode 100755 .github/scripts/update-version-file.sh delete mode 100644 .github/workflows/benchmark-testing.yaml delete mode 100644 .github/workflows/codeql-analysis.yml delete mode 100644 .github/workflows/dependabot-automation.yaml delete mode 100644 .github/workflows/detect-schema-changes.yaml delete mode 100644 .github/workflows/oss-project-board-add.yaml delete mode 100644 .github/workflows/release-version-file.yaml delete mode 100644 .github/workflows/release.yaml delete mode 100644 .github/workflows/remove-awaiting-response-label.yaml delete mode 100644 .github/workflows/test-fixture-cache-publish.yaml delete mode 100644 .github/workflows/update-bootstrap-tools.yml delete mode 100644 .github/workflows/update-cpe-dictionary-index.yml delete mode 100644 .github/workflows/update-stereoscope-release.yml delete mode 100644 .github/workflows/validations.yaml diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 0a100afe4..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: bug -assignees: '' - ---- - -**What happened**: - -**What you expected to happen**: - -**Steps to reproduce the issue**: - -**Anything else we need to know?**: - -**Environment**: -- Output of `syft version`: -- OS (e.g: `cat /etc/os-release` or similar): diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index 3009b9c0c..000000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,6 +0,0 @@ -contact_links: - - - name: Join our Discourse community đŸ’Ŧ - # link to our community Discourse site - url: https://anchore.com/discourse - about: 'Come chat with us! Ask for help, join our software development efforts, or just give us feedback!' diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index d07c5f151..000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: enhancement -assignees: '' - ---- - -**What would you like to be added**: - -**Why is this needed**: - -**Additional context**: - diff --git a/.github/actions/bootstrap/action.yaml b/.github/actions/bootstrap/action.yaml deleted file mode 100644 index 6150113ae..000000000 --- a/.github/actions/bootstrap/action.yaml +++ /dev/null @@ -1,66 +0,0 @@ -name: "Bootstrap" - -description: "Bootstrap all tools and dependencies" -inputs: - go-version: - description: "Go version to install" - required: true - default: "1.22.x" - go-dependencies: - description: "Download go dependencies" - required: true - default: "true" - cache-key-prefix: - description: "Prefix all cache keys with this value" - required: true - default: "181053ac82" - download-test-fixture-cache: - description: "Download test fixture cache from OCI and github actions" - required: true - default: "false" - bootstrap-apt-packages: - description: "Space delimited list of tools to install via apt" - default: "libxml2-utils" - -runs: - using: "composite" - steps: - # note: go mod and build is automatically cached on default with v4+ - - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 - if: inputs.go-version != '' - with: - go-version: ${{ inputs.go-version }} - - - name: Restore tool cache - id: tool-cache - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 - with: - path: ${{ github.workspace }}/.tool - key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-tool-${{ hashFiles('.binny.yaml') }} - - - name: Install project tools - shell: bash - run: make tools - - - name: Install go dependencies - if: inputs.go-dependencies == 'true' - shell: bash - run: make ci-bootstrap-go - - - name: Install apt packages - if: inputs.bootstrap-apt-packages != '' - shell: bash - run: | - DEBIAN_FRONTEND=noninteractive sudo apt update && sudo -E apt install -y ${{ inputs.bootstrap-apt-packages }} - - - name: Restore ORAS cache from github actions - if: inputs.download-test-fixture-cache == 'true' - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 - with: - path: ${{ github.workspace }}/.tmp/oras-cache - key: ${{ inputs.cache-key-prefix }}-oras-cache - - - name: Download test fixture cache - if: inputs.download-test-fixture-cache == 'true' - shell: bash - run: make download-test-fixture-cache diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 0009183a7..000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,27 +0,0 @@ -version: 2 - -updates: - - - package-ecosystem: gomod - directory: "/" - schedule: - interval: "daily" - open-pull-requests-limit: 10 - labels: - - "dependencies" - - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "daily" - open-pull-requests-limit: 10 - labels: - - "dependencies" - - - package-ecosystem: "github-actions" - directory: "/.github/actions/boostrap" - schedule: - interval: "daily" - open-pull-requests-limit: 10 - labels: - - "dependencies" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index de2b78a66..000000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,25 +0,0 @@ -# Description - -Please include a summary of the changes along with any relevant motivation and context, -or link to an issue where this is explained. - - - -- Fixes # - -## Type of change - - - -- [ ] Bug fix (non-breaking change which fixes an issue) -- [ ] New feature (non-breaking change which adds functionality) -- [ ] Breaking change (please discuss with the team first; Syft is 1.0 software and we won't accept breaking changes without going to 2.0) -- [ ] Documentation (updates the documentation) -- [ ] Chore (improve the developer experience, fix a test flake, etc, without changing the visible behavior of Syft) -- [ ] Performance (make Syft run faster or use less memory, without changing visible behavior much) - -# Checklist: - -- [ ] I have added unit tests that cover changed behavior -- [ ] I have tested my code in common scenarios and confirmed there are no regressions -- [ ] I have added comments to my code, particularly in hard-to-understand sections diff --git a/.github/scripts/check_binary_fixture_size.sh b/.github/scripts/check_binary_fixture_size.sh deleted file mode 100755 index 764824820..000000000 --- a/.github/scripts/check_binary_fixture_size.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -# current limit for fixture size -size=1000 - -if [ $# -eq 0 ]; then - echo "Usage: $0 " - exit 1 -fi - -directory="$1" - -# Remove trailing slash using parameter expansion -directory="${directory%/}" - -if [ ! -d "$directory" ]; then - echo "Directory not found: $directory" - exit 1 -fi - -found_large_files=0 -while IFS= read -r -d '' file; do - if [ $(wc -c < "$file") -gt $size ]; then - echo "File $file is greater than ${size} bytes." - found_large_files=1 - fi -done < <(find "$directory" -type f -print0) - -if [ "$found_large_files" -eq 1 ]; then - echo "Script failed: Some files are greater than ${size} bytes." - exit 1 -else - echo "All files in $directory and its subdirectories are ${size} bytes or smaller. Check passed." - exit 0 -fi - diff --git a/.github/scripts/ci-check.sh b/.github/scripts/ci-check.sh deleted file mode 100755 index 0ab83a318..000000000 --- a/.github/scripts/ci-check.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -red=$(tput setaf 1) -bold=$(tput bold) -normal=$(tput sgr0) - -# assert we are running in CI (or die!) -if [[ -z "$CI" ]]; then - echo "${bold}${red}This step should ONLY be run in CI. Exiting...${normal}" - exit 1 -fi diff --git a/.github/scripts/coverage.py b/.github/scripts/coverage.py deleted file mode 100755 index db14135cd..000000000 --- a/.github/scripts/coverage.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python3 -import subprocess -import sys -import shlex - - -class bcolors: - HEADER = '\033[95m' - OKBLUE = '\033[94m' - OKCYAN = '\033[96m' - OKGREEN = '\033[92m' - WARNING = '\033[93m' - FAIL = '\033[91m' - ENDC = '\033[0m' - BOLD = '\033[1m' - UNDERLINE = '\033[4m' - - -if len(sys.argv) < 3: - print("Usage: coverage.py [threshold] [go-coverage-report]") - sys.exit(1) - - -threshold = float(sys.argv[1]) -report = sys.argv[2] - - -args = shlex.split(f"go tool cover -func {report}") -p = subprocess.run(args, capture_output=True, text=True) - -percent_coverage = float(p.stdout.splitlines()[-1].split()[-1].replace("%", "")) -print(f"{bcolors.BOLD}Coverage: {percent_coverage}%{bcolors.ENDC}") - -if percent_coverage < threshold: - print(f"{bcolors.BOLD}{bcolors.FAIL}Coverage below threshold of {threshold}%{bcolors.ENDC}") - sys.exit(1) diff --git a/.github/scripts/find_cache_paths.py b/.github/scripts/find_cache_paths.py deleted file mode 100755 index cc2e4081a..000000000 --- a/.github/scripts/find_cache_paths.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python3 -from __future__ import annotations - -import os -import glob -import sys -import json -import hashlib - - -IGNORED_PREFIXES = [] - - -def find_fingerprints_and_check_dirs(base_dir): - all_fingerprints = set(glob.glob(os.path.join(base_dir, '**', 'test*', '**', '*.fingerprint'), recursive=True)) - - all_fingerprints = {os.path.relpath(fp) for fp in all_fingerprints - if not any(fp.startswith(prefix) for prefix in IGNORED_PREFIXES)} - - if not all_fingerprints: - show("No .fingerprint files or cache directories found.") - exit(1) - - missing_content = [] - valid_paths = set() - fingerprint_contents = [] - - for fingerprint in all_fingerprints: - path = fingerprint.replace('.fingerprint', '') - - if not os.path.exists(path): - missing_content.append(path) - continue - - if not os.path.isdir(path): - valid_paths.add(path) - continue - - if os.listdir(path): - valid_paths.add(path) - else: - missing_content.append(path) - - with open(fingerprint, 'r') as f: - content = f.read().strip() - fingerprint_contents.append((fingerprint, content)) - - return sorted(valid_paths), missing_content, fingerprint_contents - - -def parse_fingerprint_contents(fingerprint_content): - input_map = {} - for line in fingerprint_content.splitlines(): - digest, path = line.split() - input_map[path] = digest - return input_map - - -def calculate_sha256(fingerprint_contents): - sorted_fingerprint_contents = sorted(fingerprint_contents, key=lambda x: x[0]) - - concatenated_contents = ''.join(content for _, content in sorted_fingerprint_contents) - - sha256_hash = hashlib.sha256(concatenated_contents.encode()).hexdigest() - - return sha256_hash - - -def calculate_file_sha256(file_path): - sha256_hash = hashlib.sha256() - with open(file_path, 'rb') as f: - for byte_block in iter(lambda: f.read(4096), b""): - sha256_hash.update(byte_block) - return sha256_hash.hexdigest() - - -def show(*s: str): - print(*s, file=sys.stderr) - - -def main(file_path: str | None): - base_dir = '.' - valid_paths, missing_content, fingerprint_contents = find_fingerprints_and_check_dirs(base_dir) - - if missing_content: - show("The following paths are missing or have no content, but have corresponding .fingerprint files:") - for path in sorted(missing_content): - show(f"- {path}") - show("Please ensure these paths exist and have content if they are directories.") - exit(1) - - sha256_hash = calculate_sha256(fingerprint_contents) - - paths_with_digests = [] - for path in sorted(valid_paths): - fingerprint_file = f"{path}.fingerprint" - try: - if os.path.exists(fingerprint_file): - file_digest = calculate_file_sha256(fingerprint_file) - - # Parse the fingerprint file to get the digest/path tuples - with open(fingerprint_file, 'r') as f: - fingerprint_content = f.read().strip() - input_map = parse_fingerprint_contents(fingerprint_content) - - paths_with_digests.append({ - "path": path, - "digest": file_digest, - "input": input_map - }) - - except Exception as e: - show(f"Error processing {fingerprint_file}: {e}") - raise e - - - output = { - "digest": sha256_hash, - "paths": paths_with_digests - } - - content = json.dumps(output, indent=2, sort_keys=True) - - if file_path: - with open(file_path, 'w') as f: - f.write(content) - - print(content) - - -if __name__ == "__main__": - file_path = None - if len(sys.argv) > 1: - file_path = sys.argv[1] - main(file_path) diff --git a/.github/scripts/fingerprint_docker_fixtures.py b/.github/scripts/fingerprint_docker_fixtures.py deleted file mode 100755 index 4a74420e0..000000000 --- a/.github/scripts/fingerprint_docker_fixtures.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python3 - -import os -import subprocess -import hashlib - -BOLD = '\033[1m' -YELLOW = '\033[0;33m' -RESET = '\033[0m' - - -def print_message(message): - print(f"{YELLOW}{message}{RESET}") - - -def sha256sum(filepath): - h = hashlib.sha256() - with open(filepath, 'rb') as f: - for chunk in iter(lambda: f.read(4096), b""): - h.update(chunk) - return h.hexdigest() - - -def is_git_tracked_or_untracked(directory): - """Returns a sorted list of files in the directory that are tracked or not ignored by Git.""" - result = subprocess.run( - ["git", "ls-files", "--cached", "--others", "--exclude-standard"], - cwd=directory, - stdout=subprocess.PIPE, - text=True - ) - return sorted(result.stdout.strip().splitlines()) - - -def find_test_fixture_dirs_with_images(base_dir): - """Find directories that contain 'test-fixtures' and at least one 'image-*' directory.""" - for root, dirs, files in os.walk(base_dir): - if 'test-fixtures' in root: - image_dirs = [d for d in dirs if d.startswith('image-')] - if image_dirs: - yield os.path.realpath(root) - - -def generate_fingerprints(): - print_message("creating fingerprint files for docker fixtures...") - - for test_fixture_dir in find_test_fixture_dirs_with_images('.'): - cache_fingerprint_path = os.path.join(test_fixture_dir, 'cache.fingerprint') - - with open(cache_fingerprint_path, 'w') as fingerprint_file: - for image_dir in find_image_dirs(test_fixture_dir): - for file in is_git_tracked_or_untracked(image_dir): - file_path = os.path.join(image_dir, file) - checksum = sha256sum(file_path) - path_from_fixture_dir = os.path.relpath(file_path, test_fixture_dir) - fingerprint_file.write(f"{checksum} {path_from_fixture_dir}\n") - - -def find_image_dirs(test_fixture_dir): - """Find all 'image-*' directories inside a given test-fixture directory.""" - result = [] - for root, dirs, files in os.walk(test_fixture_dir): - for dir_name in dirs: - if dir_name.startswith('image-'): - result.append(os.path.join(root, dir_name)) - return sorted(result) - - -if __name__ == "__main__": - generate_fingerprints() diff --git a/.github/scripts/go-mod-tidy-check.sh b/.github/scripts/go-mod-tidy-check.sh deleted file mode 100755 index 28f22fcdc..000000000 --- a/.github/scripts/go-mod-tidy-check.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash -set -eu - -ORIGINAL_STATE_DIR=$(mktemp -d "TEMP-original-state-XXXXXXXXX") -TIDY_STATE_DIR=$(mktemp -d "TEMP-tidy-state-XXXXXXXXX") - -trap "cp -p ${ORIGINAL_STATE_DIR}/* ./ && git update-index -q --refresh && rm -fR ${ORIGINAL_STATE_DIR} ${TIDY_STATE_DIR}" EXIT - -# capturing original state of files... -cp go.mod go.sum "${ORIGINAL_STATE_DIR}" - -# capturing state of go.mod and go.sum after running go mod tidy... -go mod tidy -cp go.mod go.sum "${TIDY_STATE_DIR}" - -set +e - -# detect difference between the git HEAD state and the go mod tidy state -DIFF_MOD=$(diff -u "${ORIGINAL_STATE_DIR}/go.mod" "${TIDY_STATE_DIR}/go.mod") -DIFF_SUM=$(diff -u "${ORIGINAL_STATE_DIR}/go.sum" "${TIDY_STATE_DIR}/go.sum") - -if [[ -n "${DIFF_MOD}" || -n "${DIFF_SUM}" ]]; then - echo "go.mod diff:" - echo "${DIFF_MOD}" - echo "go.sum diff:" - echo "${DIFF_SUM}" - echo "" - printf "FAILED! go.mod and/or go.sum are NOT tidy; please run 'go mod tidy'.\n\n" - exit 1 -fi diff --git a/.github/scripts/json-schema-drift-check.sh b/.github/scripts/json-schema-drift-check.sh deleted file mode 100755 index 3002236d6..000000000 --- a/.github/scripts/json-schema-drift-check.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash -set -u - -if [ "$(git status --porcelain | wc -l)" -ne "0" ]; then - echo " 🔴 there are uncommitted changes, please commit them before running this check" - exit 1 -fi - -if ! make generate-json-schema; then - echo "Generating json schema failed" - exit 1 -fi - -if [ "$(git status --porcelain | wc -l)" -ne "0" ]; then - echo " 🔴 there are uncommitted changes, please commit them before running this check" - exit 1 -fi diff --git a/.github/scripts/labeler.py b/.github/scripts/labeler.py deleted file mode 100755 index 2efd33206..000000000 --- a/.github/scripts/labeler.py +++ /dev/null @@ -1,249 +0,0 @@ -#!/usr/bin/env python3 - -from __future__ import annotations - -import sys -import glob -import subprocess -import os -import re - -DRY_RUN = False - -JSON_SCHEMA_LABEL = "json-schema" - -# note: we can't use "breaking-change" as the label since that might be applied manually by a user. This is a -# distinct label that we can use to indicate that the label was applied (or removed) by automation. -BREAKING_CHANGE_LABEL = "detected-breaking-change" - - -def main(changed_files: str | None = None, merge_base_schema_files: str | None = None): - global DRY_RUN - - pr_number = os.environ.get("GITHUB_PR_NUMBER") - comment_file_path = os.environ.get("CI_COMMENT_FILE") - - if not comment_file_path: - print("CI_COMMENT_FILE not set") - sys.exit(1) - - if not pr_number: - DRY_RUN = True - - if changed_files: - DRY_RUN = True - - # read lines from file... this is useful for local testing - with open(changed_files) as f: - pr_changed_files = f.read().splitlines() - - with open(merge_base_schema_files) as f: - og_json_schema_files = sort_json_schema_files(f.read().splitlines()) - - else: - if not is_ci(): - print("Not in CI") - sys.exit(1) - - if not pr_number: - print("Not a PR") - sys.exit(1) - - pr_changed_files = get_pr_changed_files(pr_number) - # since we are running this in the context of the pull_request_target, the checkout is the merge base.. - # that is the main branch of the original repo, NOT the branch in the forked repo (or branch in the target - # repo for non-forked PRs). This means we just need to list the current checkedout files to get a sense of - # the changes before a merge. - og_json_schema_files = list_json_schema_files() - - pr_json_schema_files = filter_to_schema_files(pr_changed_files) - - pr_labels = get_pr_labels(pr_number) - - # print("schema files in pr: ", summarize_schema_files(pr_json_schema_files)) - # print("og schema files: ", summarize_schema_files(og_json_schema_files)) - - if not og_json_schema_files: - print("No schema files found in merge base") - sys.exit(1) - - # pr_json_schema_files = set of PR files are added, removed, and changed files - new_schema_files = set(pr_json_schema_files) - set(og_json_schema_files) - removed_or_modified_schema_files = set(pr_json_schema_files) - set(new_schema_files) - - print("new schemas: ", summarize_schema_files(new_schema_files)) - print("removed or modified schemas:", summarize_schema_files(removed_or_modified_schema_files)) - - # if there is a new or modified schema, we should add the "json-schema" label to the PR... - if new_schema_files or removed_or_modified_schema_files: - print("\nAdding json-schema label...") - add_label(pr_number, JSON_SCHEMA_LABEL) - - else: - if JSON_SCHEMA_LABEL in pr_labels: - remove_label(pr_number, JSON_SCHEMA_LABEL) - - # new schema files should be scrutinized, comparing the latest and added versions to see if it's a breaking - # change (major version bump). Warn about it on the PR via adding a breaking-change label... - if is_breaking_change(new_schema_files, og_json_schema_files[-1]): - print("\nBreaking change detected...") - add_label(pr_number, BREAKING_CHANGE_LABEL) - else: - if BREAKING_CHANGE_LABEL in pr_labels: - remove_label(pr_number, BREAKING_CHANGE_LABEL) - - # modifying an existing schema could be a breaking change, we should warn about it on the PR via a comment... - # removing schema files should never be allowed, we should warn about it on the PR via a comment... - if removed_or_modified_schema_files: - print("\nRemoved or modified schema detected...") - schemas = sort_json_schema_files(list(removed_or_modified_schema_files)) - schemas_str = "\n".join([f" - {schema}" for schema in schemas]) - add_comment(comment_file_path, f"Detected modification or removal of existing json schemas:\n{schemas_str}", warning=True) - - -def add_comment(comment_file_path: str, comment: str, warning: bool = False, important: bool = False): - if warning or important: - comment_lines = comment.splitlines() - comment = "\n".join([f"> {line}" for line in comment_lines]) - - if warning: - comment = f"> [!WARNING]\n{comment}" - elif important: - comment = f"> [!IMPORTANT]\n{comment}" - - # create any parent directories if they don't exist - os.makedirs(os.path.dirname(comment_file_path), exist_ok=True) - - with open(comment_file_path, "w") as f: - f.write(comment) - - print(f"Comment file contents: {comment_file_path}") - print(comment) - - -def add_label(pr_number: str, label: str): - # run "gh pr edit --add-label