diff --git a/cmd/packages.go b/cmd/packages.go index fa60d363bf9..931640ba06d 100644 --- a/cmd/packages.go +++ b/cmd/packages.go @@ -35,7 +35,7 @@ const ( Supports the following image sources: {{.appName}} {{.command}} yourrepo/yourimage:tag defaults to using images from a Docker daemon. If Docker is not present, the image is pulled directly from the registry. - {{.appName}} {{.command}} path/to/a/file/or/dir a Docker tar, OCI tar, OCI directory, or generic filesystem directory + {{.appName}} {{.command}} path/to/a/file/or/dir a Docker tar, OCI tar, OCI directory, or generic filesystem directory You can also explicitly specify the scheme to use: {{.appName}} {{.command}} docker:yourrepo/yourimage:tag explicitly use the Docker daemon diff --git a/syft/pkg/cataloger/common/cpe/sort_by_specificity.go b/syft/pkg/cataloger/common/cpe/sort_by_specificity.go index bcb3cd3b5f5..03b1a741e01 100644 --- a/syft/pkg/cataloger/common/cpe/sort_by_specificity.go +++ b/syft/pkg/cataloger/common/cpe/sort_by_specificity.go @@ -18,10 +18,18 @@ func (c BySpecificity) Less(i, j int) bool { iScore := weightedCountForSpecifiedFields(c[i]) jScore := weightedCountForSpecifiedFields(c[j]) - if iScore == jScore { + // check weighted sort first + if iScore != jScore { + return iScore > jScore + } + + // sort longer fields to top + if countFieldLength(c[i]) != countFieldLength(c[j]) { return countFieldLength(c[i]) > countFieldLength(c[j]) } - return iScore > jScore + + // if score and length are equal then text sort + return c[i].BindToFmtString() < c[j].BindToFmtString() } func countFieldLength(cpe wfn.Attributes) int { diff --git a/syft/pkg/cataloger/common/cpe/sort_by_specificity_test.go b/syft/pkg/cataloger/common/cpe/sort_by_specificity_test.go index 4d0d300bb27..f979bd8fbda 100644 --- a/syft/pkg/cataloger/common/cpe/sort_by_specificity_test.go +++ b/syft/pkg/cataloger/common/cpe/sort_by_specificity_test.go @@ -80,6 +80,25 @@ func TestCPESpecificity(t *testing.T) { mustCPE("cpe:2.3:a:1:*:333:*:*:*:*:*:*:*"), }, }, + { + name: "sort by mix of field length, specificity, dash", + input: []pkg.CPE{ + mustCPE("cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine_keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine-keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine:alpine-keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine-keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine_keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"), + }, + expected: []pkg.CPE{ + mustCPE("cpe:2.3:a:alpine-keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine-keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine_keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine_keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine:alpine-keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*"), + }, + }, } for _, test := range tests {