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

Reply via email to