Skip to content

Commit

Permalink
fix: remove APK OriginPackage cpe candidates (#1637)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
westonsteimel authored Mar 1, 2023
1 parent 2e6e3b0 commit e2ebc97
Show file tree
Hide file tree
Showing 7 changed files with 303 additions and 454 deletions.
53 changes: 1 addition & 52 deletions syft/pkg/apk_metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
}
242 changes: 0 additions & 242 deletions syft/pkg/apk_metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})
}
}
10 changes: 2 additions & 8 deletions syft/pkg/cataloger/apkdb/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Loading

0 comments on commit e2ebc97

Please sign in to comment.