Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package syft for openSUSE:Factory checked in at 2023-02-17 16:44:09 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/syft (Old) and /work/SRC/openSUSE:Factory/.syft.new.22824 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "syft" Fri Feb 17 16:44:09 2023 rev:28 rq:1066250 version:0.72.0 Changes: -------- --- /work/SRC/openSUSE:Factory/syft/syft.changes 2023-02-10 14:35:45.598078148 +0100 +++ /work/SRC/openSUSE:Factory/.syft.new.22824/syft.changes 2023-02-17 16:44:16.558616292 +0100 @@ -1,0 +2,13 @@ +Thu Feb 16 17:31:12 UTC 2023 - ka...@b1-systems.de + +- Update to version 0.72.0: + * Update Stereoscope to 4b5ebf8c7f4b81ca79c4c3f0af1d0723eab87d42 (#1576) + * chore(deps): bump golang.org/x/net from 0.6.0 to 0.7.0 (#1574) + * chore: update bug issue template (#1571) + * allow convert to take stdin (#1570) + * fix: improve CPE and upstream generation logic for Alpine packages (#1567) + * fix: missing APK node vulnerabilities (#1565) + * fix: python CPE generation for alpine (#1564) + * chore(deps): bump github.com/docker/docker (#1563) + +------------------------------------------------------------------- Old: ---- syft-0.71.0.tar.gz New: ---- syft-0.72.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ syft.spec ++++++ --- /var/tmp/diff_new_pack.D8c88P/_old 2023-02-17 16:44:18.222625662 +0100 +++ /var/tmp/diff_new_pack.D8c88P/_new 2023-02-17 16:44:18.226625686 +0100 @@ -19,7 +19,7 @@ %define __arch_install_post export NO_BRP_STRIP_DEBUG=true Name: syft -Version: 0.71.0 +Version: 0.72.0 Release: 0 Summary: CLI tool and library for generating a Software Bill of Materials License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.D8c88P/_old 2023-02-17 16:44:18.262625888 +0100 +++ /var/tmp/diff_new_pack.D8c88P/_new 2023-02-17 16:44:18.266625911 +0100 @@ -3,7 +3,7 @@ <param name="url">https://github.com/anchore/syft</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">v0.71.0</param> + <param name="revision">v0.72.0</param> <param name="versionformat">@PARENT_TAG@</param> <param name="changesgenerate">enable</param> <param name="versionrewrite-pattern">v(.*)</param> @@ -16,7 +16,7 @@ <param name="compression">gz</param> </service> <service name="go_modules" mode="disabled"> - <param name="archive">syft-0.71.0.tar.gz</param> + <param name="archive">syft-0.72.0.tar.gz</param> </service> </services> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.D8c88P/_old 2023-02-17 16:44:18.286626023 +0100 +++ /var/tmp/diff_new_pack.D8c88P/_new 2023-02-17 16:44:18.290626046 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/anchore/syft</param> - <param name="changesrevision">88c81d33edc67b0b9636d0046417a9373ac8b74f</param></service></servicedata> + <param name="changesrevision">2642a3616170ccbda9d8c8cb4f4a6b0fd5c63da9</param></service></servicedata> (No newline at EOF) ++++++ syft-0.71.0.tar.gz -> syft-0.72.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.71.0/.github/ISSUE_TEMPLATE/bug_report.md new/syft-0.72.0/.github/ISSUE_TEMPLATE/bug_report.md --- old/syft-0.71.0/.github/ISSUE_TEMPLATE/bug_report.md 2023-02-09 17:35:11.000000000 +0100 +++ new/syft-0.72.0/.github/ISSUE_TEMPLATE/bug_report.md 2023-02-16 16:22:43.000000000 +0100 @@ -7,12 +7,12 @@ --- -**Please provide a set of steps on how to reproduce the issue** - **What happened**: **What you expected to happen**: +**Steps to reproduce the issue**: + **Anything else we need to know?**: **Environment**: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.71.0/cmd/syft/cli/convert/convert.go new/syft-0.72.0/cmd/syft/cli/convert/convert.go --- old/syft-0.71.0/cmd/syft/cli/convert/convert.go 2023-02-09 17:35:11.000000000 +0100 +++ new/syft-0.72.0/cmd/syft/cli/convert/convert.go 2023-02-16 16:22:43.000000000 +0100 @@ -3,6 +3,7 @@ import ( "context" "fmt" + "io" "os" "github.com/anchore/syft/cmd/syft/cli/options" @@ -26,15 +27,23 @@ // this can only be a SBOM file userInput := args[0] - f, err := os.Open(userInput) - if err != nil { - return fmt.Errorf("failed to open SBOM file: %w", err) + + var reader io.ReadCloser + + if userInput == "-" { + reader = os.Stdin + } else { + f, err := os.Open(userInput) + if err != nil { + return fmt.Errorf("failed to open SBOM file: %w", err) + } + defer func() { + _ = f.Close() + }() + reader = f } - defer func() { - _ = f.Close() - }() - sbom, _, err := formats.Decode(f) + sbom, _, err := formats.Decode(reader) if err != nil { return fmt.Errorf("failed to decode SBOM: %w", err) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.71.0/cmd/syft/cli/convert.go new/syft-0.72.0/cmd/syft/cli/convert.go --- old/syft-0.71.0/cmd/syft/cli/convert.go 2023-02-09 17:35:11.000000000 +0100 +++ new/syft-0.72.0/cmd/syft/cli/convert.go 2023-02-16 16:22:43.000000000 +0100 @@ -14,8 +14,9 @@ ) const ( - convertExample = ` {{.appName}} {{.command}} img.syft.json -o spdx-json convert a syft SBOM to spdx-json, output goes to stdout in table format, by default - {{.appName}} {{.command}} img.syft.json -o cyclonedx-json=img.cdx.json convert a syft SBOM to CycloneDX, output goes to a file named img.cdx.json + convertExample = ` {{.appName}} {{.command}} img.syft.json -o spdx-json convert a syft SBOM to spdx-json, output goes to stdout + {{.appName}} {{.command}} img.syft.json -o cyclonedx-json=img.cdx.json convert a syft SBOM to CycloneDX, output is written to the file "img.cdx.json"" + {{.appName}} {{.command}} - -o spdx-json convert an SBOM from STDIN to spdx-json ` ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.71.0/go.mod new/syft-0.72.0/go.mod --- old/syft-0.71.0/go.mod 2023-02-09 17:35:11.000000000 +0100 +++ new/syft-0.72.0/go.mod 2023-02-16 16:22:43.000000000 +0100 @@ -43,7 +43,7 @@ github.com/wagoodman/jotframe v0.0.0-20211129225309-56b0d0a4aebb github.com/xeipuuv/gojsonschema v1.2.0 golang.org/x/mod v0.8.0 - golang.org/x/net v0.6.0 + golang.org/x/net v0.7.0 golang.org/x/term v0.5.0 gopkg.in/yaml.v2 v2.4.0 ) @@ -52,8 +52,8 @@ github.com/CycloneDX/cyclonedx-go v0.7.1-0.20221222100750-41a1ac565cce github.com/Masterminds/sprig/v3 v3.2.3 github.com/anchore/go-logger v0.0.0-20220728155337-03b66a5207d8 - github.com/anchore/stereoscope v0.0.0-20230208154630-5a306f07f2e7 - github.com/docker/docker v23.0.0+incompatible + github.com/anchore/stereoscope v0.0.0-20230216143338-4b5ebf8c7f4b + github.com/docker/docker v23.0.1+incompatible github.com/google/go-containerregistry v0.13.0 github.com/invopop/jsonschema v0.7.0 github.com/knqyf263/go-rpmdb v0.0.0-20221030135625-4082a22221ce @@ -71,7 +71,7 @@ github.com/Microsoft/go-winio v0.6.0 // indirect github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect github.com/becheran/wildmatch-go v1.0.0 // indirect - github.com/containerd/containerd v1.6.12 // indirect + github.com/containerd/containerd v1.6.18 // indirect github.com/containerd/stargz-snapshotter/estargz v0.12.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/cli v20.10.20+incompatible // indirect diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.71.0/go.sum new/syft-0.72.0/go.sum --- old/syft-0.71.0/go.sum 2023-02-09 17:35:11.000000000 +0100 +++ new/syft-0.72.0/go.sum 2023-02-16 16:22:43.000000000 +0100 @@ -90,8 +90,8 @@ 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.20230104203445-02e0a6721501 h1:AV7qjwMcM4r8wFhJq3jLRztew3ywIyPTRapl2T1s9o8= github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.0-20230208154630-5a306f07f2e7 h1:PrdFBPMyika+AM1/AwDmYqrVeUATDU90wbrd81ugicU= -github.com/anchore/stereoscope v0.0.0-20230208154630-5a306f07f2e7/go.mod h1:TUCfo52tEz7ahTUFtKN//wcB7kJzQs0Oifmnd4NkIXw= +github.com/anchore/stereoscope v0.0.0-20230216143338-4b5ebf8c7f4b h1:vMEAfz91QLjJq2W8JPxpIC4dG4OeynTY4MisHnZ19F0= +github.com/anchore/stereoscope v0.0.0-20230216143338-4b5ebf8c7f4b/go.mod h1:6oSG43mzahqiktzXZDctqi1o66fwU2wDk3xki0KlnbA= 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= @@ -132,8 +132,8 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/containerd/containerd v1.6.12 h1:kJ9b3mOFKf8yqo05Ob+tMoxvt1pbVWhnB0re9Y+k+8c= -github.com/containerd/containerd v1.6.12/go.mod h1:K4Bw7gjgh4TnkmQY+py/PYQGp4e7xgnHAeg87VeWb3A= +github.com/containerd/containerd v1.6.18 h1:qZbsLvmyu+Vlty0/Ex5xc0z2YtKpIsb5n45mAMI+2Ns= +github.com/containerd/containerd v1.6.18/go.mod h1:1RdCUu95+gc2v9t3IL+zIlpClSmew7/0YS8O5eQZrOw= github.com/containerd/stargz-snapshotter/estargz v0.12.1 h1:+7nYmHJb0tEkcRaAW+MHqoKaJYZmkikupxCqVtmPuY0= github.com/containerd/stargz-snapshotter/estargz v0.12.1/go.mod h1:12VUuCq3qPq4y8yUW+l5w3+oXV3cx2Po3KSe/SmPGqw= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -150,8 +150,8 @@ github.com/docker/cli v20.10.20+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v23.0.0+incompatible h1:L6c28tNyqZ4/ub9AZC9d5QUuunoHHfEH4/Ue+h/E5nE= -github.com/docker/docker v23.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v23.0.1+incompatible h1:vjgvJZxprTTE1A37nm+CLNAdwu6xZekyoiVlUZEINcY= +github.com/docker/docker v23.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= @@ -716,8 +716,8 @@ golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 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= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.71.0/syft/pkg/cataloger/apkdb/package.go new/syft-0.72.0/syft/pkg/cataloger/apkdb/package.go --- old/syft-0.71.0/syft/pkg/cataloger/apkdb/package.go 2023-02-09 17:35:11.000000000 +0100 +++ new/syft-0.72.0/syft/pkg/cataloger/apkdb/package.go 2023-02-16 16:22:43.000000000 +0100 @@ -9,6 +9,10 @@ "github.com/anchore/syft/syft/source" ) +var ( + prefixes = []string{"py-", "py2-", "py3-", "ruby-"} +) + func newPackage(d pkg.ApkMetadata, release *linux.Release, locations ...source.Location) pkg.Package { p := pkg.Package{ Name: d.Package, @@ -26,6 +30,20 @@ return p } +func generateUpstream(m pkg.ApkMetadata) string { + if m.OriginPackage != "" && m.OriginPackage != m.Package { + return m.OriginPackage + } + + for _, p := range prefixes { + if strings.HasPrefix(m.Package, p) { + return strings.TrimPrefix(m.Package, p) + } + } + + return m.Package +} + // packageURL returns the PURL for the specific Alpine package (see https://github.com/package-url/purl-spec) func packageURL(m pkg.ApkMetadata, distro *linux.Release) string { if distro == nil || distro.ID != "alpine" { @@ -38,7 +56,7 @@ } if m.OriginPackage != "" { - qualifiers[pkg.PURLQualifierUpstream] = m.OriginPackage + qualifiers[pkg.PURLQualifierUpstream] = generateUpstream(m) } return packageurl.NewPackageURL( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.71.0/syft/pkg/cataloger/apkdb/package_test.go new/syft-0.72.0/syft/pkg/cataloger/apkdb/package_test.go --- old/syft-0.71.0/syft/pkg/cataloger/apkdb/package_test.go 2023-02-09 17:35:11.000000000 +0100 +++ new/syft-0.72.0/syft/pkg/cataloger/apkdb/package_test.go 2023-02-16 16:22:43.000000000 +0100 @@ -96,6 +96,34 @@ }, expected: "pkg:apk/alpine/p@v?arch=a&upstream=origin&distro=alpine-3.4.6", }, + { + name: "upstream python package information as qualifier", + metadata: pkg.ApkMetadata{ + Package: "py3-potatoes", + Version: "v", + Architecture: "a", + OriginPackage: "py3-potatoes", + }, + distro: linux.Release{ + ID: "alpine", + VersionID: "3.4.6", + }, + expected: "pkg:apk/alpine/py3-potatoes@v?arch=a&upstream=potatoes&distro=alpine-3.4.6", + }, + { + name: "python package with origin package as upstream", + metadata: pkg.ApkMetadata{ + Package: "py3-non-existant", + Version: "v", + Architecture: "a", + OriginPackage: "abcdefg", + }, + distro: linux.Release{ + ID: "alpine", + VersionID: "3.4.6", + }, + expected: "pkg:apk/alpine/py3-non-existant@v?arch=a&upstream=abcdefg&distro=alpine-3.4.6", + }, } for _, test := range tests { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.71.0/syft/pkg/cataloger/common/cpe/apk.go new/syft-0.72.0/syft/pkg/cataloger/common/cpe/apk.go --- old/syft-0.71.0/syft/pkg/cataloger/common/cpe/apk.go 1970-01-01 01:00:00.000000000 +0100 +++ new/syft-0.72.0/syft/pkg/cataloger/common/cpe/apk.go 2023-02-16 16:22:43.000000000 +0100 @@ -0,0 +1,173 @@ +package cpe + +import ( + "strings" + + "github.com/anchore/syft/syft/pkg" +) + +var ( + pythonPrefixes = []string{"py-", "py2-", "py3-"} + rubyPrefixes = []string{"ruby-"} +) + +func pythonCandidateVendorsFromName(v string) fieldCandidateSet { + vendors := newFieldCandidateSet() + vendors.add(fieldCandidate{ + value: v, + disallowSubSelections: true, + disallowDelimiterVariations: true, + }) + + vendors.addValue(findAdditionalVendors(defaultCandidateAdditions, pkg.PythonPkg, v, v)...) + vendors.removeByValue(findVendorsToRemove(defaultCandidateRemovals, pkg.PythonPkg, v)...) + + for _, av := range additionalVendorsForPython(v) { + vendors.add(fieldCandidate{ + value: av, + disallowSubSelections: true, + disallowDelimiterVariations: true, + }) + vendors.addValue(findAdditionalVendors(defaultCandidateAdditions, pkg.PythonPkg, av, av)...) + vendors.removeByValue(findVendorsToRemove(defaultCandidateRemovals, pkg.PythonPkg, av)...) + } + + return vendors +} + +func pythonCandidateVendorsFromAPK(m pkg.ApkMetadata) fieldCandidateSet { + vendors := newFieldCandidateSet() + + for _, p := range pythonPrefixes { + if strings.HasPrefix(m.Package, p) { + t := strings.ToLower(strings.TrimPrefix(m.Package, p)) + vendors.union(pythonCandidateVendorsFromName(t)) + } + + if m.OriginPackage != m.Package && strings.HasPrefix(m.OriginPackage, p) { + t := strings.ToLower(strings.TrimPrefix(m.OriginPackage, p)) + vendors.union(pythonCandidateVendorsFromName(t)) + } + } + + return vendors +} + +func pythonCandidateProductsFromName(p string) fieldCandidateSet { + products := newFieldCandidateSet() + products.add(fieldCandidate{ + value: p, + disallowSubSelections: true, + disallowDelimiterVariations: true, + }) + + products.addValue(findAdditionalProducts(defaultCandidateAdditions, pkg.PythonPkg, p)...) + products.removeByValue(findProductsToRemove(defaultCandidateRemovals, pkg.PythonPkg, p)...) + return products +} + +func pythonCandidateProductsFromAPK(m pkg.ApkMetadata) fieldCandidateSet { + products := newFieldCandidateSet() + + for _, p := range pythonPrefixes { + if strings.HasPrefix(m.Package, p) { + t := strings.ToLower(strings.TrimPrefix(m.Package, p)) + products.union(pythonCandidateProductsFromName(t)) + } + + if m.OriginPackage != m.Package && strings.HasPrefix(m.OriginPackage, p) { + t := strings.ToLower(strings.TrimPrefix(m.OriginPackage, p)) + products.union(pythonCandidateProductsFromName(t)) + } + } + + return products +} + +func rubyCandidateVendorsFromName(v string) fieldCandidateSet { + vendors := newFieldCandidateSet() + vendors.add(fieldCandidate{ + value: v, + disallowSubSelections: true, + disallowDelimiterVariations: true, + }) + + vendors.addValue(findAdditionalVendors(defaultCandidateAdditions, pkg.GemPkg, v, v)...) + vendors.removeByValue(findVendorsToRemove(defaultCandidateRemovals, pkg.GemPkg, v)...) + return vendors +} + +func rubyCandidateVendorsFromAPK(m pkg.ApkMetadata) fieldCandidateSet { + vendors := newFieldCandidateSet() + + for _, p := range rubyPrefixes { + if strings.HasPrefix(m.Package, p) { + t := strings.ToLower(strings.TrimPrefix(m.Package, p)) + vendors.union(rubyCandidateVendorsFromName(t)) + } + + if m.OriginPackage != m.Package && strings.HasPrefix(m.OriginPackage, p) { + t := strings.ToLower(strings.TrimPrefix(m.OriginPackage, p)) + vendors.union(rubyCandidateVendorsFromName(t)) + } + } + + return vendors +} + +func rubyCandidateProductsFromName(p string) fieldCandidateSet { + products := newFieldCandidateSet() + products.add(fieldCandidate{ + value: p, + disallowSubSelections: true, + disallowDelimiterVariations: true, + }) + + products.addValue(findAdditionalProducts(defaultCandidateAdditions, pkg.GemPkg, p)...) + products.removeByValue(findProductsToRemove(defaultCandidateRemovals, pkg.GemPkg, p)...) + return products +} + +func rubyCandidateProductsFromAPK(m pkg.ApkMetadata) fieldCandidateSet { + products := newFieldCandidateSet() + + for _, p := range rubyPrefixes { + if strings.HasPrefix(m.Package, p) { + t := strings.ToLower(strings.TrimPrefix(m.Package, p)) + products.union(rubyCandidateProductsFromName(t)) + } + + if m.OriginPackage != m.Package && strings.HasPrefix(m.OriginPackage, p) { + t := strings.ToLower(strings.TrimPrefix(m.OriginPackage, p)) + products.union(rubyCandidateProductsFromName(t)) + } + } + + return products +} + +func candidateVendorsForAPK(p pkg.Package) fieldCandidateSet { + metadata, ok := p.Metadata.(pkg.ApkMetadata) + if !ok { + return nil + } + + vendors := newFieldCandidateSet() + vendors.union(pythonCandidateVendorsFromAPK(metadata)) + vendors.union(rubyCandidateVendorsFromAPK(metadata)) + + return vendors +} + +func candidateProductsForAPK(p pkg.Package) fieldCandidateSet { + metadata, ok := p.Metadata.(pkg.ApkMetadata) + if !ok { + return nil + } + + products := newFieldCandidateSet() + products.union(pythonCandidateProductsFromAPK(metadata)) + products.union(rubyCandidateProductsFromAPK(metadata)) + + return products +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.71.0/syft/pkg/cataloger/common/cpe/apk_test.go new/syft-0.72.0/syft/pkg/cataloger/common/cpe/apk_test.go --- old/syft-0.71.0/syft/pkg/cataloger/common/cpe/apk_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/syft-0.72.0/syft/pkg/cataloger/common/cpe/apk_test.go 2023-02-16 16:22:43.000000000 +0100 @@ -0,0 +1,91 @@ +package cpe + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/anchore/syft/syft/pkg" +) + +func Test_candidateVendorsForAPK(t *testing.T) { + tests := []struct { + name string + pkg pkg.Package + expected []string + }{ + { + name: "py3-cryptography Package", + pkg: pkg.Package{ + Metadata: pkg.ApkMetadata{ + Package: "py3-cryptography", + }, + }, + expected: []string{"python-cryptography_project", "cryptography", "cryptographyproject", "cryptography_project"}, + }, + { + name: "py2-pypdf OriginPackage", + pkg: pkg.Package{ + Metadata: pkg.ApkMetadata{ + OriginPackage: "py2-pypdf", + }, + }, + expected: []string{"pypdf", "pypdfproject", "pypdf_project"}, + }, + { + name: "ruby-armadillo Package", + pkg: pkg.Package{ + Metadata: pkg.ApkMetadata{ + Package: "ruby-armadillo", + }, + }, + expected: []string{"armadillo"}, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + assert.ElementsMatch(t, test.expected, candidateVendorsForAPK(test.pkg).values(), "different vendors") + }) + } +} + +func Test_candidateProductsForAPK(t *testing.T) { + tests := []struct { + name string + pkg pkg.Package + expected []string + }{ + { + name: "py3-cryptography Package", + pkg: pkg.Package{ + Metadata: pkg.ApkMetadata{ + Package: "py3-cryptography", + }, + }, + expected: []string{"cryptography", "python-cryptography"}, + }, + { + name: "py2-pypdf OriginPackage", + pkg: pkg.Package{ + Metadata: pkg.ApkMetadata{ + OriginPackage: "py2-pypdf", + }, + }, + expected: []string{"pypdf"}, + }, + { + name: "ruby-armadillo Package", + pkg: pkg.Package{ + Metadata: pkg.ApkMetadata{ + Package: "ruby-armadillo", + }, + }, + expected: []string{"armadillo"}, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + assert.ElementsMatch(t, test.expected, candidateProductsForAPK(test.pkg).values(), "different products") + }) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.71.0/syft/pkg/cataloger/common/cpe/candidate_by_package_type.go new/syft-0.72.0/syft/pkg/cataloger/common/cpe/candidate_by_package_type.go --- old/syft-0.71.0/syft/pkg/cataloger/common/cpe/candidate_by_package_type.go 2023-02-09 17:35:11.000000000 +0100 +++ new/syft-0.72.0/syft/pkg/cataloger/common/cpe/candidate_by_package_type.go 2023-02-16 16:22:43.000000000 +0100 @@ -121,12 +121,89 @@ candidateKey{PkgName: "yajl-ruby"}, candidateAddition{AdditionalProducts: []string{"yajl-ruby_gem"}}, }, + { + pkg.GemPkg, + candidateKey{PkgName: "cgi"}, + candidateAddition{AdditionalVendors: []string{"ruby-lang"}}, + }, + { + pkg.GemPkg, + candidateKey{PkgName: "date"}, + candidateAddition{AdditionalVendors: []string{"ruby-lang"}}, + }, + { + pkg.GemPkg, + candidateKey{PkgName: "openssl"}, + candidateAddition{AdditionalVendors: []string{"ruby-lang"}}, + }, + { + pkg.GemPkg, + candidateKey{PkgName: "rake"}, + candidateAddition{AdditionalVendors: []string{"ruby-lang"}}, + }, + { + pkg.GemPkg, + candidateKey{PkgName: "rdoc"}, + candidateAddition{AdditionalVendors: []string{"ruby-lang"}}, + }, + { + pkg.GemPkg, + candidateKey{PkgName: "rexml"}, + candidateAddition{AdditionalVendors: []string{"ruby-lang"}}, + }, + { + pkg.GemPkg, + candidateKey{PkgName: "trunk"}, + candidateAddition{AdditionalVendors: []string{"ruby-lang"}}, + }, + { + pkg.GemPkg, + candidateKey{PkgName: "webrick"}, + candidateAddition{AdditionalVendors: []string{"ruby-lang"}}, + }, // Python packages { pkg.PythonPkg, candidateKey{PkgName: "python-rrdtool"}, candidateAddition{AdditionalProducts: []string{"rrdtool"}}, }, + { + pkg.PythonPkg, + candidateKey{PkgName: "cryptography"}, + candidateAddition{AdditionalProducts: []string{"python-cryptography"}, AdditionalVendors: []string{"python-cryptography_project"}}, + }, + { + pkg.PythonPkg, + candidateKey{PkgName: "pip"}, + candidateAddition{AdditionalVendors: []string{"pypa"}}, + }, + // Alpine packages + { + pkg.ApkPkg, + candidateKey{PkgName: "python3"}, + candidateAddition{AdditionalProducts: []string{"python"}, AdditionalVendors: []string{"python", "python_software_foundation"}}, + }, + { + pkg.ApkPkg, + candidateKey{PkgName: "python"}, + candidateAddition{AdditionalVendors: []string{"python_software_foundation"}}, + }, + { + pkg.ApkPkg, + candidateKey{PkgName: "nodejs"}, + candidateAddition{AdditionalProducts: []string{"node.js"}}, + }, + { + pkg.ApkPkg, + candidateKey{PkgName: "nodejs-current"}, + candidateAddition{AdditionalProducts: []string{"node.js"}}, + }, + // Binary packages + { + pkg.BinaryPkg, + candidateKey{PkgName: "node"}, + candidateAddition{AdditionalProducts: []string{"nodejs", "node.js"}}, + }, }) var defaultCandidateRemovals = buildCandidateRemovalLookup( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.71.0/syft/pkg/cataloger/common/cpe/generate.go new/syft-0.72.0/syft/pkg/cataloger/common/cpe/generate.go --- old/syft-0.71.0/syft/pkg/cataloger/common/cpe/generate.go 2023-02-09 17:35:11.000000000 +0100 +++ new/syft-0.72.0/syft/pkg/cataloger/common/cpe/generate.go 2023-02-16 16:22:43.000000000 +0100 @@ -109,6 +109,8 @@ vendors.union(candidateVendorsForPython(p)) case pkg.JavaMetadataType: vendors.union(candidateVendorsForJava(p)) + case pkg.ApkMetadataType: + vendors.union(candidateVendorsForAPK(p)) } // try swapping hyphens for underscores, vice versa, and removing separators altogether @@ -156,6 +158,11 @@ products.addValue(prod) } } + + if p.MetadataType == pkg.ApkMetadataType { + products.union(candidateProductsForAPK(p)) + } + // it is never OK to have candidates with these values ["" and "*"] (since CPEs will match any other value) products.removeByValue("") products.removeByValue("*") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.71.0/syft/pkg/cataloger/common/cpe/generate_test.go new/syft-0.72.0/syft/pkg/cataloger/common/cpe/generate_test.go --- old/syft-0.71.0/syft/pkg/cataloger/common/cpe/generate_test.go 2023-02-09 17:35:11.000000000 +0100 +++ new/syft-0.72.0/syft/pkg/cataloger/common/cpe/generate_test.go 2023-02-16 16:22:43.000000000 +0100 @@ -100,6 +100,18 @@ "cpe:2.3:a:william_goodman:name:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:william_goodman:python-name:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:william_goodman:python_name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:alex_goodman_project:python_name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:alex_goodman_project:name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:alex_goodman_project:python-name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:alex_goodmanproject:name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:alex_goodmanproject:python-name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:alex_goodmanproject:python_name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:william_goodman_project:name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:william_goodman_project:python-name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:william_goodman_project:python_name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:william_goodmanproject:name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:william_goodmanproject:python-name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:william_goodmanproject:python_name:3.2:*:*:*:*:*:*:*", }, }, { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.71.0/syft/pkg/cataloger/common/cpe/python.go new/syft-0.72.0/syft/pkg/cataloger/common/cpe/python.go --- old/syft-0.71.0/syft/pkg/cataloger/common/cpe/python.go 2023-02-09 17:35:11.000000000 +0100 +++ new/syft-0.72.0/syft/pkg/cataloger/common/cpe/python.go 2023-02-16 16:22:43.000000000 +0100 @@ -1,6 +1,19 @@ package cpe -import "github.com/anchore/syft/syft/pkg" +import ( + "fmt" + "strings" + + "github.com/anchore/syft/syft/pkg" +) + +func additionalVendorsForPython(v string) (vendors []string) { + if !strings.HasSuffix(v, "project") { + vendors = append(vendors, fmt.Sprintf("%sproject", v), fmt.Sprintf("%s_project", v)) + } + + return vendors +} func candidateVendorsForPython(p pkg.Package) fieldCandidateSet { metadata, ok := p.Metadata.(pkg.PythonPackageMetadata) @@ -11,18 +24,36 @@ vendors := newFieldCandidateSet() if metadata.Author != "" { + name := normalizePersonName(metadata.Author) vendors.add(fieldCandidate{ - value: normalizePersonName(metadata.Author), + value: name, disallowSubSelections: true, disallowDelimiterVariations: true, }) + + for _, v := range additionalVendorsForPython(name) { + vendors.add(fieldCandidate{ + value: v, + disallowSubSelections: true, + disallowDelimiterVariations: true, + }) + } } if metadata.AuthorEmail != "" { + name := normalizePersonName(stripEmailSuffix(metadata.AuthorEmail)) vendors.add(fieldCandidate{ - value: normalizePersonName(stripEmailSuffix(metadata.AuthorEmail)), + value: name, disallowSubSelections: true, }) + + for _, v := range additionalVendorsForPython(name) { + vendors.add(fieldCandidate{ + value: v, + disallowSubSelections: true, + disallowDelimiterVariations: true, + }) + } } return vendors diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.71.0/test/cli/all_formats_convertible_test.go new/syft-0.72.0/test/cli/all_formats_convertible_test.go --- old/syft-0.71.0/test/cli/all_formats_convertible_test.go 2023-02-09 17:35:11.000000000 +0100 +++ new/syft-0.72.0/test/cli/all_formats_convertible_test.go 2023-02-16 16:22:43.000000000 +0100 @@ -10,14 +10,9 @@ "github.com/stretchr/testify/require" ) -func TestConvertCmdFlags(t *testing.T) { +func TestAllFormatsConvertable(t *testing.T) { assertions := []traitAssertion{ - func(tb testing.TB, stdout, _ string, _ int) { - tb.Helper() - if len(stdout) < 1000 { - tb.Errorf("there may not be any report output (len=%d)", len(stdout)) - } - }, + assertStdoutLengthGreaterThan(1000), assertSuccessfulReturnCode, } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.71.0/test/cli/convert_cmd_test.go new/syft-0.72.0/test/cli/convert_cmd_test.go --- old/syft-0.71.0/test/cli/convert_cmd_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/syft-0.72.0/test/cli/convert_cmd_test.go 2023-02-16 16:22:43.000000000 +0100 @@ -0,0 +1,50 @@ +package cli + +import ( + "fmt" + "strings" + "testing" +) + +func TestConvertCmd(t *testing.T) { + assertions := []traitAssertion{ + assertInOutput("PackageName: musl-utils"), + assertSuccessfulReturnCode, + } + + tests := []struct { + from string + to string + }{ + {from: "syft-json", to: "spdx-tag-value"}, + } + + for _, test := range tests { + t.Run(fmt.Sprintf("from %s to %s", test.from, test.to), func(t *testing.T) { + sbomArgs := []string{"dir:./test-fixtures/image-pkg-coverage", "-o", test.from} + cmd, stdout, stderr := runSyft(t, nil, sbomArgs...) + if cmd.ProcessState.ExitCode() != 0 { + t.Log("STDOUT:\n", stdout) + t.Log("STDERR:\n", stderr) + t.Log("COMMAND:", strings.Join(cmd.Args, " ")) + t.Fatalf("failure executing syft creating an sbom") + return + } + + convertArgs := []string{"convert", "-", "-o", test.to} + cmd = getSyftCommand(t, convertArgs...) + + cmd.Stdin = strings.NewReader(stdout) + stdout, stderr = runCommandObj(t, cmd, nil, false) + + for _, traitFn := range assertions { + traitFn(t, stdout, stderr, cmd.ProcessState.ExitCode()) + } + if t.Failed() { + t.Log("STDOUT:\n", stdout) + t.Log("STDERR:\n", stderr) + t.Log("COMMAND:", strings.Join(cmd.Args, " ")) + } + }) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.71.0/test/cli/utils_test.go new/syft-0.72.0/test/cli/utils_test.go --- old/syft-0.71.0/test/cli/utils_test.go 2023-02-09 17:35:11.000000000 +0100 +++ new/syft-0.72.0/test/cli/utils_test.go 2023-02-16 16:22:43.000000000 +0100 @@ -177,7 +177,7 @@ t.Errorf("STDOUT: %s", stdout) t.Errorf("STDERR: %s", stderr) - // this probably indicates a timeout + // this probably indicates a timeout... lets run it again with more verbosity to help debug issues args = append(args, "-vv") cmd = getSyftCommand(t, args...) @@ -194,6 +194,48 @@ return cmd, stdout, stderr } +func runCommandObj(t testing.TB, cmd *exec.Cmd, env map[string]string, expectError bool) (string, string) { + cancel := make(chan bool, 1) + defer func() { + cancel <- true + }() + + if env == nil { + env = make(map[string]string) + } + + // we should not have tests reaching out for app update checks + env["SYFT_CHECK_FOR_APP_UPDATE"] = "false" + + timeout := func() { + select { + case <-cancel: + return + case <-time.After(60 * time.Second): + } + + if cmd != nil && cmd.Process != nil { + // get a stack trace printed + err := cmd.Process.Signal(syscall.SIGABRT) + if err != nil { + t.Errorf("error aborting: %+v", err) + } + } + } + + go timeout() + + stdout, stderr, err := runCommand(cmd, env) + + if !expectError && err != nil && stdout == "" { + t.Errorf("error running syft: %+v", err) + t.Errorf("STDOUT: %s", stdout) + t.Errorf("STDERR: %s", stderr) + } + + return stdout, stderr +} + func runCosign(t testing.TB, env map[string]string, args ...string) (*exec.Cmd, string, string) { cmd := getCommand(t, ".tmp/cosign", args...) if env == nil { ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/syft/vendor.tar.gz /work/SRC/openSUSE:Factory/.syft.new.22824/vendor.tar.gz differ: char 5, line 1