mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01:00
fix: remove APK OriginPackage cpe candidates (#1637)
Adding APK OriginPackage CPE candidates to the child package results in false positives in grype because it can't associate CPE-based findings to the corresponding OriginPackage APK fixes. This reverts changing the `upstream` in the PURL for APK packages as the logic in Grype that uses it expects it to be an APK package name. This also allows refactoring to unexport and move the APK CPE candidate generation logic closer to where CPE generation occurs Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
This commit is contained in:
parent
2e6e3b0c74
commit
e2ebc9769f
@ -4,27 +4,18 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/scylladb/go-set/strset"
|
||||
|
||||
"github.com/anchore/syft/internal"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
)
|
||||
|
||||
const ApkDBGlob = "**/lib/apk/db/installed"
|
||||
|
||||
var (
|
||||
_ FileOwner = (*ApkMetadata)(nil)
|
||||
prefixesToPackageType = map[string]Type{
|
||||
"py-": PythonPkg,
|
||||
"ruby-": GemPkg,
|
||||
}
|
||||
streamVersionPkgNamePattern = regexp.MustCompile(`^(?P<stream>[a-zA-Z][\w-]*?)(?P<streamVersion>\-?\d[\d\.]*?)($|-(?P<subPackage>[a-zA-Z][\w-]*?)?)$`)
|
||||
)
|
||||
var _ FileOwner = (*ApkMetadata)(nil)
|
||||
|
||||
// ApkMetadata represents all captured data for a Alpine DB package entry.
|
||||
// See the following sources for more information:
|
||||
@ -123,45 +114,3 @@ func (m ApkMetadata) OwnedFiles() (result []string) {
|
||||
sort.Strings(result)
|
||||
return result
|
||||
}
|
||||
|
||||
type UpstreamCandidate struct {
|
||||
Name string
|
||||
Type Type
|
||||
}
|
||||
|
||||
func (m ApkMetadata) UpstreamCandidates() (candidates []UpstreamCandidate) {
|
||||
name := m.Package
|
||||
if m.OriginPackage != "" && m.OriginPackage != m.Package {
|
||||
candidates = append(candidates, UpstreamCandidate{Name: m.OriginPackage, Type: ApkPkg})
|
||||
}
|
||||
|
||||
groups := internal.MatchNamedCaptureGroups(streamVersionPkgNamePattern, m.Package)
|
||||
stream, ok := groups["stream"]
|
||||
|
||||
if ok && stream != "" {
|
||||
sub, ok := groups["subPackage"]
|
||||
|
||||
if ok && sub != "" {
|
||||
name = fmt.Sprintf("%s-%s", stream, sub)
|
||||
} else {
|
||||
name = stream
|
||||
}
|
||||
}
|
||||
|
||||
for prefix, typ := range prefixesToPackageType {
|
||||
if strings.HasPrefix(name, prefix) {
|
||||
t := strings.TrimPrefix(name, prefix)
|
||||
if t != "" {
|
||||
candidates = append(candidates, UpstreamCandidate{Name: t, Type: typ})
|
||||
return candidates
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if name != "" {
|
||||
candidates = append(candidates, UpstreamCandidate{Name: name, Type: UnknownPkg})
|
||||
return candidates
|
||||
}
|
||||
|
||||
return candidates
|
||||
}
|
||||
|
||||
@ -163,245 +163,3 @@ func TestSpaceDelimitedStringSlice_UnmarshalJSON(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestApkMetadata_UpstreamCandidates(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
metadata ApkMetadata
|
||||
expected []UpstreamCandidate
|
||||
}{
|
||||
{
|
||||
name: "gocase",
|
||||
metadata: ApkMetadata{
|
||||
Package: "p",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "p", Type: UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "same package and origin simple case",
|
||||
metadata: ApkMetadata{
|
||||
Package: "p",
|
||||
OriginPackage: "p",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "p", Type: UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "different package and origin",
|
||||
metadata: ApkMetadata{
|
||||
Package: "p",
|
||||
OriginPackage: "origin",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "origin", Type: ApkPkg},
|
||||
{Name: "p", Type: UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "upstream python package information as qualifier py- prefix",
|
||||
metadata: ApkMetadata{
|
||||
Package: "py-potatoes",
|
||||
OriginPackage: "py-potatoes",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "potatoes", Type: PythonPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "upstream python package information as qualifier py3- prefix",
|
||||
metadata: ApkMetadata{
|
||||
Package: "py3-potatoes",
|
||||
OriginPackage: "py3-potatoes",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "potatoes", Type: PythonPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "python package with distinct origin package",
|
||||
metadata: ApkMetadata{
|
||||
Package: "py3-non-existant",
|
||||
OriginPackage: "abcdefg",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "abcdefg", Type: ApkPkg},
|
||||
{Name: "non-existant", Type: PythonPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "upstream ruby package information as qualifier",
|
||||
metadata: ApkMetadata{
|
||||
Package: "ruby-something",
|
||||
OriginPackage: "ruby-something",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "something", Type: GemPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ruby package with distinct origin package",
|
||||
metadata: ApkMetadata{
|
||||
Package: "ruby-something",
|
||||
OriginPackage: "1234567",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "1234567", Type: ApkPkg},
|
||||
{Name: "something", Type: GemPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "postgesql-15 upstream postgresql",
|
||||
metadata: ApkMetadata{
|
||||
Package: "postgresql-15",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "postgresql", Type: UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "postgesql15 upstream postgresql",
|
||||
metadata: ApkMetadata{
|
||||
Package: "postgresql15",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "postgresql", Type: UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "go-1.19 upstream go",
|
||||
metadata: ApkMetadata{
|
||||
Package: "go-1.19",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "go", Type: UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "go1.143 upstream go",
|
||||
metadata: ApkMetadata{
|
||||
Package: "go1.143",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "go", Type: UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "abc-101.191.23456 upstream abc",
|
||||
metadata: ApkMetadata{
|
||||
Package: "abc-101.191.23456",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "abc", Type: UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "abc101.191.23456 upstream abc",
|
||||
metadata: ApkMetadata{
|
||||
Package: "abc101.191.23456",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "abc", Type: UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "abc101-12345-1045 upstream abc101-12345",
|
||||
metadata: ApkMetadata{
|
||||
Package: "abc101-12345-1045",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "abc101-12345", Type: UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "abc101-a12345-1045 upstream abc101-a12345",
|
||||
metadata: ApkMetadata{
|
||||
Package: "abc101-a12345-1045",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "abc-a12345-1045", Type: UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "package starting with single digit",
|
||||
metadata: ApkMetadata{
|
||||
Package: "3proxy",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "3proxy", Type: UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "package starting with multiple digits",
|
||||
metadata: ApkMetadata{
|
||||
Package: "356proxy",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "356proxy", Type: UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "package composed of only digits",
|
||||
metadata: ApkMetadata{
|
||||
Package: "123456",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "123456", Type: UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ruby-3.6 upstream ruby",
|
||||
metadata: ApkMetadata{
|
||||
Package: "ruby-3.6",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "ruby", Type: UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ruby3.6 upstream ruby",
|
||||
metadata: ApkMetadata{
|
||||
Package: "ruby3.6",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "ruby", Type: UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ruby3.6-tacos upstream tacos",
|
||||
metadata: ApkMetadata{
|
||||
Package: "ruby3.6-tacos",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "tacos", Type: GemPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ruby-3.6-tacos upstream tacos",
|
||||
metadata: ApkMetadata{
|
||||
Package: "ruby-3.6-tacos",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "tacos", Type: GemPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "abc1234jksajflksa",
|
||||
metadata: ApkMetadata{
|
||||
Package: "abc1234jksajflksa",
|
||||
},
|
||||
expected: []UpstreamCandidate{
|
||||
{Name: "abc1234jksajflksa", Type: UnknownPkg},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
actual := test.metadata.UpstreamCandidates()
|
||||
assert.Equal(t, test.expected, actual)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,14 +36,8 @@ func packageURL(m pkg.ApkMetadata, distro *linux.Release) string {
|
||||
pkg.PURLQualifierArch: m.Architecture,
|
||||
}
|
||||
|
||||
upstreams := m.UpstreamCandidates()
|
||||
if len(upstreams) > 0 {
|
||||
// only room for one value so for now just take the first one
|
||||
upstream := upstreams[0]
|
||||
|
||||
if upstream.Name != "" && upstream.Name != m.Package {
|
||||
qualifiers[pkg.PURLQualifierUpstream] = upstream.Name
|
||||
}
|
||||
if m.OriginPackage != m.Package {
|
||||
qualifiers[pkg.PURLQualifierUpstream] = m.OriginPackage
|
||||
}
|
||||
|
||||
return packageurl.NewPackageURL(
|
||||
|
||||
@ -96,146 +96,6 @@ func Test_PackageURL(t *testing.T) {
|
||||
},
|
||||
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",
|
||||
},
|
||||
{
|
||||
name: "postgesql-15 upstream postgresql",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "postgresql-15",
|
||||
Version: "15.0",
|
||||
Architecture: "a",
|
||||
OriginPackage: "postgresql-15",
|
||||
},
|
||||
distro: linux.Release{
|
||||
ID: "alpine",
|
||||
VersionID: "3.4.6",
|
||||
},
|
||||
expected: "pkg:apk/alpine/postgresql-15@15.0?arch=a&upstream=postgresql&distro=alpine-3.4.6",
|
||||
},
|
||||
{
|
||||
name: "postgesql15 upstream postgresql",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "postgresql15",
|
||||
Version: "15.0",
|
||||
Architecture: "a",
|
||||
OriginPackage: "postgresql15",
|
||||
},
|
||||
distro: linux.Release{
|
||||
ID: "alpine",
|
||||
VersionID: "3.4.6",
|
||||
},
|
||||
expected: "pkg:apk/alpine/postgresql15@15.0?arch=a&upstream=postgresql&distro=alpine-3.4.6",
|
||||
},
|
||||
{
|
||||
name: "go-1.19 upstream go",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "go-1.19",
|
||||
Version: "1.19",
|
||||
Architecture: "a",
|
||||
OriginPackage: "go-1.19",
|
||||
},
|
||||
distro: linux.Release{
|
||||
ID: "alpine",
|
||||
VersionID: "3.4.6",
|
||||
},
|
||||
expected: "pkg:apk/alpine/go-1.19@1.19?arch=a&upstream=go&distro=alpine-3.4.6",
|
||||
},
|
||||
{
|
||||
name: "go1.19 upstream go",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "go1.19",
|
||||
Version: "1.19",
|
||||
Architecture: "a",
|
||||
OriginPackage: "go1.19",
|
||||
},
|
||||
distro: linux.Release{
|
||||
ID: "alpine",
|
||||
VersionID: "3.4.6",
|
||||
},
|
||||
expected: "pkg:apk/alpine/go1.19@1.19?arch=a&upstream=go&distro=alpine-3.4.6",
|
||||
},
|
||||
{
|
||||
name: "abc-101.191.23456 upstream abc",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "abc-101.191.23456",
|
||||
Version: "101.191.23456",
|
||||
Architecture: "a",
|
||||
OriginPackage: "abc-101.191.23456",
|
||||
},
|
||||
distro: linux.Release{
|
||||
ID: "alpine",
|
||||
VersionID: "3.4.6",
|
||||
},
|
||||
expected: "pkg:apk/alpine/abc-101.191.23456@101.191.23456?arch=a&upstream=abc&distro=alpine-3.4.6",
|
||||
},
|
||||
{
|
||||
name: "abc101.191.23456 upstream abc",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "abc101.191.23456",
|
||||
Version: "101.191.23456",
|
||||
Architecture: "a",
|
||||
OriginPackage: "abc101.191.23456",
|
||||
},
|
||||
distro: linux.Release{
|
||||
ID: "alpine",
|
||||
VersionID: "3.4.6",
|
||||
},
|
||||
expected: "pkg:apk/alpine/abc101.191.23456@101.191.23456?arch=a&upstream=abc&distro=alpine-3.4.6",
|
||||
},
|
||||
{
|
||||
name: "abc101-12345-1045 upstream abc101-12345",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "abc101-12345-1045",
|
||||
Version: "101.191.23456",
|
||||
Architecture: "a",
|
||||
OriginPackage: "abc101-12345-1045",
|
||||
},
|
||||
distro: linux.Release{
|
||||
ID: "alpine",
|
||||
VersionID: "3.4.6",
|
||||
},
|
||||
expected: "pkg:apk/alpine/abc101-12345-1045@101.191.23456?arch=a&upstream=abc101-12345&distro=alpine-3.4.6",
|
||||
},
|
||||
{
|
||||
name: "abc101-a12345-1045 upstream abc101-a12345",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "abc101-a12345-1045",
|
||||
Version: "101.191.23456",
|
||||
Architecture: "a",
|
||||
OriginPackage: "abc101-a12345-1045",
|
||||
},
|
||||
distro: linux.Release{
|
||||
ID: "alpine",
|
||||
VersionID: "3.4.6",
|
||||
},
|
||||
expected: "pkg:apk/alpine/abc101-a12345-1045@101.191.23456?arch=a&upstream=abc-a12345-1045&distro=alpine-3.4.6",
|
||||
},
|
||||
{
|
||||
name: "wolfi distro",
|
||||
metadata: pkg.ApkMetadata{
|
||||
|
||||
@ -1,9 +1,64 @@
|
||||
package cpe
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/anchore/syft/internal"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
var (
|
||||
prefixesToPackageType = map[string]pkg.Type{
|
||||
"py-": pkg.PythonPkg,
|
||||
"ruby-": pkg.GemPkg,
|
||||
}
|
||||
streamVersionPkgNamePattern = regexp.MustCompile(`^(?P<stream>[a-zA-Z][\w-]*?)(?P<streamVersion>\-?\d[\d\.]*?)($|-(?P<subPackage>[a-zA-Z][\w-]*?)?)$`)
|
||||
)
|
||||
|
||||
type upstreamCandidate struct {
|
||||
Name string
|
||||
Type pkg.Type
|
||||
}
|
||||
|
||||
func upstreamCandidates(m pkg.ApkMetadata) (candidates []upstreamCandidate) {
|
||||
// Do not consider OriginPackage variations when generating CPE candidates for the child package
|
||||
// because doing so will result in false positives when matching to vulnerabilities in Grype since
|
||||
// it won't know to lookup apk fix entries using the OriginPackage name.
|
||||
|
||||
name := m.Package
|
||||
groups := internal.MatchNamedCaptureGroups(streamVersionPkgNamePattern, m.Package)
|
||||
stream, ok := groups["stream"]
|
||||
|
||||
if ok && stream != "" {
|
||||
sub, ok := groups["subPackage"]
|
||||
|
||||
if ok && sub != "" {
|
||||
name = fmt.Sprintf("%s-%s", stream, sub)
|
||||
} else {
|
||||
name = stream
|
||||
}
|
||||
}
|
||||
|
||||
for prefix, typ := range prefixesToPackageType {
|
||||
if strings.HasPrefix(name, prefix) {
|
||||
t := strings.TrimPrefix(name, prefix)
|
||||
if t != "" {
|
||||
candidates = append(candidates, upstreamCandidate{Name: t, Type: typ})
|
||||
return candidates
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if name != "" {
|
||||
candidates = append(candidates, upstreamCandidate{Name: name, Type: pkg.UnknownPkg})
|
||||
return candidates
|
||||
}
|
||||
|
||||
return candidates
|
||||
}
|
||||
|
||||
func candidateVendorsForAPK(p pkg.Package) fieldCandidateSet {
|
||||
metadata, ok := p.Metadata.(pkg.ApkMetadata)
|
||||
if !ok {
|
||||
@ -11,7 +66,7 @@ func candidateVendorsForAPK(p pkg.Package) fieldCandidateSet {
|
||||
}
|
||||
|
||||
vendors := newFieldCandidateSet()
|
||||
candidates := metadata.UpstreamCandidates()
|
||||
candidates := upstreamCandidates(metadata)
|
||||
|
||||
for _, c := range candidates {
|
||||
switch c.Type {
|
||||
@ -52,7 +107,7 @@ func candidateProductsForAPK(p pkg.Package) fieldCandidateSet {
|
||||
}
|
||||
|
||||
products := newFieldCandidateSet()
|
||||
candidates := metadata.UpstreamCandidates()
|
||||
candidates := upstreamCandidates(metadata)
|
||||
|
||||
for _, c := range candidates {
|
||||
switch c.Type {
|
||||
|
||||
@ -31,7 +31,7 @@ func Test_candidateVendorsForAPK(t *testing.T) {
|
||||
OriginPackage: "abcdefg",
|
||||
},
|
||||
},
|
||||
expected: []string{"pypdf", "pypdfproject", "pypdf_project", "abcdefg"},
|
||||
expected: []string{"pypdf", "pypdfproject", "pypdf_project"},
|
||||
},
|
||||
{
|
||||
name: "ruby-armadillo Package",
|
||||
@ -97,7 +97,7 @@ func Test_candidateVendorsForAPK(t *testing.T) {
|
||||
OriginPackage: "ruby",
|
||||
},
|
||||
},
|
||||
expected: []string{"rake", "ruby-lang", "ruby"},
|
||||
expected: []string{"rake", "ruby-lang"},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
@ -130,7 +130,7 @@ func Test_candidateProductsForAPK(t *testing.T) {
|
||||
OriginPackage: "abcdefg",
|
||||
},
|
||||
},
|
||||
expected: []string{"pypdf", "abcdefg"},
|
||||
expected: []string{"pypdf"},
|
||||
},
|
||||
{
|
||||
name: "ruby-armadillo Package",
|
||||
@ -193,7 +193,7 @@ func Test_candidateProductsForAPK(t *testing.T) {
|
||||
OriginPackage: "ruby",
|
||||
},
|
||||
},
|
||||
expected: []string{"rake", "ruby"},
|
||||
expected: []string{"rake"},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
@ -202,3 +202,242 @@ func Test_candidateProductsForAPK(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_upstreamCandidates(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
metadata pkg.ApkMetadata
|
||||
expected []upstreamCandidate
|
||||
}{
|
||||
{
|
||||
name: "gocase",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "p",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "p", Type: pkg.UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "same package and origin simple case",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "p",
|
||||
OriginPackage: "p",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "p", Type: pkg.UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "different package and origin",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "p",
|
||||
OriginPackage: "origin",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "p", Type: pkg.UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "upstream python package information as qualifier py- prefix",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "py-potatoes",
|
||||
OriginPackage: "py-potatoes",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "potatoes", Type: pkg.PythonPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "upstream python package information as qualifier py3- prefix",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "py3-potatoes",
|
||||
OriginPackage: "py3-potatoes",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "potatoes", Type: pkg.PythonPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "python package with distinct origin package",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "py3-non-existant",
|
||||
OriginPackage: "abcdefg",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "non-existant", Type: pkg.PythonPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "upstream ruby package information as qualifier",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "ruby-something",
|
||||
OriginPackage: "ruby-something",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "something", Type: pkg.GemPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ruby package with distinct origin package",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "ruby-something",
|
||||
OriginPackage: "1234567",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "something", Type: pkg.GemPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "postgesql-15 upstream postgresql",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "postgresql-15",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "postgresql", Type: pkg.UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "postgesql15 upstream postgresql",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "postgresql15",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "postgresql", Type: pkg.UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "go-1.19 upstream go",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "go-1.19",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "go", Type: pkg.UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "go1.143 upstream go",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "go1.143",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "go", Type: pkg.UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "abc-101.191.23456 upstream abc",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "abc-101.191.23456",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "abc", Type: pkg.UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "abc101.191.23456 upstream abc",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "abc101.191.23456",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "abc", Type: pkg.UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "abc101-12345-1045 upstream abc101-12345",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "abc101-12345-1045",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "abc101-12345", Type: pkg.UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "abc101-a12345-1045 upstream abc101-a12345",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "abc101-a12345-1045",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "abc-a12345-1045", Type: pkg.UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "package starting with single digit",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "3proxy",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "3proxy", Type: pkg.UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "package starting with multiple digits",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "356proxy",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "356proxy", Type: pkg.UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "package composed of only digits",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "123456",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "123456", Type: pkg.UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ruby-3.6 upstream ruby",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "ruby-3.6",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "ruby", Type: pkg.UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ruby3.6 upstream ruby",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "ruby3.6",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "ruby", Type: pkg.UnknownPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ruby3.6-tacos upstream tacos",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "ruby3.6-tacos",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "tacos", Type: pkg.GemPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ruby-3.6-tacos upstream tacos",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "ruby-3.6-tacos",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "tacos", Type: pkg.GemPkg},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "abc1234jksajflksa",
|
||||
metadata: pkg.ApkMetadata{
|
||||
Package: "abc1234jksajflksa",
|
||||
},
|
||||
expected: []upstreamCandidate{
|
||||
{Name: "abc1234jksajflksa", Type: pkg.UnknownPkg},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
actual := upstreamCandidates(test.metadata)
|
||||
assert.Equal(t, test.expected, actual)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -707,12 +707,6 @@ func TestGeneratePackageCPEs(t *testing.T) {
|
||||
"cpe:2.3:a:ruby_rake:rake:2.7.6-r0:*:*:*:*:*:*:*",
|
||||
"cpe:2.3:a:ruby_rake:ruby-rake:2.7.6-r0:*:*:*:*:*:*:*",
|
||||
"cpe:2.3:a:ruby_rake:ruby_rake:2.7.6-r0:*:*:*:*:*:*:*",
|
||||
"cpe:2.3:a:rake:ruby:2.7.6-r0:*:*:*:*:*:*:*",
|
||||
"cpe:2.3:a:ruby-lang:ruby:2.7.6-r0:*:*:*:*:*:*:*",
|
||||
"cpe:2.3:a:ruby-rake:ruby:2.7.6-r0:*:*:*:*:*:*:*",
|
||||
"cpe:2.3:a:ruby:ruby:2.7.6-r0:*:*:*:*:*:*:*",
|
||||
"cpe:2.3:a:ruby_lang:ruby:2.7.6-r0:*:*:*:*:*:*:*",
|
||||
"cpe:2.3:a:ruby_rake:ruby:2.7.6-r0:*:*:*:*:*:*:*",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user