github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/syft/pkg/cataloger/common/cpe/apk.go (about) 1 package cpe 2 3 import ( 4 "fmt" 5 "regexp" 6 "strings" 7 8 "github.com/anchore/syft/internal" 9 "github.com/anchore/syft/syft/pkg" 10 ) 11 12 var ( 13 prefixesToPackageType = map[string]pkg.Type{ 14 "py-": pkg.PythonPkg, 15 "ruby-": pkg.GemPkg, 16 } 17 streamVersionPkgNamePattern = regexp.MustCompile(`^(?P<stream>[a-zA-Z][\w-]*?)(?P<streamVersion>\-?\d[\d\.]*?)($|-(?P<subPackage>[a-zA-Z][\w-]*?)?)$`) 18 ) 19 20 type upstreamCandidate struct { 21 Name string 22 Type pkg.Type 23 } 24 25 func upstreamCandidates(m pkg.ApkMetadata) (candidates []upstreamCandidate) { 26 // Do not consider OriginPackage variations when generating CPE candidates for the child package 27 // because doing so will result in false positives when matching to vulnerabilities in Grype since 28 // it won't know to lookup apk fix entries using the OriginPackage name. 29 30 name := m.Package 31 groups := internal.MatchNamedCaptureGroups(streamVersionPkgNamePattern, m.Package) 32 stream, ok := groups["stream"] 33 34 if ok && stream != "" { 35 sub, ok := groups["subPackage"] 36 37 if ok && sub != "" { 38 name = fmt.Sprintf("%s-%s", stream, sub) 39 } else { 40 name = stream 41 } 42 } 43 44 for prefix, typ := range prefixesToPackageType { 45 if strings.HasPrefix(name, prefix) { 46 t := strings.TrimPrefix(name, prefix) 47 if t != "" { 48 candidates = append(candidates, upstreamCandidate{Name: t, Type: typ}) 49 return candidates 50 } 51 } 52 } 53 54 if name != "" { 55 candidates = append(candidates, upstreamCandidate{Name: name, Type: pkg.UnknownPkg}) 56 return candidates 57 } 58 59 return candidates 60 } 61 62 func candidateVendorsForAPK(p pkg.Package) fieldCandidateSet { 63 metadata, ok := p.Metadata.(pkg.ApkMetadata) 64 if !ok { 65 return nil 66 } 67 68 vendors := newFieldCandidateSet() 69 candidates := upstreamCandidates(metadata) 70 71 for _, c := range candidates { 72 switch c.Type { 73 case pkg.UnknownPkg: 74 vendors.addValue(c.Name) 75 vendors.addValue(findAdditionalVendors(defaultCandidateAdditions, pkg.ApkPkg, c.Name, c.Name)...) 76 vendors.removeByValue(findVendorsToRemove(defaultCandidateRemovals, pkg.ApkPkg, c.Name)...) 77 case pkg.PythonPkg: 78 vendors.addValue(c.Name) 79 vendors.addValue(findAdditionalVendors(defaultCandidateAdditions, c.Type, c.Name, c.Name)...) 80 vendors.removeByValue(findVendorsToRemove(defaultCandidateRemovals, c.Type, c.Name)...) 81 for _, av := range additionalVendorsForPython(c.Name) { 82 vendors.addValue(av) 83 vendors.addValue(findAdditionalVendors(defaultCandidateAdditions, pkg.PythonPkg, av, av)...) 84 vendors.removeByValue(findVendorsToRemove(defaultCandidateRemovals, pkg.PythonPkg, av)...) 85 } 86 default: 87 vendors.addValue(c.Name) 88 vendors.addValue(findAdditionalVendors(defaultCandidateAdditions, c.Type, c.Name, c.Name)...) 89 vendors.removeByValue(findVendorsToRemove(defaultCandidateRemovals, c.Type, c.Name)...) 90 } 91 } 92 93 vendors.union(candidateVendorsFromURL(metadata.URL)) 94 95 for v := range vendors { 96 v.disallowDelimiterVariations = true 97 v.disallowSubSelections = true 98 } 99 100 return vendors 101 } 102 103 func candidateProductsForAPK(p pkg.Package) fieldCandidateSet { 104 metadata, ok := p.Metadata.(pkg.ApkMetadata) 105 if !ok { 106 return nil 107 } 108 109 products := newFieldCandidateSet() 110 candidates := upstreamCandidates(metadata) 111 112 for _, c := range candidates { 113 switch c.Type { 114 case pkg.UnknownPkg: 115 products.addValue(c.Name) 116 products.addValue(findAdditionalProducts(defaultCandidateAdditions, pkg.ApkPkg, c.Name)...) 117 products.removeByValue(findProductsToRemove(defaultCandidateRemovals, pkg.ApkPkg, c.Name)...) 118 default: 119 products.addValue(c.Name) 120 products.addValue(findAdditionalProducts(defaultCandidateAdditions, c.Type, c.Name)...) 121 products.removeByValue(findProductsToRemove(defaultCandidateRemovals, c.Type, c.Name)...) 122 } 123 } 124 125 for p := range products { 126 p.disallowDelimiterVariations = true 127 p.disallowSubSelections = true 128 } 129 130 return products 131 }