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-03-10 22:07:24 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/syft (Old) and /work/SRC/openSUSE:Factory/.syft.new.31432 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "syft" Fri Mar 10 22:07:24 2023 rev:31 rq:1070559 version:0.74.1 Changes: -------- --- /work/SRC/openSUSE:Factory/syft/syft.changes 2023-03-03 22:31:17.552001903 +0100 +++ /work/SRC/openSUSE:Factory/.syft.new.31432/syft.changes 2023-03-10 22:07:31.161170586 +0100 @@ -1,0 +2,20 @@ +Thu Mar 09 15:31:12 UTC 2023 - ka...@b1-systems.de + +- Update to version 0.74.1: + * Update syft bootstrap tools to latest versions. (#1658) + * fix: improved Python binary detection (#1648) + * fix: suppress some known incorrect vendor candidates for npm + CPEs (#1659) + * fix: sanitize SPDX LicenseRefs (#1657) + * chore(deps): bump golang.org/x/mod from 0.8.0 to 0.9.0 (#1655) + * chore(deps): bump golang.org/x/net from 0.7.0 to 0.8.0 (#1653) + * chore(deps): bump github.com/spf13/afero from 1.9.4 to 1.9.5 + (#1654) + * chore(deps): bump golang.org/x/term from 0.5.0 to 0.6.0 (#1656) + * fix: dotnet PURL types are invalid (#1649) + * feat: disable cpe vendor wildcards to reduce false positives + (#1647) + * read relative etc/apk/repositories for alpine version when no + OS provided (#1615) + +------------------------------------------------------------------- Old: ---- syft-0.74.0.tar.gz New: ---- syft-0.74.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ syft.spec ++++++ --- /var/tmp/diff_new_pack.H5okv1/_old 2023-03-10 22:07:32.901178507 +0100 +++ /var/tmp/diff_new_pack.H5okv1/_new 2023-03-10 22:07:32.905178525 +0100 @@ -19,7 +19,7 @@ %define __arch_install_post export NO_BRP_STRIP_DEBUG=true Name: syft -Version: 0.74.0 +Version: 0.74.1 Release: 0 Summary: CLI tool and library for generating a Software Bill of Materials License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.H5okv1/_old 2023-03-10 22:07:32.949178725 +0100 +++ /var/tmp/diff_new_pack.H5okv1/_new 2023-03-10 22:07:32.953178744 +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.74.0</param> + <param name="revision">v0.74.1</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.74.0.tar.gz</param> + <param name="archive">syft-0.74.1.tar.gz</param> </service> </services> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.H5okv1/_old 2023-03-10 22:07:32.981178871 +0100 +++ /var/tmp/diff_new_pack.H5okv1/_new 2023-03-10 22:07:32.981178871 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/anchore/syft</param> - <param name="changesrevision">5f90d0371873faf5eb8f2e748909b32294be6263</param></service></servicedata> + <param name="changesrevision">41cbbe09b205e3b80e8a57d4f7a509b5f938557d</param></service></servicedata> (No newline at EOF) ++++++ syft-0.74.0.tar.gz -> syft-0.74.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/.github/workflows/validations.yaml new/syft-0.74.1/.github/workflows/validations.yaml --- old/syft-0.74.0/.github/workflows/validations.yaml 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/.github/workflows/validations.yaml 2023-03-07 18:54:32.000000000 +0100 @@ -54,6 +54,13 @@ 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 + id: unit-binary-cataloger-cache + uses: actions/cache@v3 + with: + path: syft/pkg/cataloger/binary/test-fixtures/classifiers/dynamic + key: ${{ runner.os }}-unit-binary-cataloger-cache-${{ hashFiles( 'syft/pkg/cataloger/binary/test-fixtures/cache.fingerprint' ) }} + - name: Run unit tests run: make unit diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/Makefile new/syft-0.74.1/Makefile --- old/syft-0.74.0/Makefile 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/Makefile 2023-03-07 18:54:32.000000000 +0100 @@ -14,7 +14,7 @@ GOSIMPORTS_VERSION := v0.3.7 BOUNCER_VERSION := v0.4.0 CHRONICLE_VERSION := v0.6.0 -GORELEASER_VERSION := v1.15.2 +GORELEASER_VERSION := v1.16.0 YAJSV_VERSION := v1.4.1 COSIGN_VERSION := v1.13.1 QUILL_VERSION := v0.2.0 @@ -189,6 +189,10 @@ cd test/integration/test-fixtures && \ make cache.fingerprint + # for BINARY test fixtures + cd syft/pkg/cataloger/binary/test-fixtures && \ + make cache.fingerprint + # for JAVA BUILD test fixtures cd syft/pkg/cataloger/java/test-fixtures/java-builds && \ make packages.fingerprint @@ -214,6 +218,7 @@ $(call title,Generating test fixtures) cd syft/pkg/cataloger/java/test-fixtures/java-builds && make cd syft/pkg/cataloger/rpm/test-fixtures && make + cd syft/pkg/cataloger/binary/test-fixtures && make .PHONY: show-test-image-cache show-test-image-cache: ## Show all docker and image tar cache diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/go.mod new/syft-0.74.1/go.mod --- old/syft-0.74.0/go.mod 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/go.mod 2023-03-07 18:54:32.000000000 +0100 @@ -32,7 +32,7 @@ github.com/sergi/go-diff v1.3.1 github.com/sirupsen/logrus v1.9.0 github.com/spdx/tools-golang v0.5.0-rc1 - github.com/spf13/afero v1.9.4 + github.com/spf13/afero v1.9.5 github.com/spf13/cobra v1.6.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.15.0 @@ -42,9 +42,9 @@ github.com/wagoodman/go-progress v0.0.0-20230301185719-21920a456ad5 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.7.0 - golang.org/x/term v0.5.0 + golang.org/x/mod v0.9.0 + golang.org/x/net v0.8.0 + golang.org/x/term v0.6.0 gopkg.in/yaml.v2 v2.4.0 ) @@ -126,9 +126,9 @@ github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect - golang.org/x/tools v0.2.0 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect + golang.org/x/tools v0.6.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect google.golang.org/grpc v1.52.0 // indirect diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/go.sum new/syft-0.74.1/go.sum --- old/syft-0.74.0/go.sum 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/go.sum 2023-03-07 18:54:32.000000000 +0100 @@ -519,8 +519,8 @@ github.com/spdx/tools-golang v0.5.0-rc1/go.mod h1:LI6onw172PdO57Ob/hgnLDD4Y2PMnroeNT3wO/2WJJI= 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.9.4 h1:Sd43wM1IWz/s1aVXdOBkjJvuP8UdyqioeE4AmM0QsBs= -github.com/spf13/afero v1.9.4/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= +github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= 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.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= @@ -627,7 +627,7 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= 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-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -670,8 +670,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 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 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= @@ -715,10 +715,11 @@ 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= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -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/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= 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= @@ -824,15 +825,15 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 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 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= 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= @@ -843,8 +844,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 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 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 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= @@ -908,8 +909,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.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= -golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 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= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/formats/common/spdxhelpers/license.go new/syft-0.74.1/syft/formats/common/spdxhelpers/license.go --- old/syft-0.74.0/syft/formats/common/spdxhelpers/license.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/formats/common/spdxhelpers/license.go 2023-03-07 18:54:32.000000000 +0100 @@ -24,6 +24,12 @@ // take all licenses and assume an AND expression; for information about license expressions see https://spdx.github.io/spdx-spec/appendix-IV-SPDX-license-expressions/ parsedLicenses := parseLicenses(p.Licenses) + for i, v := range parsedLicenses { + if strings.HasPrefix(v, spdxlicense.LicenseRefPrefix) { + parsedLicenses[i] = SanitizeElementID(v) + } + } + if len(parsedLicenses) == 0 { return NOASSERTION } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/formats/common/spdxhelpers/license_test.go new/syft-0.74.1/syft/formats/common/spdxhelpers/license_test.go --- old/syft-0.74.0/syft/formats/common/spdxhelpers/license_test.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/formats/common/spdxhelpers/license_test.go 2023-03-07 18:54:32.000000000 +0100 @@ -65,6 +65,17 @@ }, expected: "GPL-2.0-only", }, + { + name: "includes valid LicenseRef-", + input: pkg.Package{ + Licenses: []string{ + "one thing first", + "two things/#$^second", + "MIT", + }, + }, + expected: "LicenseRef-one-thing-first AND LicenseRef-two-things----second AND MIT", + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/formats/common/spdxhelpers/to_format_model.go new/syft-0.74.1/syft/formats/common/spdxhelpers/to_format_model.go --- old/syft-0.74.0/syft/formats/common/spdxhelpers/to_format_model.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/formats/common/spdxhelpers/to_format_model.go 2023-03-07 18:54:32.000000000 +0100 @@ -514,8 +514,8 @@ func toOtherLicenses(catalog *pkg.Catalog) []*spdx.OtherLicense { licenses := map[string]bool{} - for _, pkg := range catalog.Sorted() { - for _, license := range parseLicenses(pkg.Licenses) { + for _, p := range catalog.Sorted() { + for _, license := range parseLicenses(p.Licenses) { if strings.HasPrefix(license, spdxlicense.LicenseRefPrefix) { licenses[license] = true } @@ -526,7 +526,7 @@ // separate the actual ID from the prefix name := strings.TrimPrefix(license, spdxlicense.LicenseRefPrefix) result = append(result, &spdx.OtherLicense{ - LicenseIdentifier: license, + LicenseIdentifier: SanitizeElementID(license), LicenseName: name, ExtractedText: NONE, // we probably should have some extracted text here, but this is good enough for now }) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/formats/common/spdxhelpers/to_format_model_test.go new/syft-0.74.1/syft/formats/common/spdxhelpers/to_format_model_test.go --- old/syft-0.74.0/syft/formats/common/spdxhelpers/to_format_model_test.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/formats/common/spdxhelpers/to_format_model_test.go 2023-03-07 18:54:32.000000000 +0100 @@ -369,7 +369,7 @@ } func Test_H1Digest(t *testing.T) { - sbom := sbom.SBOM{} + s := sbom.SBOM{} tests := []struct { name string pkg pkg.Package @@ -416,7 +416,7 @@ for _, test := range tests { t.Run(test.name, func(t *testing.T) { catalog := pkg.NewCatalog(test.pkg) - pkgs := toPackages(catalog, sbom) + pkgs := toPackages(catalog, s) require.Len(t, pkgs, 1) for _, p := range pkgs { if test.expectedDigest == "" { @@ -431,3 +431,67 @@ }) } } + +func Test_OtherLicenses(t *testing.T) { + tests := []struct { + name string + pkg pkg.Package + expected []*spdx.OtherLicense + }{ + { + name: "no licenseRef", + pkg: pkg.Package{ + Licenses: []string{ + "MIT", + }, + }, + expected: nil, + }, + { + name: "single licenseRef", + pkg: pkg.Package{ + Licenses: []string{ + "un known", + }, + }, + expected: []*spdx.OtherLicense{ + { + LicenseIdentifier: "LicenseRef-un-known", + LicenseName: "un known", + ExtractedText: NONE, + }, + }, + }, + { + name: "multiple licenseRef", + pkg: pkg.Package{ + Licenses: []string{ + "un known", + "not known %s", + "MIT", + }, + }, + expected: []*spdx.OtherLicense{ + { + LicenseIdentifier: "LicenseRef-un-known", + LicenseName: "un known", + ExtractedText: NONE, + }, + { + LicenseIdentifier: "LicenseRef-not-known--s", + LicenseName: "not known %s", + ExtractedText: NONE, + }, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + catalog := pkg.NewCatalog(test.pkg) + otherLicenses := toOtherLicenses(catalog) + require.Len(t, otherLicenses, len(test.expected)) + require.Equal(t, test.expected, otherLicenses) + }) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/apkdb/cataloger_test.go new/syft-0.74.1/syft/pkg/cataloger/apkdb/cataloger_test.go --- old/syft-0.74.0/syft/pkg/cataloger/apkdb/cataloger_test.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/apkdb/cataloger_test.go 2023-03-07 18:54:32.000000000 +0100 @@ -24,6 +24,7 @@ pkgtest.NewCatalogTester(). FromDirectory(t, test.fixture). ExpectsResolverContentQueries(test.expected). + IgnoreUnfulfilledPathResponses("etc/apk/repositories"). TestCataloger(t, NewApkdbCataloger()) }) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/apkdb/parse_apk_db.go new/syft-0.74.1/syft/pkg/cataloger/apkdb/parse_apk_db.go --- old/syft-0.74.0/syft/pkg/cataloger/apkdb/parse_apk_db.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/apkdb/parse_apk_db.go 2023-03-07 18:54:32.000000000 +0100 @@ -3,7 +3,9 @@ import ( "bufio" "fmt" + "io" "path" + "regexp" "strconv" "strings" @@ -20,11 +22,15 @@ // integrity check var _ generic.Parser = parseApkDB +var ( + repoRegex = regexp.MustCompile(`(?m)^https://.*\.alpinelinux\.org/alpine/v([^/]+)/([a-zA-Z0-9_]+)$`) +) + // parseApkDB parses packages from a given APK installed DB file. For more // information on specific fields, see https://wiki.alpinelinux.org/wiki/Apk_spec. // -//nolint:funlen -func parseApkDB(_ source.FileResolver, env *generic.Environment, reader source.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { +//nolint:funlen,gocognit +func parseApkDB(resolver source.FileResolver, env *generic.Environment, reader source.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { scanner := bufio.NewScanner(reader) var apks []pkg.ApkMetadata @@ -101,6 +107,19 @@ if env != nil { r = env.LinuxRelease } + // this is somewhat ugly, but better than completely failing when we can't find the release, + // e.g. embedded deeper in the tree, like containers or chroots. + // but we now have no way of handling different repository sources. On the other hand, + // we never could before this. At least now, we can handle some. + // This should get fixed with https://gitlab.alpinelinux.org/alpine/apk-tools/-/issues/10875 + if r == nil { + // find the repositories file from the relative directory of the DB file + releases := findReleases(resolver, reader.Location.RealPath) + + if len(releases) > 0 { + r = &releases[0] + } + } pkgs := make([]pkg.Package, 0, len(apks)) for _, apk := range apks { @@ -110,6 +129,58 @@ return pkgs, discoverPackageDependencies(pkgs), nil } +func findReleases(resolver source.FileResolver, dbPath string) []linux.Release { + if resolver == nil { + return nil + } + + reposLocation := path.Clean(path.Join(path.Dir(dbPath), "../../../etc/apk/repositories")) + locations, err := resolver.FilesByPath(reposLocation) + if err != nil { + log.Tracef("unable to find APK repositories file %q: %+v", reposLocation, err) + return nil + } + + if len(locations) == 0 { + return nil + } + location := locations[0] + + reposReader, err := resolver.FileContentsByLocation(location) + if err != nil { + log.Tracef("unable to fetch contents for APK repositories file %q: %+v", reposLocation, err) + return nil + } + + return parseReleasesFromAPKRepository(source.LocationReadCloser{ + Location: location, + ReadCloser: reposReader, + }) +} + +func parseReleasesFromAPKRepository(reader source.LocationReadCloser) []linux.Release { + var releases []linux.Release + + reposB, err := io.ReadAll(reader) + if err != nil { + log.Tracef("unable to read APK repositories file %q: %+v", reader.Location.RealPath, err) + return nil + } + + parts := repoRegex.FindAllStringSubmatch(string(reposB), -1) + for _, part := range parts { + if len(part) >= 3 { + releases = append(releases, linux.Release{ + Name: "Alpine Linux", + ID: "alpine", + VersionID: part[1], + }) + } + } + + return releases +} + func parseApkField(line string) *apkField { parts := strings.SplitN(line, ":", 2) if len(parts) != 2 { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/apkdb/parse_apk_db_test.go new/syft-0.74.1/syft/pkg/cataloger/apkdb/parse_apk_db_test.go --- old/syft-0.74.0/syft/pkg/cataloger/apkdb/parse_apk_db_test.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/apkdb/parse_apk_db_test.go 2023-03-07 18:54:32.000000000 +0100 @@ -1,8 +1,10 @@ package apkdb import ( + "io" "os" "path/filepath" + "strings" "testing" "github.com/google/go-cmp/cmp" @@ -1186,3 +1188,49 @@ }) } } + +func TestParseReleasesFromAPKRepository(t *testing.T) { + tests := []struct { + repos string + want []linux.Release + desc string + }{ + { + "https://foo.alpinelinux.org/alpine/v3.14/main", + []linux.Release{ + {Name: "Alpine Linux", ID: "alpine", VersionID: "3.14"}, + }, + "single repo", + }, + { + `https://foo.alpinelinux.org/alpine/v3.14/main +https://foo.alpinelinux.org/alpine/v3.14/community`, + []linux.Release{ + {Name: "Alpine Linux", ID: "alpine", VersionID: "3.14"}, + {Name: "Alpine Linux", ID: "alpine", VersionID: "3.14"}, + }, + "multiple repos", + }, + { + ``, + nil, + "empty", + }, + { + `https://foo.bar.org/alpine/v3.14/main +https://foo.them.org/alpine/v3.14/community`, + nil, + "invalid repos", + }, + } + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + reposReader := io.NopCloser(strings.NewReader(tt.repos)) + got := parseReleasesFromAPKRepository(source.LocationReadCloser{ + Location: source.NewLocation("test"), + ReadCloser: reposReader, + }) + assert.Equal(t, tt.want, got) + }) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/binary/cataloger.go new/syft-0.74.1/syft/pkg/cataloger/binary/cataloger.go --- old/syft-0.74.0/syft/pkg/cataloger/binary/cataloger.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/binary/cataloger.go 2023-03-07 18:54:32.000000000 +0100 @@ -74,12 +74,7 @@ return nil, err } for _, location := range locations { - reader, err := resolver.FileContentsByLocation(location) - if err != nil { - return nil, err - } - locationReader := source.NewLocationReadCloser(location, reader) - pkgs, err := cls.EvidenceMatcher(cls, locationReader) + pkgs, err := cls.EvidenceMatcher(resolver, cls, location) if err != nil { return nil, err } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/binary/cataloger_test.go new/syft-0.74.1/syft/pkg/cataloger/binary/cataloger_test.go --- old/syft-0.74.0/syft/pkg/cataloger/binary/cataloger_test.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/binary/cataloger_test.go 2023-03-07 18:54:32.000000000 +0100 @@ -4,8 +4,11 @@ "errors" "fmt" "io" + "strings" "testing" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -69,25 +72,6 @@ }, }, { - name: "positive-python-duplicates", - fixtureDir: "test-fixtures/classifiers/positive/python-duplicates", - expected: pkg.Package{ - Name: "python", - Version: "3.8.16", - Type: "binary", - PURL: "pkg:generic/python@3.8.16", - Locations: locations("dir/python3.8", "python3.8", "libpython3.8.so", "patchlevel.h"), - Metadata: pkg.BinaryMetadata{ - Matches: []pkg.ClassifierMatch{ - match("python-binary", "dir/python3.8"), - match("python-binary", "python3.8"), - match("python-binary-lib", "libpython3.8.so"), - match("cpython-source", "patchlevel.h"), - }, - }, - }, - }, - { name: "positive-traefik-2.9.6", fixtureDir: "test-fixtures/classifiers/positive/traefik-2.9.6", expected: pkg.Package{ @@ -315,25 +299,81 @@ }, }, { + name: "positive-python-3.11.2-from-shared-lib", + fixtureDir: "test-fixtures/classifiers/dynamic/python-binary-shared-lib-3.11", + expected: pkg.Package{ + Name: "python", + Version: "3.11.2", + PURL: "pkg:generic/python@3.11.2", + Locations: locations("python3", "libpython3.11.so.1.0"), + Metadata: pkg.BinaryMetadata{ + Matches: []pkg.ClassifierMatch{ + match("python-binary", "python3"), + match("python-binary", "libpython3.11.so.1.0"), + match("python-binary-lib", "libpython3.11.so.1.0"), + }, + }, + }, + }, + { + name: "positive-python-3.9-from-shared-redhat-lib", + fixtureDir: "test-fixtures/classifiers/dynamic/python-binary-shared-lib-redhat-3.9", + expected: pkg.Package{ + Name: "python", + Version: "3.9.13", + PURL: "pkg:generic/python@3.9.13", + Locations: locations("python3.9", "libpython3.9.so.1.0"), + Metadata: pkg.BinaryMetadata{ + Matches: []pkg.ClassifierMatch{ + match("python-binary", "python3.9"), + match("python-binary", "libpython3.9.so.1.0"), + match("python-binary-lib", "libpython3.9.so.1.0"), + }, + }, + }, + }, + { + name: "positive-python-binary-with-version-3.9", + fixtureDir: "test-fixtures/classifiers/dynamic/python-binary-with-version-3.9", + expected: pkg.Package{ + Name: "python", + Version: "3.9.2", + PURL: "pkg:generic/python@3.9.2", + Locations: locations("python3.9"), + Metadata: pkg.BinaryMetadata{ + Matches: []pkg.ClassifierMatch{ + match("python-binary", "python3.9"), + }, + }, + }, + }, + { name: "positive-python3.6", fixtureDir: "test-fixtures/classifiers/positive/python-binary-3.6", expected: pkg.Package{ Name: "python", - Version: "3.6.3a-vZ9", - PURL: "pkg:generic/python@3.6.3a-vZ9", + Version: "3.6.3", + PURL: "pkg:generic/python@3.6.3", Locations: locations("python3.6"), Metadata: metadata("python-binary"), }, }, { - name: "positive-patchlevel.h", - fixtureDir: "test-fixtures/classifiers/positive/python-source-3.9", + name: "positive-python-duplicates", + fixtureDir: "test-fixtures/classifiers/positive/python-duplicates", expected: pkg.Package{ Name: "python", - Version: "3.9-aZ5", - PURL: "pkg:generic/python@3.9-aZ5", - Locations: locations("patchlevel.h"), - Metadata: metadata("cpython-source"), + Version: "3.8.16", + Type: "binary", + PURL: "pkg:generic/python@3.8.16", + Locations: locations("dir/python3.8", "python3.8", "libpython3.8.so"), + Metadata: pkg.BinaryMetadata{ + Matches: []pkg.ClassifierMatch{ + match("python-binary", "dir/python3.8"), + match("python-binary", "python3.8"), + match("python-binary-lib", "libpython3.8.so"), + }, + }, }, }, { @@ -491,17 +531,6 @@ require.NoError(t, err) for _, p := range packages { - expectedLocations := test.expected.Locations.ToSlice() - gotLocations := p.Locations.ToSlice() - require.Len(t, gotLocations, len(expectedLocations)) - - for i, expectedLocation := range expectedLocations { - gotLocation := gotLocations[i] - if expectedLocation.RealPath != gotLocation.RealPath { - t.Fatalf("locations do not match; expected: %v got: %v", expectedLocations, gotLocations) - } - } - assertPackagesAreEqual(t, test.expected, p) } }) @@ -611,6 +640,21 @@ } func assertPackagesAreEqual(t *testing.T, expected pkg.Package, p pkg.Package) { + var failMessages []string + expectedLocations := expected.Locations.ToSlice() + gotLocations := p.Locations.ToSlice() + + if len(expectedLocations) != len(gotLocations) { + failMessages = append(failMessages, "locations are not equal length") + } else { + for i, expectedLocation := range expectedLocations { + gotLocation := gotLocations[i] + if expectedLocation.RealPath != gotLocation.RealPath { + failMessages = append(failMessages, fmt.Sprintf("locations do not match; expected: %v got: %v", expectedLocation.RealPath, gotLocation.RealPath)) + } + } + } + m1 := expected.Metadata.(pkg.BinaryMetadata).Matches m2 := p.Metadata.(pkg.BinaryMetadata).Matches matches := true @@ -633,17 +677,26 @@ } else { matches = false } + + if !matches { + failMessages = append(failMessages, "classifier matches not equal") + } if expected.Name != p.Name || expected.Version != p.Version || - expected.PURL != p.PURL || - !matches { - assert.Failf(t, "packages not equal", "%v != %v", stringifyPkg(expected), stringifyPkg(p)) + expected.PURL != p.PURL { + failMessages = append(failMessages, "packages do not match") } -} -func stringifyPkg(p pkg.Package) string { - matches := p.Metadata.(pkg.BinaryMetadata).Matches - return fmt.Sprintf("(name=%s, version=%s, purl=%s, matches=%+v)", p.Name, p.Version, p.PURL, matches) + if len(failMessages) > 0 { + assert.Failf(t, strings.Join(failMessages, "; "), "diff: %s", + cmp.Diff(expected, p, + cmp.Transformer("Locations", func(l source.LocationSet) []source.Location { + return l.ToSlice() + }), + cmpopts.IgnoreUnexported(pkg.Package{}, source.Location{}), + cmpopts.IgnoreFields(pkg.Package{}, "CPEs", "FoundBy", "MetadataType", "Type"), + )) + } } type panicyResolver struct { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/binary/classifier.go new/syft-0.74.1/syft/pkg/cataloger/binary/classifier.go --- old/syft-0.74.0/syft/pkg/cataloger/binary/classifier.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/binary/classifier.go 2023-03-07 18:54:32.000000000 +0100 @@ -2,6 +2,9 @@ import ( "bytes" + "debug/elf" + "debug/macho" + "debug/pe" "fmt" "io" "reflect" @@ -10,6 +13,7 @@ "github.com/anchore/packageurl-go" "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/cpe" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/internal/unionreader" @@ -49,12 +53,12 @@ } // evidenceMatcher is a function called to catalog Packages that match some sort of evidence -type evidenceMatcher func(classifier classifier, reader source.LocationReadCloser) ([]pkg.Package, error) +type evidenceMatcher func(resolver source.FileResolver, classifier classifier, location source.Location) ([]pkg.Package, error) func evidenceMatchers(matchers ...evidenceMatcher) evidenceMatcher { - return func(classifier classifier, reader source.LocationReadCloser) ([]pkg.Package, error) { + return func(resolver source.FileResolver, classifier classifier, location source.Location) ([]pkg.Package, error) { for _, matcher := range matchers { - match, err := matcher(classifier, reader) + match, err := matcher(resolver, classifier, location) if err != nil { return nil, err } @@ -68,12 +72,12 @@ func fileNameTemplateVersionMatcher(fileNamePattern string, contentTemplate string) evidenceMatcher { pat := regexp.MustCompile(fileNamePattern) - return func(classifier classifier, reader source.LocationReadCloser) ([]pkg.Package, error) { - if !pat.MatchString(reader.RealPath) { + return func(resolver source.FileResolver, classifier classifier, location source.Location) ([]pkg.Package, error) { + if !pat.MatchString(location.RealPath) { return nil, nil } - filepathNamedGroupValues := internal.MatchNamedCaptureGroups(pat, reader.RealPath) + filepathNamedGroupValues := internal.MatchNamedCaptureGroups(pat, location.RealPath) tmpl, err := template.New("").Parse(contentTemplate) if err != nil { @@ -91,26 +95,70 @@ return nil, fmt.Errorf("unable to compile rendered regex=%q: %w", patternBuf.String(), err) } - contents, err := getContents(reader) + contents, err := getContents(resolver, location) if err != nil { return nil, fmt.Errorf("unable to get read contents for file: %w", err) } matchMetadata := internal.MatchNamedCaptureGroups(tmplPattern, string(contents)) - return singlePackage(classifier, reader, matchMetadata), nil + return singlePackage(classifier, location, matchMetadata), nil } } func fileContentsVersionMatcher(pattern string) evidenceMatcher { pat := regexp.MustCompile(pattern) - return func(classifier classifier, reader source.LocationReadCloser) ([]pkg.Package, error) { - contents, err := getContents(reader) + return func(resolver source.FileResolver, classifier classifier, location source.Location) ([]pkg.Package, error) { + contents, err := getContents(resolver, location) if err != nil { return nil, fmt.Errorf("unable to get read contents for file: %w", err) } matchMetadata := internal.MatchNamedCaptureGroups(pat, string(contents)) - return singlePackage(classifier, reader, matchMetadata), nil + return singlePackage(classifier, location, matchMetadata), nil + } +} + +//nolint:gocognit +func sharedLibraryLookup(sharedLibraryPattern string, sharedLibraryMatcher evidenceMatcher) evidenceMatcher { + pat := regexp.MustCompile(sharedLibraryPattern) + return func(resolver source.FileResolver, classifier classifier, location source.Location) (packages []pkg.Package, _ error) { + libs, err := sharedLibraries(resolver, location) + if err != nil { + return nil, err + } + for _, lib := range libs { + if !pat.MatchString(lib) { + continue + } + + locations, err := resolver.FilesByGlob("**/" + lib) + if err != nil { + return nil, err + } + for _, libraryLication := range locations { + pkgs, err := sharedLibraryMatcher(resolver, classifier, libraryLication) + if err != nil { + return nil, err + } + for _, p := range pkgs { + // set the source binary as the first location + locationSet := source.NewLocationSet(location) + locationSet.Add(p.Locations.ToSlice()...) + p.Locations = locationSet + meta, _ := p.Metadata.(pkg.BinaryMetadata) + p.Metadata = pkg.BinaryMetadata{ + Matches: append([]pkg.ClassifierMatch{ + { + Classifier: classifier.Class, + Location: location, + }, + }, meta.Matches...), + } + packages = append(packages, p) + } + } + } + return packages, nil } } @@ -122,7 +170,7 @@ return p } -func singlePackage(classifier classifier, reader source.LocationReadCloser, matchMetadata map[string]string) []pkg.Package { +func singlePackage(classifier classifier, location source.Location, matchMetadata map[string]string) []pkg.Package { version, ok := matchMetadata["version"] if !ok { return nil @@ -140,7 +188,7 @@ p := pkg.Package{ Name: classifier.Package, Version: version, - Locations: source.NewLocationSet(reader.Location), + Locations: source.NewLocationSet(location), Type: pkg.BinaryPkg, CPEs: cpes, FoundBy: catalogerName, @@ -149,7 +197,7 @@ Matches: []pkg.ClassifierMatch{ { Classifier: classifier.Class, - Location: reader.Location, + Location: location, }, }, }, @@ -174,8 +222,13 @@ return []pkg.Package{p} } -func getContents(reader source.LocationReadCloser) ([]byte, error) { - unionReader, err := unionreader.GetUnionReader(reader.ReadCloser) +func getContents(resolver source.FileResolver, location source.Location) ([]byte, error) { + reader, err := resolver.FileContentsByLocation(location) + if err != nil { + return nil, err + } + + unionReader, err := unionreader.GetUnionReader(reader) if err != nil { return nil, fmt.Errorf("unable to get union reader for file: %w", err) } @@ -195,3 +248,43 @@ cpe.Must(cpeString), } } + +// sharedLibraries returns a list of all shared libraries found within a binary, currently +// supporting: elf, macho, and windows pe +func sharedLibraries(resolver source.FileResolver, location source.Location) ([]string, error) { + contents, err := getContents(resolver, location) + if err != nil { + return nil, err + } + + r := bytes.NewReader(contents) + + e, _ := elf.NewFile(r) + if e != nil { + symbols, err := e.ImportedLibraries() + if err != nil { + log.Debugf("unable to read elf binary at: %s -- %s", location.RealPath, err) + } + return symbols, nil + } + + m, _ := macho.NewFile(r) + if m != nil { + symbols, err := m.ImportedLibraries() + if err != nil { + log.Debugf("unable to read macho binary at: %s -- %s", location.RealPath, err) + } + return symbols, nil + } + + p, _ := pe.NewFile(r) + if p != nil { + symbols, err := p.ImportedLibraries() + if err != nil { + log.Debugf("unable to read pe binary at: %s -- %s", location.RealPath, err) + } + return symbols, nil + } + + return nil, nil +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/binary/classifier_test.go new/syft-0.74.1/syft/pkg/cataloger/binary/classifier_test.go --- old/syft-0.74.0/syft/pkg/cataloger/binary/classifier_test.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/binary/classifier_test.go 2023-03-07 18:54:32.000000000 +0100 @@ -67,10 +67,8 @@ locations, err := resolver.FilesByPath(test.fixture) require.NoError(t, err) require.Len(t, locations, 1) - location := locations[0] - readCloser, err := resolver.FileContentsByLocation(location) - require.NoError(t, err) - pkgs, err := test.classifier.EvidenceMatcher(test.classifier, source.NewLocationReadCloser(location, readCloser)) + + pkgs, err := test.classifier.EvidenceMatcher(resolver, test.classifier, locations[0]) require.NoError(t, err) require.Len(t, pkgs, 1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/binary/default_classifiers.go new/syft-0.74.1/syft/pkg/cataloger/binary/default_classifiers.go --- old/syft-0.74.0/syft/pkg/cataloger/binary/default_classifiers.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/binary/default_classifiers.go 2023-03-07 18:54:32.000000000 +0100 @@ -9,22 +9,16 @@ { Class: "python-binary", FileGlob: "**/python*", - EvidenceMatcher: fileNameTemplateVersionMatcher( - `(.*/|^)python(?P<version>[0-9]+\.[0-9]+)$`, - `(?m)(?P<version>{{ .version }}\.[0-9]+[-_a-zA-Z0-9]*)`), - Package: "python", - PURL: mustPURL("pkg:generic/python@version"), - CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:python_software_foundation:python:*:*:*:*:*:*:*:*"), - cpe.Must("cpe:2.3:a:python:python:*:*:*:*:*:*:*:*"), - }, - }, - { - Class: "python-binary-lib", - FileGlob: "**/libpython*.so*", - EvidenceMatcher: fileNameTemplateVersionMatcher( - `(.*/|^)libpython(?P<version>[0-9]+\.[0-9]+).so.*$`, - `(?m)(?P<version>{{ .version }}\.[0-9]+[-_a-zA-Z0-9]*)`), + EvidenceMatcher: evidenceMatchers( + // try to find version information from libpython shared libraries + sharedLibraryLookup( + `^libpython[0-9]+(?:\.[0-9]+)+\.so.*$`, + libpythonMatcher), + // check for version information in the binary + fileNameTemplateVersionMatcher( + `(?:.*/|^)python(?P<version>[0-9]+(?:\.[0-9]+)+)$`, + pythonVersionTemplate), + ), Package: "python", PURL: mustPURL("pkg:generic/python@version"), CPEs: []cpe.CPE{ @@ -33,12 +27,11 @@ }, }, { - Class: "cpython-source", - FileGlob: "**/patchlevel.h", - EvidenceMatcher: fileContentsVersionMatcher( - `(?m)#define\s+PY_VERSION\s+"?(?P<version>[0-9\.\-_a-zA-Z]+)"?`), - Package: "python", - PURL: mustPURL("pkg:generic/python@version"), + Class: "python-binary-lib", + FileGlob: "**/libpython*.so*", + EvidenceMatcher: libpythonMatcher, + Package: "python", + PURL: mustPURL("pkg:generic/python@version"), CPEs: []cpe.CPE{ cpe.Must("cpe:2.3:a:python_software_foundation:python:*:*:*:*:*:*:*:*"), cpe.Must("cpe:2.3:a:python:python:*:*:*:*:*:*:*:*"), @@ -228,3 +221,11 @@ CPEs: singleCPE("cpe:2.3:a:rust-lang:rust:*:*:*:*:*:*:*:*"), }, } + +// in both binaries and shared libraries, the version pattern is [NUL]3.11.2[NUL] +var pythonVersionTemplate = `(?m)\x00(?P<version>{{ .version }}[-._a-zA-Z0-9]*)\x00` + +var libpythonMatcher = fileNameTemplateVersionMatcher( + `(?:.*/|^)libpython(?P<version>[0-9]+(?:\.[0-9]+)+)\.so.*$`, + pythonVersionTemplate, +) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/binary/test-fixtures/.gitignore new/syft-0.74.1/syft/pkg/cataloger/binary/test-fixtures/.gitignore --- old/syft-0.74.0/syft/pkg/cataloger/binary/test-fixtures/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/binary/test-fixtures/.gitignore 2023-03-07 18:54:32.000000000 +0100 @@ -0,0 +1 @@ +classifiers/dynamic diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/binary/test-fixtures/Makefile new/syft-0.74.1/syft/pkg/cataloger/binary/test-fixtures/Makefile --- old/syft-0.74.0/syft/pkg/cataloger/binary/test-fixtures/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/binary/test-fixtures/Makefile 2023-03-07 18:54:32.000000000 +0100 @@ -0,0 +1,38 @@ +.PHONY: all +all: \ + classifiers/dynamic/python-binary-shared-lib-3.11 \ + classifiers/dynamic/python-binary-shared-lib-redhat-3.9 \ + classifiers/dynamic/python-binary-with-version-3.9 + +classifiers/dynamic/python-binary-shared-lib-3.11: + $(eval $@_image := "python:3.11-slim@sha256:0b106e1d2bf485c2a41474bc9cd5103e9eea4e179f40f10741b53b127059221e") + ./get-image-file.sh $($@_image) \ + /usr/local/bin/python3.11 \ + $@/python3 + ./get-image-file.sh $($@_image) \ + /usr/local/lib/libpython3.11.so.1.0 \ + $@/libpython3.11.so.1.0 + +classifiers/dynamic/python-binary-shared-lib-redhat-3.9: + $(eval $@_image := "registry.access.redhat.com/ubi8/python-39@sha256:f3cf958b96ce016b63e3e163e488f52e42891304dafef5a0811563f22e3cbad0") + ./get-image-file.sh $($@_image) \ + /usr/bin/python3.9 \ + $@/python3.9 + ./get-image-file.sh $($@_image) \ + /usr/lib64/libpython3.9.so.1.0 \ + $@/libpython3.9.so.1.0 + +classifiers/dynamic/python-binary-with-version-3.9: + $(eval $@_image := "python:3.9.16-bullseye@sha256:93fb93c461a2e47a2176706fad1f39eaacd5dd40e19c0b018699a28c03eb2e2a") + ./get-image-file.sh $($@_image) \ + /usr/bin/python3.9 \ + $@/python3.9 + +.PHONY: clean +clean: + rm -rf classifiers/dynamic + +.PHONY: cache.fingerprint +cache.fingerprint: # for CI + $(title,Install test fixture fingerprint) + @find ./classifiers/dynamic/* -type f -exec md5sum {} + | awk '{print $1}' | sort | tee /dev/stderr | md5sum | tee cache.fingerprint >> cache.fingerprint Binary files old/syft-0.74.0/syft/pkg/cataloger/binary/test-fixtures/classifiers/positive/python-binary-3.6/python3.6 and new/syft-0.74.1/syft/pkg/cataloger/binary/test-fixtures/classifiers/positive/python-binary-3.6/python3.6 differ Binary files old/syft-0.74.0/syft/pkg/cataloger/binary/test-fixtures/classifiers/positive/python-duplicates/dir/python3.8 and new/syft-0.74.1/syft/pkg/cataloger/binary/test-fixtures/classifiers/positive/python-duplicates/dir/python3.8 differ Binary files old/syft-0.74.0/syft/pkg/cataloger/binary/test-fixtures/classifiers/positive/python-duplicates/libpython3.8.so and new/syft-0.74.1/syft/pkg/cataloger/binary/test-fixtures/classifiers/positive/python-duplicates/libpython3.8.so differ Binary files old/syft-0.74.0/syft/pkg/cataloger/binary/test-fixtures/classifiers/positive/python-duplicates/python3.8 and new/syft-0.74.1/syft/pkg/cataloger/binary/test-fixtures/classifiers/positive/python-duplicates/python3.8 differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/binary/test-fixtures/classifiers/positive/python-source-3.9/patchlevel.h new/syft-0.74.1/syft/pkg/cataloger/binary/test-fixtures/classifiers/positive/python-source-3.9/patchlevel.h --- old/syft-0.74.0/syft/pkg/cataloger/binary/test-fixtures/classifiers/positive/python-source-3.9/patchlevel.h 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/binary/test-fixtures/classifiers/positive/python-source-3.9/patchlevel.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,7 +0,0 @@ -# note: this SHOULD match as python 3.9 - -some source code... - -#define PY_VERSION 3.9-aZ5 - -more source! \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/binary/test-fixtures/get-image-file.sh new/syft-0.74.1/syft/pkg/cataloger/binary/test-fixtures/get-image-file.sh --- old/syft-0.74.0/syft/pkg/cataloger/binary/test-fixtures/get-image-file.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/binary/test-fixtures/get-image-file.sh 2023-03-07 18:54:32.000000000 +0100 @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -uxe + +CTRID=$(docker create $1) + +function cleanup() { + docker rm "${CTRID}" +} + +trap cleanup EXIT +set +e + +mkdir -p $(dirname $3) + +docker cp ${CTRID}:$2 $3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/common/cpe/candidate_by_package_type.go new/syft-0.74.1/syft/pkg/cataloger/common/cpe/candidate_by_package_type.go --- old/syft-0.74.0/syft/pkg/cataloger/common/cpe/candidate_by_package_type.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/common/cpe/candidate_by_package_type.go 2023-03-07 18:54:32.000000000 +0100 @@ -350,6 +350,27 @@ candidateKey{PkgName: "redis"}, candidateRemovals{VendorsToRemove: []string{"redis"}}, }, + // NPM packages + { + pkg.NpmPkg, + candidateKey{PkgName: "redis"}, + candidateRemovals{VendorsToRemove: []string{"redis"}}, + }, + { + pkg.NpmPkg, + candidateKey{PkgName: "php"}, + candidateRemovals{VendorsToRemove: []string{"php"}}, + }, + { + pkg.NpmPkg, + candidateKey{PkgName: "delegate"}, + candidateRemovals{VendorsToRemove: []string{"delegate"}}, + }, + { + pkg.NpmPkg, + candidateKey{PkgName: "docker"}, + candidateRemovals{VendorsToRemove: []string{"docker"}}, + }, }) // buildCandidateLookup is a convenience function for creating the defaultCandidateAdditions set diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/common/cpe/generate.go new/syft-0.74.1/syft/pkg/cataloger/common/cpe/generate.go --- old/syft-0.74.0/syft/pkg/cataloger/common/cpe/generate.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/common/cpe/generate.go 2023-03-07 18:54:32.000000000 +0100 @@ -93,13 +93,6 @@ } } - // some ecosystems do not have enough metadata to determine the vendor accurately, in which case we selectively - // allow * as a candidate. Note: do NOT allow Java packages to have * vendors. - switch p.Language { - case pkg.Ruby, pkg.JavaScript: - vendors.addValue(wfn.Any) - } - switch p.MetadataType { case pkg.RpmMetadataType: vendors.union(candidateVendorsForRPM(p)) @@ -111,8 +104,15 @@ vendors.union(candidateVendorsForJava(p)) case pkg.ApkMetadataType: vendors.union(candidateVendorsForAPK(p)) + case pkg.NpmPackageJSONMetadataType: + vendors.union(candidateVendorsForJavascript(p)) } + // We should no longer be generating vendor candidates with these values ["" and "*"] + // (since CPEs will match any other value) + vendors.removeByValue("") + vendors.removeByValue("*") + // try swapping hyphens for underscores, vice versa, and removing separators altogether addDelimiterVariations(vendors) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/common/cpe/generate_test.go new/syft-0.74.1/syft/pkg/cataloger/common/cpe/generate_test.go --- old/syft-0.74.0/syft/pkg/cataloger/common/cpe/generate_test.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/common/cpe/generate_test.go 2023-03-07 18:54:32.000000000 +0100 @@ -117,15 +117,20 @@ { name: "javascript language", p: pkg.Package{ - Name: "name", - Version: "3.2", - FoundBy: "some-analyzer", - Language: pkg.JavaScript, - Type: pkg.DebPkg, + Name: "name", + Version: "3.2", + FoundBy: "some-analyzer", + Language: pkg.JavaScript, + MetadataType: pkg.NpmPackageJSONMetadataType, + Metadata: pkg.NpmPackageJSONMetadata{ + Author: "jon", + URL: "https://github.com/bob/npm-name", + }, }, expected: []string{ "cpe:2.3:a:name:name:3.2:*:*:*:*:*:*:*", - "cpe:2.3:a:*:name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:jon:name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:bob:name:3.2:*:*:*:*:*:*:*", }, }, { @@ -142,10 +147,10 @@ "someones name", "someones.elses.n...@gmail.com", }, + Homepage: "https://github.com/tom/ruby-name", }, }, expected: []string{ - "cpe:2.3:a:*:name:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:name:name:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:ruby-lang:name:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:ruby:name:3.2:*:*:*:*:*:*:*", @@ -154,6 +159,7 @@ "cpe:2.3:a:someones-name:name:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:someones_elses_name:name:3.2:*:*:*:*:*:*:*", "cpe:2.3:a:someones_name:name:3.2:*:*:*:*:*:*:*", + "cpe:2.3:a:tom:name:3.2:*:*:*:*:*:*:*", }, }, { @@ -641,7 +647,6 @@ }, }, expected: []string{ - "cpe:2.3:a:*:bundler:2.1.4:*:*:*:*:*:*:*", "cpe:2.3:a:bundler:bundler:2.1.4:*:*:*:*:*:*:*", "cpe:2.3:a:ruby-lang:bundler:2.1.4:*:*:*:*:*:*:*", "cpe:2.3:a:ruby:bundler:2.1.4:*:*:*:*:*:*:*", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/common/cpe/javascript.go new/syft-0.74.1/syft/pkg/cataloger/common/cpe/javascript.go --- old/syft-0.74.0/syft/pkg/cataloger/common/cpe/javascript.go 1970-01-01 01:00:00.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/common/cpe/javascript.go 2023-03-07 18:54:32.000000000 +0100 @@ -0,0 +1,32 @@ +package cpe + +import "github.com/anchore/syft/syft/pkg" + +func candidateVendorsForJavascript(p pkg.Package) fieldCandidateSet { + if p.MetadataType != pkg.NpmPackageJSONMetadataType { + return nil + } + + vendors := newFieldCandidateSet() + metadata, ok := p.Metadata.(pkg.NpmPackageJSONMetadata) + if !ok { + return nil + } + + if metadata.Author != "" { + vendors.add(fieldCandidate{ + value: normalizePersonName(stripEmailSuffix(metadata.Author)), + disallowSubSelections: true, + }) + } + + if metadata.URL != "" { + vendors.union(candidateVendorsFromURL(metadata.URL)) + } + + if metadata.Homepage != "" { + vendors.union(candidateVendorsFromURL(metadata.Homepage)) + } + + return vendors +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/common/cpe/ruby.go new/syft-0.74.1/syft/pkg/cataloger/common/cpe/ruby.go --- old/syft-0.74.0/syft/pkg/cataloger/common/cpe/ruby.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/common/cpe/ruby.go 2023-03-07 18:54:32.000000000 +0100 @@ -17,5 +17,10 @@ disallowSubSelections: true, }) } + + if metadata.Homepage != "" { + vendors.union(candidateVendorsFromURL(metadata.Homepage)) + } + return vendors } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/common/cpe/vendors_from_url.go new/syft-0.74.1/syft/pkg/cataloger/common/cpe/vendors_from_url.go --- old/syft-0.74.0/syft/pkg/cataloger/common/cpe/vendors_from_url.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/common/cpe/vendors_from_url.go 2023-03-07 18:54:32.000000000 +0100 @@ -21,7 +21,7 @@ } vendorExtractionPatterns = []*regexp.Regexp{ - regexp.MustCompile(`^https://(?:github|gitlab)\.com/(?P<vendor>[\w\-]*?)/.*$`), + regexp.MustCompile(`^(?:https|http|git)://(?:github|gitlab)\.com/(?P<vendor>[\w\-]*?)/.*$`), } ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/common/cpe/vendors_from_url_test.go new/syft-0.74.1/syft/pkg/cataloger/common/cpe/vendors_from_url_test.go --- old/syft-0.74.0/syft/pkg/cataloger/common/cpe/vendors_from_url_test.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/common/cpe/vendors_from_url_test.go 2023-03-07 18:54:32.000000000 +0100 @@ -52,6 +52,16 @@ url: "https://github.com/armadillo/abcxyz-12345/a/b/c/d/e/f/g", expected: []string{"armadillo"}, }, + { + name: "github username from git://", + url: "git://github.com/abc/xyz.git", + expected: []string{"abc"}, + }, + { + name: "github username from http://", + url: "http://github.com/abc/xyz.git", + expected: []string{"abc"}, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/dotnet/package.go new/syft-0.74.1/syft/pkg/cataloger/dotnet/package.go --- old/syft-0.74.0/syft/pkg/cataloger/dotnet/package.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/dotnet/package.go 2023-03-07 18:54:32.000000000 +0100 @@ -45,7 +45,17 @@ var qualifiers packageurl.Qualifiers return packageurl.NewPackageURL( - packageurl.TypeDotnet, + // This originally was packageurl.TypeDotnet, but this isn't a valid PURL type, according to: + // https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst + // Some history: + // https://github.com/anchore/packageurl-go/pull/8 added the type to Anchore's fork + // due to this PR: https://github.com/anchore/syft/pull/951 + // There were questions about "dotnet" being the right purlType at the time, but it was + // acknowledged that scanning a dotnet file does not necessarily mean the packages found + // are nuget packages and so the alternate type was added. Since this is still an invalid + // PURL type, however, we will use TypeNuget and revisit at such time there is a better + // official PURL type available. + packageurl.TypeNuget, "", m.Name, m.Version, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syft-0.74.0/syft/pkg/cataloger/dotnet/parse_dotnet_deps_test.go new/syft-0.74.1/syft/pkg/cataloger/dotnet/parse_dotnet_deps_test.go --- old/syft-0.74.0/syft/pkg/cataloger/dotnet/parse_dotnet_deps_test.go 2023-03-01 21:35:01.000000000 +0100 +++ new/syft-0.74.1/syft/pkg/cataloger/dotnet/parse_dotnet_deps_test.go 2023-03-07 18:54:32.000000000 +0100 @@ -16,7 +16,7 @@ { Name: "AWSSDK.Core", Version: "3.7.10.6", - PURL: "pkg:dotnet/AWSSDK.Core@3.7.10.6", + PURL: "pkg:nuget/AWSSDK.Core@3.7.10.6", Locations: fixtureLocationSet, Language: pkg.Dotnet, Type: pkg.DotnetPkg, @@ -32,7 +32,7 @@ { Name: "Microsoft.Extensions.DependencyInjection.Abstractions", Version: "6.0.0", - PURL: "pkg:dotnet/Microsoft.Extensions.DependencyInjection.Abstractions@6.0.0", + PURL: "pkg:nuget/Microsoft.Extensions.DependencyInjection.Abstractions@6.0.0", Locations: fixtureLocationSet, Language: pkg.Dotnet, Type: pkg.DotnetPkg, @@ -48,7 +48,7 @@ { Name: "Microsoft.Extensions.DependencyInjection", Version: "6.0.0", - PURL: "pkg:dotnet/Microsoft.Extensions.DependencyInjection@6.0.0", + PURL: "pkg:nuget/Microsoft.Extensions.DependencyInjection@6.0.0", Locations: fixtureLocationSet, Language: pkg.Dotnet, Type: pkg.DotnetPkg, @@ -64,7 +64,7 @@ { Name: "Microsoft.Extensions.Logging.Abstractions", Version: "6.0.0", - PURL: "pkg:dotnet/Microsoft.Extensions.Logging.Abstractions@6.0.0", + PURL: "pkg:nuget/Microsoft.Extensions.Logging.Abstractions@6.0.0", Locations: fixtureLocationSet, Language: pkg.Dotnet, Type: pkg.DotnetPkg, @@ -80,7 +80,7 @@ { Name: "Microsoft.Extensions.Logging", Version: "6.0.0", - PURL: "pkg:dotnet/Microsoft.Extensions.Logging@6.0.0", + PURL: "pkg:nuget/Microsoft.Extensions.Logging@6.0.0", Locations: fixtureLocationSet, Language: pkg.Dotnet, Type: pkg.DotnetPkg, @@ -97,7 +97,7 @@ { Name: "Microsoft.Extensions.Options", Version: "6.0.0", - PURL: "pkg:dotnet/Microsoft.Extensions.Options@6.0.0", + PURL: "pkg:nuget/Microsoft.Extensions.Options@6.0.0", Locations: fixtureLocationSet, Language: pkg.Dotnet, Type: pkg.DotnetPkg, @@ -113,7 +113,7 @@ { Name: "Microsoft.Extensions.Primitives", Version: "6.0.0", - PURL: "pkg:dotnet/Microsoft.Extensions.Primitives@6.0.0", + PURL: "pkg:nuget/Microsoft.Extensions.Primitives@6.0.0", Locations: fixtureLocationSet, Language: pkg.Dotnet, Type: pkg.DotnetPkg, @@ -129,7 +129,7 @@ { Name: "Newtonsoft.Json", Version: "13.0.1", - PURL: "pkg:dotnet/Newtonsoft.Json@13.0.1", + PURL: "pkg:nuget/Newtonsoft.Json@13.0.1", Locations: fixtureLocationSet, Language: pkg.Dotnet, Type: pkg.DotnetPkg, @@ -145,7 +145,7 @@ { Name: "Serilog.Sinks.Console", Version: "4.0.1", - PURL: "pkg:dotnet/Serilog.Sinks.Console@4.0.1", + PURL: "pkg:nuget/Serilog.Sinks.Console@4.0.1", Locations: fixtureLocationSet, Language: pkg.Dotnet, Type: pkg.DotnetPkg, @@ -161,7 +161,7 @@ { Name: "Serilog", Version: "2.10.0", - PURL: "pkg:dotnet/Serilog@2.10.0", + PURL: "pkg:nuget/Serilog@2.10.0", Locations: fixtureLocationSet, Language: pkg.Dotnet, Type: pkg.DotnetPkg, @@ -177,7 +177,7 @@ { Name: "System.Diagnostics.DiagnosticSource", Version: "6.0.0", - PURL: "pkg:dotnet/System.Diagnostics.DiagnosticSource@6.0.0", + PURL: "pkg:nuget/System.Diagnostics.DiagnosticSource@6.0.0", Locations: fixtureLocationSet, Language: pkg.Dotnet, Type: pkg.DotnetPkg, @@ -193,7 +193,7 @@ { Name: "System.Runtime.CompilerServices.Unsafe", Version: "6.0.0", - PURL: "pkg:dotnet/System.Runtime.CompilerServices.Unsafe@6.0.0", + PURL: "pkg:nuget/System.Runtime.CompilerServices.Unsafe@6.0.0", Locations: fixtureLocationSet, Language: pkg.Dotnet, Type: pkg.DotnetPkg, ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/syft/vendor.tar.gz /work/SRC/openSUSE:Factory/.syft.new.31432/vendor.tar.gz differ: char 5, line 1