mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01:00
Fix: Include version information in binary cataloger CPEs (#1310)
This commit is contained in:
parent
10464642e9
commit
3e99c4d7d8
@ -7,6 +7,7 @@ import (
|
||||
"regexp"
|
||||
|
||||
"github.com/anchore/syft/internal"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
@ -22,10 +23,10 @@ type Classifier struct {
|
||||
// source location. If any of the patterns match, the file will be considered a candidate for parsing.
|
||||
// If no patterns are provided, the reader is automatically considered a candidate.
|
||||
FilepathPatterns []*regexp.Regexp
|
||||
// EvidencePattern is a list of regular expressions that will be used to match against the file contents of a
|
||||
// EvidencePatterns is a list of regular expressions that will be used to match against the file contents of a
|
||||
// given file in the source location. If any of the patterns match, the file will be considered a candidate for parsing.
|
||||
EvidencePatterns []*regexp.Regexp
|
||||
// CPE is the CPE we want to match against
|
||||
// CPEs are the specific CPEs we want to include for this binary with updated version information
|
||||
CPEs []pkg.CPE
|
||||
}
|
||||
|
||||
@ -45,20 +46,33 @@ func (c Classifier) Examine(reader source.LocationReadCloser) (p *pkg.Package, r
|
||||
}
|
||||
|
||||
var classifiedPackage *pkg.Package
|
||||
for _, patternTemplate := range c.EvidencePatterns {
|
||||
if !patternTemplate.Match(contents) {
|
||||
for _, evidencePattern := range c.EvidencePatterns {
|
||||
if !evidencePattern.Match(contents) {
|
||||
continue
|
||||
}
|
||||
|
||||
matchMetadata := internal.MatchNamedCaptureGroups(patternTemplate, string(contents))
|
||||
if classifiedPackage == nil {
|
||||
matchMetadata := internal.MatchNamedCaptureGroups(evidencePattern, string(contents))
|
||||
version, ok := matchMetadata["version"]
|
||||
if !ok {
|
||||
log.Debugf("no version found in binary from pattern %v", evidencePattern)
|
||||
continue
|
||||
}
|
||||
|
||||
var cpes []pkg.CPE
|
||||
for _, cpe := range c.CPEs {
|
||||
cpe.Version = version
|
||||
if err == nil {
|
||||
cpes = append(cpes, cpe)
|
||||
}
|
||||
}
|
||||
|
||||
classifiedPackage = &pkg.Package{
|
||||
Name: path.Base(reader.VirtualPath),
|
||||
Version: matchMetadata["version"],
|
||||
Version: version,
|
||||
Language: pkg.Binary,
|
||||
Locations: source.NewLocationSet(reader.Location),
|
||||
Type: pkg.BinaryPkg,
|
||||
CPEs: c.CPEs,
|
||||
CPEs: cpes,
|
||||
MetadataType: pkg.BinaryMetadataType,
|
||||
Metadata: pkg.BinaryMetadata{
|
||||
Classifier: c.Package,
|
||||
@ -68,7 +82,6 @@ func (c Classifier) Examine(reader source.LocationReadCloser) (p *pkg.Package, r
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return classifiedPackage, nil, nil
|
||||
}
|
||||
|
||||
|
||||
96
syft/pkg/cataloger/generic/classifier_test.go
Normal file
96
syft/pkg/cataloger/generic/classifier_test.go
Normal file
@ -0,0 +1,96 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
func Test_ClassifierCPEs(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
fixture string
|
||||
classifier Classifier
|
||||
cpes []string
|
||||
}{
|
||||
{
|
||||
name: "no CPEs",
|
||||
fixture: "test-fixtures/version.txt",
|
||||
classifier: Classifier{
|
||||
Package: "some-app",
|
||||
FilepathPatterns: []*regexp.Regexp{
|
||||
regexp.MustCompile(".*/version.txt"),
|
||||
},
|
||||
EvidencePatterns: []*regexp.Regexp{
|
||||
regexp.MustCompile(`(?m)my-verison:(?P<version>[0-9.]+)`),
|
||||
},
|
||||
CPEs: []pkg.CPE{},
|
||||
},
|
||||
cpes: nil,
|
||||
},
|
||||
{
|
||||
name: "one CPE",
|
||||
fixture: "test-fixtures/version.txt",
|
||||
classifier: Classifier{
|
||||
Package: "some-app",
|
||||
FilepathPatterns: []*regexp.Regexp{
|
||||
regexp.MustCompile(".*/version.txt"),
|
||||
},
|
||||
EvidencePatterns: []*regexp.Regexp{
|
||||
regexp.MustCompile(`(?m)my-verison:(?P<version>[0-9.]+)`),
|
||||
},
|
||||
CPEs: []pkg.CPE{
|
||||
pkg.MustCPE("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*"),
|
||||
},
|
||||
},
|
||||
cpes: []string{
|
||||
"cpe:2.3:a:some:app:1.8:*:*:*:*:*:*:*",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple CPEs",
|
||||
fixture: "test-fixtures/version.txt",
|
||||
classifier: Classifier{
|
||||
Package: "some-app",
|
||||
FilepathPatterns: []*regexp.Regexp{
|
||||
regexp.MustCompile(".*/version.txt"),
|
||||
},
|
||||
EvidencePatterns: []*regexp.Regexp{
|
||||
regexp.MustCompile(`(?m)my-verison:(?P<version>[0-9.]+)`),
|
||||
},
|
||||
CPEs: []pkg.CPE{
|
||||
pkg.MustCPE("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*"),
|
||||
pkg.MustCPE("cpe:2.3:a:some:apps:*:*:*:*:*:*:*:*"),
|
||||
},
|
||||
},
|
||||
cpes: []string{
|
||||
"cpe:2.3:a:some:app:1.8:*:*:*:*:*:*:*",
|
||||
"cpe:2.3:a:some:apps:1.8:*:*:*:*:*:*:*",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
resolver := source.NewMockResolverForPaths(test.fixture)
|
||||
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)
|
||||
p, _, err := test.classifier.Examine(source.NewLocationReadCloser(location, readCloser))
|
||||
require.NoError(t, err)
|
||||
|
||||
var cpes []string
|
||||
for _, c := range p.CPEs {
|
||||
cpes = append(cpes, pkg.CPEString(c))
|
||||
}
|
||||
require.Equal(t, test.cpes, cpes)
|
||||
})
|
||||
}
|
||||
}
|
||||
1
syft/pkg/cataloger/generic/test-fixtures/version.txt
Normal file
1
syft/pkg/cataloger/generic/test-fixtures/version.txt
Normal file
@ -0,0 +1 @@
|
||||
my-verison:1.8
|
||||
Loading…
x
Reference in New Issue
Block a user