mirror of
https://github.com/anchore/syft.git
synced 2026-02-14 19:46:42 +01:00
Add ability to extend the binaries cataloguers (#2469)
* Add ability to extend the binaries cataloguers Signed-off-by: Laurent Goderre <laurent.goderre@docker.com> * restrict binary classifier package attributes Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> --------- Signed-off-by: Laurent Goderre <laurent.goderre@docker.com> Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
parent
3174a17efb
commit
a16a4ad6c9
@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/anchore/syft/internal/log"
|
"github.com/anchore/syft/internal/log"
|
||||||
"github.com/anchore/syft/syft/cataloging"
|
"github.com/anchore/syft/syft/cataloging"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger"
|
"github.com/anchore/syft/syft/pkg/cataloger"
|
||||||
|
binaryCataloger "github.com/anchore/syft/syft/pkg/cataloger/binary"
|
||||||
golangCataloger "github.com/anchore/syft/syft/pkg/cataloger/golang"
|
golangCataloger "github.com/anchore/syft/syft/pkg/cataloger/golang"
|
||||||
javaCataloger "github.com/anchore/syft/syft/pkg/cataloger/java"
|
javaCataloger "github.com/anchore/syft/syft/pkg/cataloger/java"
|
||||||
javascriptCataloger "github.com/anchore/syft/syft/pkg/cataloger/javascript"
|
javascriptCataloger "github.com/anchore/syft/syft/pkg/cataloger/javascript"
|
||||||
@ -150,6 +151,7 @@ func (cfg Catalog) ToCatalogerConfig() cataloger.Config {
|
|||||||
Javascript: javascriptCataloger.DefaultCatalogerConfig().
|
Javascript: javascriptCataloger.DefaultCatalogerConfig().
|
||||||
WithSearchRemoteLicenses(cfg.Javascript.SearchRemoteLicenses).
|
WithSearchRemoteLicenses(cfg.Javascript.SearchRemoteLicenses).
|
||||||
WithNpmBaseURL(cfg.Javascript.NpmBaseURL),
|
WithNpmBaseURL(cfg.Javascript.NpmBaseURL),
|
||||||
|
Binary: binaryCataloger.DefaultCatalogerConfig(),
|
||||||
Python: pythonCataloger.CatalogerConfig{
|
Python: pythonCataloger.CatalogerConfig{
|
||||||
GuessUnpinnedRequirements: cfg.Python.GuessUnpinnedRequirements,
|
GuessUnpinnedRequirements: cfg.Python.GuessUnpinnedRequirements,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -12,8 +12,20 @@ import (
|
|||||||
|
|
||||||
const catalogerName = "binary-cataloger"
|
const catalogerName = "binary-cataloger"
|
||||||
|
|
||||||
func NewCataloger() pkg.Cataloger {
|
type CatalogerConfig struct {
|
||||||
return &Cataloger{}
|
Classifiers []Classifier
|
||||||
|
}
|
||||||
|
|
||||||
|
func DefaultCatalogerConfig() CatalogerConfig {
|
||||||
|
return CatalogerConfig{
|
||||||
|
Classifiers: DefaultClassifiers(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCataloger(cfg CatalogerConfig) pkg.Cataloger {
|
||||||
|
return &Cataloger{
|
||||||
|
classifiers: cfg.Classifiers,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cataloger is the cataloger responsible for surfacing evidence of a very limited set of binary files,
|
// Cataloger is the cataloger responsible for surfacing evidence of a very limited set of binary files,
|
||||||
@ -21,7 +33,9 @@ func NewCataloger() pkg.Cataloger {
|
|||||||
// binary, but rather the specific set that has been curated to be important, predominantly related to toolchain-
|
// binary, but rather the specific set that has been curated to be important, predominantly related to toolchain-
|
||||||
// related runtimes like Python, Go, Java, or Node. Some exceptions can be made for widely-used binaries such
|
// related runtimes like Python, Go, Java, or Node. Some exceptions can be made for widely-used binaries such
|
||||||
// as busybox.
|
// as busybox.
|
||||||
type Cataloger struct{}
|
type Cataloger struct {
|
||||||
|
classifiers []Classifier
|
||||||
|
}
|
||||||
|
|
||||||
// Name returns a string that uniquely describes the Cataloger
|
// Name returns a string that uniquely describes the Cataloger
|
||||||
func (c Cataloger) Name() string {
|
func (c Cataloger) Name() string {
|
||||||
@ -34,7 +48,7 @@ func (c Cataloger) Catalog(resolver file.Resolver) ([]pkg.Package, []artifact.Re
|
|||||||
var packages []pkg.Package
|
var packages []pkg.Package
|
||||||
var relationships []artifact.Relationship
|
var relationships []artifact.Relationship
|
||||||
|
|
||||||
for _, cls := range defaultClassifiers {
|
for _, cls := range c.classifiers {
|
||||||
log.WithFields("classifier", cls.Class).Trace("cataloging binaries")
|
log.WithFields("classifier", cls.Class).Trace("cataloging binaries")
|
||||||
newPkgs, err := catalog(resolver, cls)
|
newPkgs, err := catalog(resolver, cls)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -71,7 +85,7 @@ func mergePackages(target *pkg.Package, extra *pkg.Package) {
|
|||||||
target.Metadata = meta
|
target.Metadata = meta
|
||||||
}
|
}
|
||||||
|
|
||||||
func catalog(resolver file.Resolver, cls classifier) (packages []pkg.Package, err error) {
|
func catalog(resolver file.Resolver, cls Classifier) (packages []pkg.Package, err error) {
|
||||||
locations, err := resolver.FilesByGlob(cls.FileGlob)
|
locations, err := resolver.FilesByGlob(cls.FileGlob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@ -780,7 +780,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
c := NewCataloger()
|
c := NewCataloger(DefaultCatalogerConfig())
|
||||||
|
|
||||||
src, err := source.NewFromDirectoryPath(test.fixtureDir)
|
src, err := source.NewFromDirectoryPath(test.fixtureDir)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -819,7 +819,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases_Image(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
c := NewCataloger()
|
c := NewCataloger(DefaultCatalogerConfig())
|
||||||
|
|
||||||
img := imagetest.GetFixtureImage(t, "docker-archive", test.fixtureImage)
|
img := imagetest.GetFixtureImage(t, "docker-archive", test.fixtureImage)
|
||||||
src, err := source.NewFromStereoscopeImageObject(img, test.fixtureImage, nil)
|
src, err := source.NewFromStereoscopeImageObject(img, test.fixtureImage, nil)
|
||||||
@ -850,7 +850,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases_Image(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestClassifierCataloger_DefaultClassifiers_NegativeCases(t *testing.T) {
|
func TestClassifierCataloger_DefaultClassifiers_NegativeCases(t *testing.T) {
|
||||||
c := NewCataloger()
|
c := NewCataloger(DefaultCatalogerConfig())
|
||||||
|
|
||||||
src, err := source.NewFromDirectoryPath("test-fixtures/classifiers/negative")
|
src, err := source.NewFromDirectoryPath("test-fixtures/classifiers/negative")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -863,6 +863,129 @@ func TestClassifierCataloger_DefaultClassifiers_NegativeCases(t *testing.T) {
|
|||||||
assert.Equal(t, 0, len(actualResults))
|
assert.Equal(t, 0, len(actualResults))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_Cataloger_CustomClassifiers(t *testing.T) {
|
||||||
|
defaultClassifers := DefaultClassifiers()
|
||||||
|
|
||||||
|
golangExpected := pkg.Package{
|
||||||
|
Name: "go",
|
||||||
|
Version: "1.14",
|
||||||
|
PURL: "pkg:generic/go@1.14",
|
||||||
|
Locations: locations("go"),
|
||||||
|
Metadata: metadata("go-binary"),
|
||||||
|
}
|
||||||
|
customExpected := pkg.Package{
|
||||||
|
Name: "foo",
|
||||||
|
Version: "1.2.3",
|
||||||
|
PURL: "pkg:generic/foo@1.2.3",
|
||||||
|
Locations: locations("foo"),
|
||||||
|
Metadata: metadata("foo-binary"),
|
||||||
|
}
|
||||||
|
fooClassifier := Classifier{
|
||||||
|
Class: "foo-binary",
|
||||||
|
FileGlob: "**/foo",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
`(?m)foobar\s(?P<version>[0-9]+\.[0-9]+\.[0-9]+)`),
|
||||||
|
Package: "foo",
|
||||||
|
PURL: mustPURL("pkg:generic/foo@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:foo:foo:*:*:*:*:*:*:*:*"),
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
config CatalogerConfig
|
||||||
|
fixtureDir string
|
||||||
|
expected *pkg.Package
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty-negative",
|
||||||
|
config: CatalogerConfig{
|
||||||
|
Classifiers: []Classifier{},
|
||||||
|
},
|
||||||
|
fixtureDir: "test-fixtures/classifiers/positive/go-1.14",
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "default-positive",
|
||||||
|
config: CatalogerConfig{
|
||||||
|
Classifiers: defaultClassifers,
|
||||||
|
},
|
||||||
|
fixtureDir: "test-fixtures/classifiers/positive/go-1.14",
|
||||||
|
expected: &golangExpected,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nodefault-negative",
|
||||||
|
config: CatalogerConfig{
|
||||||
|
Classifiers: []Classifier{fooClassifier},
|
||||||
|
},
|
||||||
|
fixtureDir: "test-fixtures/classifiers/positive/go-1.14",
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "default-extended-positive",
|
||||||
|
config: CatalogerConfig{
|
||||||
|
Classifiers: append(
|
||||||
|
append([]Classifier{}, defaultClassifers...),
|
||||||
|
fooClassifier,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
fixtureDir: "test-fixtures/classifiers/positive/go-1.14",
|
||||||
|
expected: &golangExpected,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "default-cutsom-negative",
|
||||||
|
config: CatalogerConfig{
|
||||||
|
|
||||||
|
Classifiers: append(
|
||||||
|
append([]Classifier{}, defaultClassifers...),
|
||||||
|
Classifier{
|
||||||
|
Class: "foo-binary",
|
||||||
|
FileGlob: "**/foo",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(`(?m)not there`),
|
||||||
|
Package: "foo",
|
||||||
|
PURL: mustPURL("pkg:generic/foo@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:foo:foo:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
fixtureDir: "test-fixtures/classifiers/positive/custom",
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "default-cutsom-positive",
|
||||||
|
config: CatalogerConfig{
|
||||||
|
Classifiers: append(
|
||||||
|
append([]Classifier{}, defaultClassifers...),
|
||||||
|
fooClassifier,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
fixtureDir: "test-fixtures/classifiers/positive/custom",
|
||||||
|
expected: &customExpected,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
c := NewCataloger(test.config)
|
||||||
|
|
||||||
|
src, err := source.NewFromDirectoryPath(test.fixtureDir)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
resolver, err := src.FileResolver(source.SquashedScope)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
packages, _, err := c.Catalog(resolver)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if test.expected == nil {
|
||||||
|
assert.Equal(t, 0, len(packages))
|
||||||
|
} else {
|
||||||
|
require.Len(t, packages, 1)
|
||||||
|
|
||||||
|
assertPackagesAreEqual(t, *test.expected, packages[0])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func locations(locations ...string) file.LocationSet {
|
func locations(locations ...string) file.LocationSet {
|
||||||
var locs []file.Location
|
var locs []file.Location
|
||||||
for _, s := range locations {
|
for _, s := range locations {
|
||||||
@ -1019,7 +1142,7 @@ func (p *panicyResolver) FileMetadataByLocation(_ file.Location) (file.Metadata,
|
|||||||
var _ file.Resolver = (*panicyResolver)(nil)
|
var _ file.Resolver = (*panicyResolver)(nil)
|
||||||
|
|
||||||
func Test_Cataloger_ResilientToErrors(t *testing.T) {
|
func Test_Cataloger_ResilientToErrors(t *testing.T) {
|
||||||
c := NewCataloger()
|
c := NewCataloger(DefaultCatalogerConfig())
|
||||||
|
|
||||||
resolver := &panicyResolver{}
|
resolver := &panicyResolver{}
|
||||||
_, _, err := c.Catalog(resolver)
|
_, _, err := c.Catalog(resolver)
|
||||||
|
|||||||
@ -20,11 +20,9 @@ import (
|
|||||||
"github.com/anchore/syft/syft/pkg/cataloger/internal/unionreader"
|
"github.com/anchore/syft/syft/pkg/cataloger/internal/unionreader"
|
||||||
)
|
)
|
||||||
|
|
||||||
var emptyPURL = packageurl.PackageURL{}
|
// Classifier is a generic package classifier that can be used to match a package definition
|
||||||
|
// to a file that meets the given content criteria of the EvidenceMatcher.
|
||||||
// classifier is a generic package classifier that can be used to match a package definition
|
type Classifier struct {
|
||||||
// to a file that meets the given content criteria of the evidenceMatcher.
|
|
||||||
type classifier struct {
|
|
||||||
Class string
|
Class string
|
||||||
|
|
||||||
// FileGlob is a selector to narrow down file inspection using the **/glob* syntax
|
// FileGlob is a selector to narrow down file inspection using the **/glob* syntax
|
||||||
@ -32,19 +30,13 @@ type classifier struct {
|
|||||||
|
|
||||||
// EvidenceMatcher is what will be used to match against the file in the source
|
// EvidenceMatcher is what will be used to match against the file in the source
|
||||||
// location. If the matcher returns a package, the file will be considered a candidate.
|
// location. If the matcher returns a package, the file will be considered a candidate.
|
||||||
EvidenceMatcher evidenceMatcher
|
EvidenceMatcher EvidenceMatcher
|
||||||
|
|
||||||
// Information below is used to specify the Package information when returned
|
// Information below is used to specify the Package information when returned
|
||||||
|
|
||||||
// Package is the name to use for the package
|
// Package is the name to use for the package
|
||||||
Package string
|
Package string
|
||||||
|
|
||||||
// Language is the language to classify this package as
|
|
||||||
Language pkg.Language
|
|
||||||
|
|
||||||
// Type is the package type to use for the package
|
|
||||||
Type pkg.Type
|
|
||||||
|
|
||||||
// PURL is the Package URL to use when generating a package
|
// PURL is the Package URL to use when generating a package
|
||||||
PURL packageurl.PackageURL
|
PURL packageurl.PackageURL
|
||||||
|
|
||||||
@ -52,11 +44,11 @@ type classifier struct {
|
|||||||
CPEs []cpe.CPE
|
CPEs []cpe.CPE
|
||||||
}
|
}
|
||||||
|
|
||||||
// evidenceMatcher is a function called to catalog Packages that match some sort of evidence
|
// EvidenceMatcher is a function called to catalog Packages that match some sort of evidence
|
||||||
type evidenceMatcher func(resolver file.Resolver, classifier classifier, location file.Location) ([]pkg.Package, error)
|
type EvidenceMatcher func(resolver file.Resolver, classifier Classifier, location file.Location) ([]pkg.Package, error)
|
||||||
|
|
||||||
func evidenceMatchers(matchers ...evidenceMatcher) evidenceMatcher {
|
func evidenceMatchers(matchers ...EvidenceMatcher) EvidenceMatcher {
|
||||||
return func(resolver file.Resolver, classifier classifier, location file.Location) ([]pkg.Package, error) {
|
return func(resolver file.Resolver, classifier Classifier, location file.Location) ([]pkg.Package, error) {
|
||||||
for _, matcher := range matchers {
|
for _, matcher := range matchers {
|
||||||
match, err := matcher(resolver, classifier, location)
|
match, err := matcher(resolver, classifier, location)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -70,9 +62,9 @@ func evidenceMatchers(matchers ...evidenceMatcher) evidenceMatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileNameTemplateVersionMatcher(fileNamePattern string, contentTemplate string) evidenceMatcher {
|
func fileNameTemplateVersionMatcher(fileNamePattern string, contentTemplate string) EvidenceMatcher {
|
||||||
pat := regexp.MustCompile(fileNamePattern)
|
pat := regexp.MustCompile(fileNamePattern)
|
||||||
return func(resolver file.Resolver, classifier classifier, location file.Location) ([]pkg.Package, error) {
|
return func(resolver file.Resolver, classifier Classifier, location file.Location) ([]pkg.Package, error) {
|
||||||
if !pat.MatchString(location.RealPath) {
|
if !pat.MatchString(location.RealPath) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@ -116,9 +108,9 @@ func fileNameTemplateVersionMatcher(fileNamePattern string, contentTemplate stri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileContentsVersionMatcher(pattern string) evidenceMatcher {
|
func FileContentsVersionMatcher(pattern string) EvidenceMatcher {
|
||||||
pat := regexp.MustCompile(pattern)
|
pat := regexp.MustCompile(pattern)
|
||||||
return func(resolver file.Resolver, classifier classifier, location file.Location) ([]pkg.Package, error) {
|
return func(resolver file.Resolver, classifier Classifier, location file.Location) ([]pkg.Package, error) {
|
||||||
contents, err := getContents(resolver, location)
|
contents, err := getContents(resolver, location)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to get read contents for file: %w", err)
|
return nil, fmt.Errorf("unable to get read contents for file: %w", err)
|
||||||
@ -136,9 +128,9 @@ func fileContentsVersionMatcher(pattern string) evidenceMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//nolint:gocognit
|
//nolint:gocognit
|
||||||
func sharedLibraryLookup(sharedLibraryPattern string, sharedLibraryMatcher evidenceMatcher) evidenceMatcher {
|
func sharedLibraryLookup(sharedLibraryPattern string, sharedLibraryMatcher EvidenceMatcher) EvidenceMatcher {
|
||||||
pat := regexp.MustCompile(sharedLibraryPattern)
|
pat := regexp.MustCompile(sharedLibraryPattern)
|
||||||
return func(resolver file.Resolver, classifier classifier, location file.Location) (packages []pkg.Package, _ error) {
|
return func(resolver file.Resolver, classifier Classifier, location file.Location) (packages []pkg.Package, _ error) {
|
||||||
libs, err := sharedLibraries(resolver, location)
|
libs, err := sharedLibraries(resolver, location)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@ -13,16 +13,16 @@ func Test_ClassifierCPEs(t *testing.T) {
|
|||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
fixture string
|
fixture string
|
||||||
classifier classifier
|
classifier Classifier
|
||||||
cpes []string
|
cpes []string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no CPEs",
|
name: "no CPEs",
|
||||||
fixture: "test-fixtures/version.txt",
|
fixture: "test-fixtures/version.txt",
|
||||||
classifier: classifier{
|
classifier: Classifier{
|
||||||
Package: "some-app",
|
Package: "some-app",
|
||||||
FileGlob: "**/version.txt",
|
FileGlob: "**/version.txt",
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(`(?m)my-verison:(?P<version>[0-9.]+)`),
|
EvidenceMatcher: FileContentsVersionMatcher(`(?m)my-verison:(?P<version>[0-9.]+)`),
|
||||||
CPEs: []cpe.CPE{},
|
CPEs: []cpe.CPE{},
|
||||||
},
|
},
|
||||||
cpes: nil,
|
cpes: nil,
|
||||||
@ -30,10 +30,10 @@ func Test_ClassifierCPEs(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "one CPE",
|
name: "one CPE",
|
||||||
fixture: "test-fixtures/version.txt",
|
fixture: "test-fixtures/version.txt",
|
||||||
classifier: classifier{
|
classifier: Classifier{
|
||||||
Package: "some-app",
|
Package: "some-app",
|
||||||
FileGlob: "**/version.txt",
|
FileGlob: "**/version.txt",
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(`(?m)my-verison:(?P<version>[0-9.]+)`),
|
EvidenceMatcher: FileContentsVersionMatcher(`(?m)my-verison:(?P<version>[0-9.]+)`),
|
||||||
CPEs: []cpe.CPE{
|
CPEs: []cpe.CPE{
|
||||||
cpe.Must("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*"),
|
cpe.Must("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*"),
|
||||||
},
|
},
|
||||||
@ -45,10 +45,10 @@ func Test_ClassifierCPEs(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "multiple CPEs",
|
name: "multiple CPEs",
|
||||||
fixture: "test-fixtures/version.txt",
|
fixture: "test-fixtures/version.txt",
|
||||||
classifier: classifier{
|
classifier: Classifier{
|
||||||
Package: "some-app",
|
Package: "some-app",
|
||||||
FileGlob: "**/version.txt",
|
FileGlob: "**/version.txt",
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(`(?m)my-verison:(?P<version>[0-9.]+)`),
|
EvidenceMatcher: FileContentsVersionMatcher(`(?m)my-verison:(?P<version>[0-9.]+)`),
|
||||||
CPEs: []cpe.CPE{
|
CPEs: []cpe.CPE{
|
||||||
cpe.Must("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*"),
|
cpe.Must("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*"),
|
||||||
cpe.Must("cpe:2.3:a:some:apps:*:*:*:*:*:*:*:*"),
|
cpe.Must("cpe:2.3:a:some:apps:*:*:*:*:*:*:*:*"),
|
||||||
|
|||||||
@ -2,350 +2,351 @@ package binary
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/anchore/syft/syft/cpe"
|
"github.com/anchore/syft/syft/cpe"
|
||||||
"github.com/anchore/syft/syft/pkg"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var defaultClassifiers = []classifier{
|
//nolint:funlen
|
||||||
{
|
func DefaultClassifiers() []Classifier {
|
||||||
Class: "python-binary",
|
return []Classifier{
|
||||||
FileGlob: "**/python*",
|
{
|
||||||
EvidenceMatcher: evidenceMatchers(
|
Class: "python-binary",
|
||||||
// try to find version information from libpython shared libraries
|
FileGlob: "**/python*",
|
||||||
sharedLibraryLookup(
|
EvidenceMatcher: evidenceMatchers(
|
||||||
`^libpython[0-9]+(?:\.[0-9]+)+[a-z]?\.so.*$`,
|
// try to find version information from libpython shared libraries
|
||||||
libpythonMatcher),
|
sharedLibraryLookup(
|
||||||
// check for version information in the binary
|
`^libpython[0-9]+(?:\.[0-9]+)+[a-z]?\.so.*$`,
|
||||||
fileNameTemplateVersionMatcher(
|
libpythonMatcher),
|
||||||
`(?:.*/|^)python(?P<version>[0-9]+(?:\.[0-9]+)+)$`,
|
// check for version information in the binary
|
||||||
pythonVersionTemplate),
|
fileNameTemplateVersionMatcher(
|
||||||
),
|
`(?:.*/|^)python(?P<version>[0-9]+(?:\.[0-9]+)+)$`,
|
||||||
Package: "python",
|
pythonVersionTemplate),
|
||||||
PURL: mustPURL("pkg:generic/python@version"),
|
),
|
||||||
CPEs: []cpe.CPE{
|
Package: "python",
|
||||||
cpe.Must("cpe:2.3:a:python_software_foundation:python:*:*:*:*:*:*:*:*"),
|
PURL: mustPURL("pkg:generic/python@version"),
|
||||||
cpe.Must("cpe:2.3:a:python:python:*:*:*:*:*:*:*:*"),
|
CPEs: []cpe.CPE{
|
||||||
|
cpe.Must("cpe:2.3:a:python_software_foundation:python:*:*:*:*:*:*:*:*"),
|
||||||
|
cpe.Must("cpe:2.3:a:python:python:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
Class: "python-binary-lib",
|
||||||
Class: "python-binary-lib",
|
FileGlob: "**/libpython*.so*",
|
||||||
FileGlob: "**/libpython*.so*",
|
EvidenceMatcher: libpythonMatcher,
|
||||||
EvidenceMatcher: libpythonMatcher,
|
Package: "python",
|
||||||
Package: "python",
|
PURL: mustPURL("pkg:generic/python@version"),
|
||||||
PURL: mustPURL("pkg:generic/python@version"),
|
CPEs: []cpe.CPE{
|
||||||
CPEs: []cpe.CPE{
|
cpe.Must("cpe:2.3:a:python_software_foundation:python:*:*:*:*:*:*:*:*"),
|
||||||
cpe.Must("cpe:2.3:a:python_software_foundation:python:*:*:*:*:*:*:*:*"),
|
cpe.Must("cpe:2.3:a:python:python:*:*:*:*:*:*:*:*"),
|
||||||
cpe.Must("cpe:2.3:a:python:python:*:*:*:*:*:*:*:*"),
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
Class: "go-binary",
|
||||||
Class: "go-binary",
|
FileGlob: "**/go",
|
||||||
FileGlob: "**/go",
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
`(?m)go(?P<version>[0-9]+\.[0-9]+(\.[0-9]+|beta[0-9]+|alpha[0-9]+|rc[0-9]+)?)\x00`),
|
||||||
`(?m)go(?P<version>[0-9]+\.[0-9]+(\.[0-9]+|beta[0-9]+|alpha[0-9]+|rc[0-9]+)?)\x00`),
|
Package: "go",
|
||||||
Package: "go",
|
PURL: mustPURL("pkg:generic/go@version"),
|
||||||
PURL: mustPURL("pkg:generic/go@version"),
|
CPEs: singleCPE("cpe:2.3:a:golang:go:*:*:*:*:*:*:*:*"),
|
||||||
CPEs: singleCPE("cpe:2.3:a:golang:go:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "julia-binary",
|
|
||||||
FileGlob: "**/libjulia-internal.so",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
`(?m)__init__\x00(?P<version>[0-9]+\.[0-9]+\.[0-9]+)\x00verify`),
|
|
||||||
Package: "julia",
|
|
||||||
PURL: mustPURL("pkg:generic/julia@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:julialang:julia:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "helm",
|
|
||||||
FileGlob: "**/helm",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
`(?m)\x00v(?P<version>[0-9]+\.[0-9]+\.[0-9]+)\x00`),
|
|
||||||
Package: "helm",
|
|
||||||
PURL: mustPURL("pkg:golang/helm.sh/helm@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:helm:helm:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "redis-binary",
|
|
||||||
FileGlob: "**/redis-server",
|
|
||||||
EvidenceMatcher: evidenceMatchers(
|
|
||||||
fileContentsVersionMatcher(`(?s)payload %5.*?(?P<version>\d.\d\.\d\d*)[a-z0-9]{12,15}-[0-9]{19}`),
|
|
||||||
fileContentsVersionMatcher(`(?s)\x00(?P<version>\d.\d\.\d\d*)[a-z0-9]{12}-[0-9]{19}\x00.*?payload %5`),
|
|
||||||
),
|
|
||||||
Package: "redis",
|
|
||||||
PURL: mustPURL("pkg:generic/redis@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:redislabs:redis:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "java-binary-openjdk",
|
|
||||||
FileGlob: "**/java",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
// [NUL]openjdk[NUL]java[NUL]0.0[NUL]11.0.17+8-LTS[NUL]
|
|
||||||
// [NUL]openjdk[NUL]java[NUL]1.8[NUL]1.8.0_352-b08[NUL]
|
|
||||||
`(?m)\x00openjdk\x00java\x00(?P<release>[0-9]+[.0-9]*)\x00(?P<version>[0-9]+[^\x00]+)\x00`),
|
|
||||||
Package: "java",
|
|
||||||
PURL: mustPURL("pkg:generic/java@version"),
|
|
||||||
// TODO the updates might need to be part of the CPE, like: 1.8.0:update152
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:oracle:openjdk:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "java-binary-ibm",
|
|
||||||
FileGlob: "**/java",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
// [NUL]java[NUL]1.8[NUL][NUL][NUL][NUL]1.8.0-foreman_2022_09_22_15_30-b00[NUL]
|
|
||||||
`(?m)\x00java\x00(?P<release>[0-9]+[.0-9]+)\x00{4}(?P<version>[0-9]+[-._a-zA-Z0-9]+)\x00`),
|
|
||||||
Package: "java",
|
|
||||||
PURL: mustPURL("pkg:generic/java@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:ibm:java:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "java-binary-oracle",
|
|
||||||
FileGlob: "**/java",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
// [NUL]19.0.1+10-21[NUL]
|
|
||||||
`(?m)\x00(?P<version>[0-9]+[.0-9]+[+][-0-9]+)\x00`),
|
|
||||||
Package: "java",
|
|
||||||
PURL: mustPURL("pkg:generic/java@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:oracle:jre:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "nodejs-binary",
|
|
||||||
FileGlob: "**/node",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
`(?m)node\.js\/v(?P<version>[0-9]+\.[0-9]+\.[0-9]+)`),
|
|
||||||
Package: "node",
|
|
||||||
Language: pkg.JavaScript,
|
|
||||||
PURL: mustPURL("pkg:generic/node@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:nodejs:node.js:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "go-binary-hint",
|
|
||||||
FileGlob: "**/VERSION",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
`(?m)go(?P<version>[0-9]+\.[0-9]+(\.[0-9]+|beta[0-9]+|alpha[0-9]+|rc[0-9]+)?)`),
|
|
||||||
Package: "go",
|
|
||||||
PURL: mustPURL("pkg:generic/go@version"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "busybox-binary",
|
|
||||||
FileGlob: "**/busybox",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
`(?m)BusyBox\s+v(?P<version>[0-9]+\.[0-9]+\.[0-9]+)`),
|
|
||||||
Package: "busybox",
|
|
||||||
PURL: mustPURL("pkg:generic/busybox@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:busybox:busybox:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "haproxy-binary",
|
|
||||||
FileGlob: "**/haproxy",
|
|
||||||
EvidenceMatcher: evidenceMatchers(
|
|
||||||
fileContentsVersionMatcher(`(?m)HA-Proxy version (?P<version>[0-9]+\.[0-9]+\.[0-9]+)`),
|
|
||||||
fileContentsVersionMatcher(`(?m)(?P<version>[0-9]+\.[0-9]+\.[0-9]+)-[0-9a-zA-Z]{7}.+HAProxy version`),
|
|
||||||
),
|
|
||||||
Package: "haproxy",
|
|
||||||
PURL: mustPURL("pkg:generic/haproxy@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:haproxy:haproxy:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "perl-binary",
|
|
||||||
FileGlob: "**/perl",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
`(?m)\/usr\/local\/lib\/perl\d\/(?P<version>[0-9]+\.[0-9]+\.[0-9]+)`),
|
|
||||||
Package: "perl",
|
|
||||||
PURL: mustPURL("pkg:generic/perl@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:perl:perl:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "php-cli-binary",
|
|
||||||
FileGlob: "**/php*",
|
|
||||||
EvidenceMatcher: fileNameTemplateVersionMatcher(
|
|
||||||
`(.*/|^)php[0-9]*$`,
|
|
||||||
`(?m)X-Powered-By: PHP\/(?P<version>[0-9]+\.[0-9]+\.[0-9]+(beta[0-9]+|alpha[0-9]+|RC[0-9]+)?)`),
|
|
||||||
Package: "php-cli",
|
|
||||||
PURL: mustPURL("pkg:generic/php-cli@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:php:php:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "php-fpm-binary",
|
|
||||||
FileGlob: "**/php-fpm*",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
`(?m)X-Powered-By: PHP\/(?P<version>[0-9]+\.[0-9]+\.[0-9]+(beta[0-9]+|alpha[0-9]+|RC[0-9]+)?)`),
|
|
||||||
Package: "php-fpm",
|
|
||||||
PURL: mustPURL("pkg:generic/php-fpm@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:php:php:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "php-apache-binary",
|
|
||||||
FileGlob: "**/libphp*.so",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
`(?m)X-Powered-By: PHP\/(?P<version>[0-9]+\.[0-9]+\.[0-9]+(beta[0-9]+|alpha[0-9]+|RC[0-9]+)?)`),
|
|
||||||
Package: "libphp",
|
|
||||||
PURL: mustPURL("pkg:generic/php@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:php:php:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "php-composer-binary",
|
|
||||||
FileGlob: "**/composer*",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
`(?m)'pretty_version'\s*=>\s*'(?P<version>[0-9]+\.[0-9]+\.[0-9]+(beta[0-9]+|alpha[0-9]+|RC[0-9]+)?)'`),
|
|
||||||
Package: "composer",
|
|
||||||
PURL: mustPURL("pkg:generic/composer@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:getcomposer:composer:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "httpd-binary",
|
|
||||||
FileGlob: "**/httpd",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
`(?m)Apache\/(?P<version>[0-9]+\.[0-9]+\.[0-9]+)`),
|
|
||||||
Package: "httpd",
|
|
||||||
PURL: mustPURL("pkg:generic/httpd@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:apache:http_server:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "memcached-binary",
|
|
||||||
FileGlob: "**/memcached",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
`(?m)memcached\s(?P<version>[0-9]+\.[0-9]+\.[0-9]+)`),
|
|
||||||
Package: "memcached",
|
|
||||||
PURL: mustPURL("pkg:generic/memcached@version"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "traefik-binary",
|
|
||||||
FileGlob: "**/traefik",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
// [NUL]v1.7.34[NUL]
|
|
||||||
// [NUL]2.9.6[NUL]
|
|
||||||
`(?m)\x00v?(?P<version>[0-9]+\.[0-9]+\.[0-9]+(-alpha[0-9]|-beta[0-9]|-rc[0-9])?)\x00`),
|
|
||||||
Package: "traefik",
|
|
||||||
PURL: mustPURL("pkg:generic/traefik@version"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "postgresql-binary",
|
|
||||||
FileGlob: "**/postgres",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
// [NUL]PostgreSQL 15beta4
|
|
||||||
// [NUL]PostgreSQL 15.1
|
|
||||||
// [NUL]PostgreSQL 9.6.24
|
|
||||||
// ?PostgreSQL 9.5alpha1
|
|
||||||
`(?m)(\x00|\?)PostgreSQL (?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)`),
|
|
||||||
Package: "postgresql",
|
|
||||||
PURL: mustPURL("pkg:generic/postgresql@version"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "mysql-binary",
|
|
||||||
FileGlob: "**/mysql",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
// ../../mysql-8.0.34
|
|
||||||
// /mysql-5.6.51/bld/client
|
|
||||||
`(?m).*/mysql-(?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)`),
|
|
||||||
Package: "mysql",
|
|
||||||
PURL: mustPURL("pkg:generic/mysql@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "mariadb-binary",
|
|
||||||
FileGlob: "**/mariadb",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
// 10.6.15-MariaDB
|
|
||||||
`(?m)(?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)-MariaDB`),
|
|
||||||
Package: "mariadb",
|
|
||||||
PURL: mustPURL("pkg:generic/mariadb@version"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "rust-standard-library-linux",
|
|
||||||
FileGlob: "**/libstd-????????????????.so",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
// clang LLVM (rustc version 1.48.0 (7eac88abb 2020-11-16))
|
|
||||||
`(?m)(\x00)clang LLVM \(rustc version (?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)) \(\w+ \d{4}\-\d{2}\-\d{2}\)`),
|
|
||||||
Package: "rust",
|
|
||||||
PURL: mustPURL("pkg:generic/rust@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:rust-lang:rust:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "rust-standard-library-macos",
|
|
||||||
FileGlob: "**/libstd-????????????????.dylib",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
// c 1.48.0 (7eac88abb 2020-11-16)
|
|
||||||
`(?m)c (?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)) \(\w+ \d{4}\-\d{2}\-\d{2}\)`),
|
|
||||||
Package: "rust",
|
|
||||||
PURL: mustPURL("pkg:generic/rust@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:rust-lang:rust:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "ruby-binary",
|
|
||||||
FileGlob: "**/ruby",
|
|
||||||
EvidenceMatcher: evidenceMatchers(
|
|
||||||
rubyMatcher,
|
|
||||||
sharedLibraryLookup(
|
|
||||||
// try to find version information from libruby shared libraries
|
|
||||||
`^libruby\.so.*$`,
|
|
||||||
rubyMatcher),
|
|
||||||
),
|
|
||||||
Package: "ruby",
|
|
||||||
PURL: mustPURL("pkg:generic/ruby@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:ruby-lang:ruby:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "erlang-binary",
|
|
||||||
FileGlob: "**/erlexec",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
// <artificial>[NUL]/usr/local/src/otp-25.3.2.7/erts/
|
|
||||||
`(?m)\<artificial\>\x00/usr/local/src/otp-(?P<version>[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+?)/erts/`,
|
|
||||||
),
|
|
||||||
Package: "erlang",
|
|
||||||
PURL: mustPURL("pkg:generic/erlang@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "consul-binary",
|
|
||||||
FileGlob: "**/consul",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
// NOTE: This is brittle and may not work for past or future versions
|
|
||||||
`CONSUL_VERSION: (?P<version>\d+\.\d+\.\d+)`,
|
|
||||||
),
|
|
||||||
Package: "consul",
|
|
||||||
PURL: mustPURL("pkg:golang/github.com/hashicorp/consul@version"),
|
|
||||||
CPEs: singleCPE("cpe:2.3:a:hashicorp:consul:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Class: "nginx-binary",
|
|
||||||
FileGlob: "**/nginx",
|
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
|
||||||
// [NUL]nginx version: nginx/1.25.1 - fetches '1.25.1'
|
|
||||||
// [NUL]nginx version: openresty/1.21.4.1 - fetches '1.21.4' as this is the nginx version part
|
|
||||||
`(?m)(\x00|\?)nginx version: [^\/]+\/(?P<version>[0-9]+\.[0-9]+\.[0-9]+(?:\+\d+)?(?:-\d+)?)`,
|
|
||||||
),
|
|
||||||
Package: "nginx",
|
|
||||||
PURL: mustPURL("pkg:generic/nginx@version"),
|
|
||||||
CPEs: []cpe.CPE{
|
|
||||||
cpe.Must("cpe:2.3:a:f5:nginx:*:*:*:*:*:*:*:*"),
|
|
||||||
cpe.Must("cpe:2.3:a:nginx:nginx:*:*:*:*:*:*:*:*"),
|
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
Class: "julia-binary",
|
||||||
Class: "bash-binary",
|
FileGlob: "**/libjulia-internal.so",
|
||||||
FileGlob: "**/bash",
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
`(?m)__init__\x00(?P<version>[0-9]+\.[0-9]+\.[0-9]+)\x00verify`),
|
||||||
// @(#)Bash version 5.2.15(1) release GNU
|
Package: "julia",
|
||||||
// @(#)Bash version 5.2.0(1) alpha GNU
|
PURL: mustPURL("pkg:generic/julia@version"),
|
||||||
// @(#)Bash version 5.2.0(1) beta GNU
|
CPEs: singleCPE("cpe:2.3:a:julialang:julia:*:*:*:*:*:*:*:*"),
|
||||||
// @(#)Bash version 5.2.0(1) rc4 GNU
|
},
|
||||||
`(?m)@\(#\)Bash version (?P<version>[0-9]+\.[0-9]+\.[0-9]+)\([0-9]\) [a-z0-9]+ GNU`,
|
{
|
||||||
),
|
Class: "helm",
|
||||||
Package: "bash",
|
FileGlob: "**/helm",
|
||||||
PURL: mustPURL("pkg:generic/bash@version"),
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
CPEs: singleCPE("cpe:2.3:a:gnu:bash:*:*:*:*:*:*:*:*"),
|
`(?m)\x00v(?P<version>[0-9]+\.[0-9]+\.[0-9]+)\x00`),
|
||||||
},
|
Package: "helm",
|
||||||
{
|
PURL: mustPURL("pkg:golang/helm.sh/helm@version"),
|
||||||
Class: "openssl-binary",
|
CPEs: singleCPE("cpe:2.3:a:helm:helm:*:*:*:*:*:*:*"),
|
||||||
FileGlob: "**/openssl",
|
},
|
||||||
EvidenceMatcher: fileContentsVersionMatcher(
|
{
|
||||||
// [NUL]OpenSSL 3.1.4'
|
Class: "redis-binary",
|
||||||
`\x00OpenSSL (?P<version>[0-9]+\.[0-9]+\.[0-9]+(-alpha[0-9]|-beta[0-9]|-rc[0-9])?)`,
|
FileGlob: "**/redis-server",
|
||||||
),
|
EvidenceMatcher: evidenceMatchers(
|
||||||
Package: "openssl",
|
FileContentsVersionMatcher(`(?s)payload %5.*?(?P<version>\d.\d\.\d\d*)[a-z0-9]{12,15}-[0-9]{19}`),
|
||||||
PURL: mustPURL("pkg:generic/openssl@version"),
|
FileContentsVersionMatcher(`(?s)\x00(?P<version>\d.\d\.\d\d*)[a-z0-9]{12}-[0-9]{19}\x00.*?payload %5`),
|
||||||
CPEs: singleCPE("cpe:2.3:a:openssl:openssl:*:*:*:*:*:*:*:*"),
|
),
|
||||||
},
|
Package: "redis",
|
||||||
|
PURL: mustPURL("pkg:generic/redis@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:redislabs:redis:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "java-binary-openjdk",
|
||||||
|
FileGlob: "**/java",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
// [NUL]openjdk[NUL]java[NUL]0.0[NUL]11.0.17+8-LTS[NUL]
|
||||||
|
// [NUL]openjdk[NUL]java[NUL]1.8[NUL]1.8.0_352-b08[NUL]
|
||||||
|
`(?m)\x00openjdk\x00java\x00(?P<release>[0-9]+[.0-9]*)\x00(?P<version>[0-9]+[^\x00]+)\x00`),
|
||||||
|
Package: "java",
|
||||||
|
PURL: mustPURL("pkg:generic/java@version"),
|
||||||
|
// TODO the updates might need to be part of the CPE, like: 1.8.0:update152
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:oracle:openjdk:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "java-binary-ibm",
|
||||||
|
FileGlob: "**/java",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
// [NUL]java[NUL]1.8[NUL][NUL][NUL][NUL]1.8.0-foreman_2022_09_22_15_30-b00[NUL]
|
||||||
|
`(?m)\x00java\x00(?P<release>[0-9]+[.0-9]+)\x00{4}(?P<version>[0-9]+[-._a-zA-Z0-9]+)\x00`),
|
||||||
|
Package: "java",
|
||||||
|
PURL: mustPURL("pkg:generic/java@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:ibm:java:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "java-binary-oracle",
|
||||||
|
FileGlob: "**/java",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
// [NUL]19.0.1+10-21[NUL]
|
||||||
|
`(?m)\x00(?P<version>[0-9]+[.0-9]+[+][-0-9]+)\x00`),
|
||||||
|
Package: "java",
|
||||||
|
PURL: mustPURL("pkg:generic/java@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:oracle:jre:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "nodejs-binary",
|
||||||
|
FileGlob: "**/node",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
`(?m)node\.js\/v(?P<version>[0-9]+\.[0-9]+\.[0-9]+)`),
|
||||||
|
Package: "node",
|
||||||
|
PURL: mustPURL("pkg:generic/node@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:nodejs:node.js:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "go-binary-hint",
|
||||||
|
FileGlob: "**/VERSION",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
`(?m)go(?P<version>[0-9]+\.[0-9]+(\.[0-9]+|beta[0-9]+|alpha[0-9]+|rc[0-9]+)?)`),
|
||||||
|
Package: "go",
|
||||||
|
PURL: mustPURL("pkg:generic/go@version"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "busybox-binary",
|
||||||
|
FileGlob: "**/busybox",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
`(?m)BusyBox\s+v(?P<version>[0-9]+\.[0-9]+\.[0-9]+)`),
|
||||||
|
Package: "busybox",
|
||||||
|
PURL: mustPURL("pkg:generic/busybox@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:busybox:busybox:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "haproxy-binary",
|
||||||
|
FileGlob: "**/haproxy",
|
||||||
|
EvidenceMatcher: evidenceMatchers(
|
||||||
|
FileContentsVersionMatcher(`(?m)HA-Proxy version (?P<version>[0-9]+\.[0-9]+\.[0-9]+)`),
|
||||||
|
FileContentsVersionMatcher(`(?m)(?P<version>[0-9]+\.[0-9]+\.[0-9]+)-[0-9a-zA-Z]{7}.+HAProxy version`),
|
||||||
|
),
|
||||||
|
Package: "haproxy",
|
||||||
|
PURL: mustPURL("pkg:generic/haproxy@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:haproxy:haproxy:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "perl-binary",
|
||||||
|
FileGlob: "**/perl",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
`(?m)\/usr\/local\/lib\/perl\d\/(?P<version>[0-9]+\.[0-9]+\.[0-9]+)`),
|
||||||
|
Package: "perl",
|
||||||
|
PURL: mustPURL("pkg:generic/perl@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:perl:perl:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "php-cli-binary",
|
||||||
|
FileGlob: "**/php*",
|
||||||
|
EvidenceMatcher: fileNameTemplateVersionMatcher(
|
||||||
|
`(.*/|^)php[0-9]*$`,
|
||||||
|
`(?m)X-Powered-By: PHP\/(?P<version>[0-9]+\.[0-9]+\.[0-9]+(beta[0-9]+|alpha[0-9]+|RC[0-9]+)?)`),
|
||||||
|
Package: "php-cli",
|
||||||
|
PURL: mustPURL("pkg:generic/php-cli@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:php:php:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "php-fpm-binary",
|
||||||
|
FileGlob: "**/php-fpm*",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
`(?m)X-Powered-By: PHP\/(?P<version>[0-9]+\.[0-9]+\.[0-9]+(beta[0-9]+|alpha[0-9]+|RC[0-9]+)?)`),
|
||||||
|
Package: "php-fpm",
|
||||||
|
PURL: mustPURL("pkg:generic/php-fpm@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:php:php:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "php-apache-binary",
|
||||||
|
FileGlob: "**/libphp*.so",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
`(?m)X-Powered-By: PHP\/(?P<version>[0-9]+\.[0-9]+\.[0-9]+(beta[0-9]+|alpha[0-9]+|RC[0-9]+)?)`),
|
||||||
|
Package: "libphp",
|
||||||
|
PURL: mustPURL("pkg:generic/php@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:php:php:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "php-composer-binary",
|
||||||
|
FileGlob: "**/composer*",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
`(?m)'pretty_version'\s*=>\s*'(?P<version>[0-9]+\.[0-9]+\.[0-9]+(beta[0-9]+|alpha[0-9]+|RC[0-9]+)?)'`),
|
||||||
|
Package: "composer",
|
||||||
|
PURL: mustPURL("pkg:generic/composer@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:getcomposer:composer:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "httpd-binary",
|
||||||
|
FileGlob: "**/httpd",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
`(?m)Apache\/(?P<version>[0-9]+\.[0-9]+\.[0-9]+)`),
|
||||||
|
Package: "httpd",
|
||||||
|
PURL: mustPURL("pkg:generic/httpd@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:apache:http_server:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "memcached-binary",
|
||||||
|
FileGlob: "**/memcached",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
`(?m)memcached\s(?P<version>[0-9]+\.[0-9]+\.[0-9]+)`),
|
||||||
|
Package: "memcached",
|
||||||
|
PURL: mustPURL("pkg:generic/memcached@version"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "traefik-binary",
|
||||||
|
FileGlob: "**/traefik",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
// [NUL]v1.7.34[NUL]
|
||||||
|
// [NUL]2.9.6[NUL]
|
||||||
|
`(?m)\x00v?(?P<version>[0-9]+\.[0-9]+\.[0-9]+(-alpha[0-9]|-beta[0-9]|-rc[0-9])?)\x00`),
|
||||||
|
Package: "traefik",
|
||||||
|
PURL: mustPURL("pkg:generic/traefik@version"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "postgresql-binary",
|
||||||
|
FileGlob: "**/postgres",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
// [NUL]PostgreSQL 15beta4
|
||||||
|
// [NUL]PostgreSQL 15.1
|
||||||
|
// [NUL]PostgreSQL 9.6.24
|
||||||
|
// ?PostgreSQL 9.5alpha1
|
||||||
|
`(?m)(\x00|\?)PostgreSQL (?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)`),
|
||||||
|
Package: "postgresql",
|
||||||
|
PURL: mustPURL("pkg:generic/postgresql@version"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "mysql-binary",
|
||||||
|
FileGlob: "**/mysql",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
// ../../mysql-8.0.34
|
||||||
|
// /mysql-5.6.51/bld/client
|
||||||
|
`(?m).*/mysql-(?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)`),
|
||||||
|
Package: "mysql",
|
||||||
|
PURL: mustPURL("pkg:generic/mysql@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "mariadb-binary",
|
||||||
|
FileGlob: "**/mariadb",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
// 10.6.15-MariaDB
|
||||||
|
`(?m)(?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)-MariaDB`),
|
||||||
|
Package: "mariadb",
|
||||||
|
PURL: mustPURL("pkg:generic/mariadb@version"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "rust-standard-library-linux",
|
||||||
|
FileGlob: "**/libstd-????????????????.so",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
// clang LLVM (rustc version 1.48.0 (7eac88abb 2020-11-16))
|
||||||
|
`(?m)(\x00)clang LLVM \(rustc version (?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)) \(\w+ \d{4}\-\d{2}\-\d{2}\)`),
|
||||||
|
Package: "rust",
|
||||||
|
PURL: mustPURL("pkg:generic/rust@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:rust-lang:rust:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "rust-standard-library-macos",
|
||||||
|
FileGlob: "**/libstd-????????????????.dylib",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
// c 1.48.0 (7eac88abb 2020-11-16)
|
||||||
|
`(?m)c (?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)) \(\w+ \d{4}\-\d{2}\-\d{2}\)`),
|
||||||
|
Package: "rust",
|
||||||
|
PURL: mustPURL("pkg:generic/rust@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:rust-lang:rust:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "ruby-binary",
|
||||||
|
FileGlob: "**/ruby",
|
||||||
|
EvidenceMatcher: evidenceMatchers(
|
||||||
|
rubyMatcher,
|
||||||
|
sharedLibraryLookup(
|
||||||
|
// try to find version information from libruby shared libraries
|
||||||
|
`^libruby\.so.*$`,
|
||||||
|
rubyMatcher),
|
||||||
|
),
|
||||||
|
Package: "ruby",
|
||||||
|
PURL: mustPURL("pkg:generic/ruby@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:ruby-lang:ruby:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "erlang-binary",
|
||||||
|
FileGlob: "**/erlexec",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
// <artificial>[NUL]/usr/local/src/otp-25.3.2.7/erts/
|
||||||
|
`(?m)\<artificial\>\x00/usr/local/src/otp-(?P<version>[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+?)/erts/`,
|
||||||
|
),
|
||||||
|
Package: "erlang",
|
||||||
|
PURL: mustPURL("pkg:generic/erlang@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "consul-binary",
|
||||||
|
FileGlob: "**/consul",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
// NOTE: This is brittle and may not work for past or future versions
|
||||||
|
`CONSUL_VERSION: (?P<version>\d+\.\d+\.\d+)`,
|
||||||
|
),
|
||||||
|
Package: "consul",
|
||||||
|
PURL: mustPURL("pkg:golang/github.com/hashicorp/consul@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:hashicorp:consul:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "nginx-binary",
|
||||||
|
FileGlob: "**/nginx",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
// [NUL]nginx version: nginx/1.25.1 - fetches '1.25.1'
|
||||||
|
// [NUL]nginx version: openresty/1.21.4.1 - fetches '1.21.4' as this is the nginx version part
|
||||||
|
`(?m)(\x00|\?)nginx version: [^\/]+\/(?P<version>[0-9]+\.[0-9]+\.[0-9]+(?:\+\d+)?(?:-\d+)?)`,
|
||||||
|
),
|
||||||
|
Package: "nginx",
|
||||||
|
PURL: mustPURL("pkg:generic/nginx@version"),
|
||||||
|
CPEs: []cpe.CPE{
|
||||||
|
cpe.Must("cpe:2.3:a:f5:nginx:*:*:*:*:*:*:*:*"),
|
||||||
|
cpe.Must("cpe:2.3:a:nginx:nginx:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "bash-binary",
|
||||||
|
FileGlob: "**/bash",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
// @(#)Bash version 5.2.15(1) release GNU
|
||||||
|
// @(#)Bash version 5.2.0(1) alpha GNU
|
||||||
|
// @(#)Bash version 5.2.0(1) beta GNU
|
||||||
|
// @(#)Bash version 5.2.0(1) rc4 GNU
|
||||||
|
`(?m)@\(#\)Bash version (?P<version>[0-9]+\.[0-9]+\.[0-9]+)\([0-9]\) [a-z0-9]+ GNU`,
|
||||||
|
),
|
||||||
|
Package: "bash",
|
||||||
|
PURL: mustPURL("pkg:generic/bash@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:gnu:bash:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Class: "openssl-binary",
|
||||||
|
FileGlob: "**/openssl",
|
||||||
|
EvidenceMatcher: FileContentsVersionMatcher(
|
||||||
|
// [NUL]OpenSSL 3.1.4'
|
||||||
|
`\x00OpenSSL (?P<version>[0-9]+\.[0-9]+\.[0-9]+(-alpha[0-9]|-beta[0-9]|-rc[0-9])?)`,
|
||||||
|
),
|
||||||
|
Package: "openssl",
|
||||||
|
PURL: mustPURL("pkg:generic/openssl@version"),
|
||||||
|
CPEs: singleCPE("cpe:2.3:a:openssl:openssl:*:*:*:*:*:*:*:*"),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// in both binaries and shared libraries, the version pattern is [NUL]3.11.2[NUL]
|
// in both binaries and shared libraries, the version pattern is [NUL]3.11.2[NUL]
|
||||||
@ -356,7 +357,7 @@ var libpythonMatcher = fileNameTemplateVersionMatcher(
|
|||||||
pythonVersionTemplate,
|
pythonVersionTemplate,
|
||||||
)
|
)
|
||||||
|
|
||||||
var rubyMatcher = fileContentsVersionMatcher(
|
var rubyMatcher = FileContentsVersionMatcher(
|
||||||
// ruby 3.2.1 (2023-02-08 revision 31819e82c8) [x86_64-linux]
|
// ruby 3.2.1 (2023-02-08 revision 31819e82c8) [x86_64-linux]
|
||||||
// ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5) [x86_64-linux]
|
// ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5) [x86_64-linux]
|
||||||
`(?m)ruby (?P<version>[0-9]+\.[0-9]+\.[0-9]+(p[0-9]+)?) `)
|
`(?m)ruby (?P<version>[0-9]+\.[0-9]+\.[0-9]+(p[0-9]+)?) `)
|
||||||
|
|||||||
@ -3,12 +3,15 @@ package binary
|
|||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/anchore/packageurl-go"
|
||||||
"github.com/anchore/syft/syft/cpe"
|
"github.com/anchore/syft/syft/cpe"
|
||||||
"github.com/anchore/syft/syft/file"
|
"github.com/anchore/syft/syft/file"
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newPackage(classifier classifier, location file.Location, matchMetadata map[string]string) *pkg.Package {
|
var emptyPURL = packageurl.PackageURL{}
|
||||||
|
|
||||||
|
func newPackage(classifier Classifier, location file.Location, matchMetadata map[string]string) *pkg.Package {
|
||||||
version, ok := matchMetadata["version"]
|
version, ok := matchMetadata["version"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
@ -42,20 +45,12 @@ func newPackage(classifier classifier, location file.Location, matchMetadata map
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if classifier.Type != "" {
|
|
||||||
p.Type = classifier.Type
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(classifier.PURL, emptyPURL) {
|
if !reflect.DeepEqual(classifier.PURL, emptyPURL) {
|
||||||
purl := classifier.PURL
|
purl := classifier.PURL
|
||||||
purl.Version = version
|
purl.Version = version
|
||||||
p.PURL = purl.ToString()
|
p.PURL = purl.ToString()
|
||||||
}
|
}
|
||||||
|
|
||||||
if classifier.Language != "" {
|
|
||||||
p.Language = classifier.Language
|
|
||||||
}
|
|
||||||
|
|
||||||
p.SetID()
|
p.SetID()
|
||||||
|
|
||||||
return &p
|
return &p
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
blah
|
||||||
|
foobar 1.2.3
|
||||||
|
baz
|
||||||
@ -44,7 +44,7 @@ func ImageCatalogers(cfg Config) []pkg.Cataloger {
|
|||||||
return filterCatalogers([]pkg.Cataloger{
|
return filterCatalogers([]pkg.Cataloger{
|
||||||
arch.NewDBCataloger(),
|
arch.NewDBCataloger(),
|
||||||
alpine.NewDBCataloger(),
|
alpine.NewDBCataloger(),
|
||||||
binary.NewCataloger(),
|
binary.NewCataloger(cfg.Binary),
|
||||||
cpp.NewConanInfoCataloger(),
|
cpp.NewConanInfoCataloger(),
|
||||||
debian.NewDBCataloger(),
|
debian.NewDBCataloger(),
|
||||||
dotnet.NewDotnetPortableExecutableCataloger(),
|
dotnet.NewDotnetPortableExecutableCataloger(),
|
||||||
@ -68,7 +68,7 @@ func DirectoryCatalogers(cfg Config) []pkg.Cataloger {
|
|||||||
return filterCatalogers([]pkg.Cataloger{
|
return filterCatalogers([]pkg.Cataloger{
|
||||||
arch.NewDBCataloger(),
|
arch.NewDBCataloger(),
|
||||||
alpine.NewDBCataloger(),
|
alpine.NewDBCataloger(),
|
||||||
binary.NewCataloger(),
|
binary.NewCataloger(cfg.Binary),
|
||||||
cpp.NewConanCataloger(),
|
cpp.NewConanCataloger(),
|
||||||
dart.NewPubspecLockCataloger(),
|
dart.NewPubspecLockCataloger(),
|
||||||
debian.NewDBCataloger(),
|
debian.NewDBCataloger(),
|
||||||
@ -107,7 +107,7 @@ func AllCatalogers(cfg Config) []pkg.Cataloger {
|
|||||||
return filterCatalogers([]pkg.Cataloger{
|
return filterCatalogers([]pkg.Cataloger{
|
||||||
arch.NewDBCataloger(),
|
arch.NewDBCataloger(),
|
||||||
alpine.NewDBCataloger(),
|
alpine.NewDBCataloger(),
|
||||||
binary.NewCataloger(),
|
binary.NewCataloger(cfg.Binary),
|
||||||
cpp.NewConanCataloger(),
|
cpp.NewConanCataloger(),
|
||||||
dart.NewPubspecLockCataloger(),
|
dart.NewPubspecLockCataloger(),
|
||||||
debian.NewDBCataloger(),
|
debian.NewDBCataloger(),
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package cataloger
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/anchore/syft/syft/cataloging"
|
"github.com/anchore/syft/syft/cataloging"
|
||||||
|
"github.com/anchore/syft/syft/pkg/cataloger/binary"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/golang"
|
"github.com/anchore/syft/syft/pkg/cataloger/golang"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/java"
|
"github.com/anchore/syft/syft/pkg/cataloger/java"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/javascript"
|
"github.com/anchore/syft/syft/pkg/cataloger/javascript"
|
||||||
@ -17,6 +18,7 @@ type Config struct {
|
|||||||
Python python.CatalogerConfig
|
Python python.CatalogerConfig
|
||||||
Java java.ArchiveCatalogerConfig
|
Java java.ArchiveCatalogerConfig
|
||||||
Javascript javascript.CatalogerConfig
|
Javascript javascript.CatalogerConfig
|
||||||
|
Binary binary.CatalogerConfig
|
||||||
Catalogers []string
|
Catalogers []string
|
||||||
Parallelism int
|
Parallelism int
|
||||||
ExcludeBinaryOverlapByOwnership bool
|
ExcludeBinaryOverlapByOwnership bool
|
||||||
@ -30,6 +32,7 @@ func DefaultConfig() Config {
|
|||||||
Python: python.DefaultCatalogerConfig(),
|
Python: python.DefaultCatalogerConfig(),
|
||||||
Java: java.DefaultArchiveCatalogerConfig(),
|
Java: java.DefaultArchiveCatalogerConfig(),
|
||||||
Javascript: javascript.DefaultCatalogerConfig(),
|
Javascript: javascript.DefaultCatalogerConfig(),
|
||||||
|
Binary: binary.DefaultCatalogerConfig(),
|
||||||
ExcludeBinaryOverlapByOwnership: true,
|
ExcludeBinaryOverlapByOwnership: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user