mirror of
https://github.com/anchore/syft.git
synced 2026-02-12 02:26:42 +01:00
wire up cli config
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
parent
41aa6f6753
commit
a05608a4c8
@ -147,6 +147,13 @@ func (cfg Catalog) ToFilesConfig() filecataloging.Config {
|
|||||||
c.Content.SkipFilesAboveSize = cfg.File.Content.SkipFilesAboveSize
|
c.Content.SkipFilesAboveSize = cfg.File.Content.SkipFilesAboveSize
|
||||||
c.Executable.Globs = cfg.File.Executable.Globs
|
c.Executable.Globs = cfg.File.Executable.Globs
|
||||||
|
|
||||||
|
// symbol capture configuration
|
||||||
|
c.Executable.Symbols.CaptureScope = cfg.File.Executable.Symbols.CaptureScope
|
||||||
|
c.Executable.Symbols.Types = cfg.File.Executable.Symbols.Types
|
||||||
|
c.Executable.Symbols.Go.StandardLibrary = cfg.File.Executable.Symbols.Go.StandardLibrary
|
||||||
|
c.Executable.Symbols.Go.ExtendedStandardLibrary = cfg.File.Executable.Symbols.Go.ExtendedStandardLibrary
|
||||||
|
c.Executable.Symbols.Go.ThirdPartyModules = cfg.File.Executable.Symbols.Go.ThirdPartyModules
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/anchore/clio"
|
"github.com/anchore/clio"
|
||||||
intFile "github.com/anchore/syft/internal/file"
|
intFile "github.com/anchore/syft/internal/file"
|
||||||
"github.com/anchore/syft/syft/file"
|
"github.com/anchore/syft/syft/file"
|
||||||
|
"github.com/anchore/syft/syft/file/cataloger/executable"
|
||||||
)
|
)
|
||||||
|
|
||||||
type fileConfig struct {
|
type fileConfig struct {
|
||||||
@ -28,11 +29,27 @@ type fileContent struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type fileExecutable struct {
|
type fileExecutable struct {
|
||||||
Globs []string `yaml:"globs" json:"globs" mapstructure:"globs"`
|
Globs []string `yaml:"globs" json:"globs" mapstructure:"globs"`
|
||||||
|
Symbols fileSymbolConfig `yaml:"symbols" json:"symbols" mapstructure:"symbols"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type fileSymbolConfig struct {
|
||||||
|
CaptureScope []executable.SymbolCaptureScope `yaml:"capture" json:"capture" mapstructure:"capture"`
|
||||||
|
Types []string `yaml:"types" json:"types" mapstructure:"types"`
|
||||||
|
Go fileGoSymbolConfig `yaml:"go" json:"go" mapstructure:"go"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type fileGoSymbolConfig struct {
|
||||||
|
StandardLibrary bool `yaml:"standard-library" json:"standard-library" mapstructure:"standard-library"`
|
||||||
|
ExtendedStandardLibrary bool `yaml:"extended-standard-library" json:"extended-standard-library" mapstructure:"extended-standard-library"`
|
||||||
|
ThirdPartyModules bool `yaml:"third-party-modules" json:"third-party-modules" mapstructure:"third-party-modules"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultFileConfig() fileConfig {
|
func defaultFileConfig() fileConfig {
|
||||||
return fileConfig{
|
api := executable.DefaultConfig()
|
||||||
|
|
||||||
|
// start with API defaults and override CLI-specific values
|
||||||
|
cfg := fileConfig{
|
||||||
Metadata: fileMetadata{
|
Metadata: fileMetadata{
|
||||||
Selection: file.FilesOwnedByPackageSelection,
|
Selection: file.FilesOwnedByPackageSelection,
|
||||||
Digests: []string{"sha1", "sha256"},
|
Digests: []string{"sha1", "sha256"},
|
||||||
@ -41,9 +58,19 @@ func defaultFileConfig() fileConfig {
|
|||||||
SkipFilesAboveSize: 250 * intFile.KB,
|
SkipFilesAboveSize: 250 * intFile.KB,
|
||||||
},
|
},
|
||||||
Executable: fileExecutable{
|
Executable: fileExecutable{
|
||||||
Globs: nil,
|
Globs: api.Globs,
|
||||||
|
Symbols: fileSymbolConfig{
|
||||||
|
CaptureScope: api.Symbols.CaptureScope,
|
||||||
|
Types: api.Symbols.Types,
|
||||||
|
Go: fileGoSymbolConfig{
|
||||||
|
StandardLibrary: api.Symbols.Go.StandardLibrary,
|
||||||
|
ExtendedStandardLibrary: api.Symbols.Go.ExtendedStandardLibrary,
|
||||||
|
ThirdPartyModules: api.Symbols.Go.ThirdPartyModules,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ interface {
|
var _ interface {
|
||||||
@ -64,7 +91,7 @@ func (c *fileConfig) PostLoad() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *fileConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
func (c *fileConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||||
descriptions.Add(&c.Metadata.Selection, `select which files should be captured by the file-metadata cataloger and included in the SBOM.
|
descriptions.Add(&c.Metadata.Selection, `select which files should be captured by the file-metadata cataloger and included in the SBOM.
|
||||||
Options include:
|
Options include:
|
||||||
- "all": capture all files from the search space
|
- "all": capture all files from the search space
|
||||||
- "owned-by-package": capture only files owned by packages
|
- "owned-by-package": capture only files owned by packages
|
||||||
@ -75,4 +102,13 @@ Options include:
|
|||||||
descriptions.Add(&c.Content.Globs, `file globs for the cataloger to match on`)
|
descriptions.Add(&c.Content.Globs, `file globs for the cataloger to match on`)
|
||||||
|
|
||||||
descriptions.Add(&c.Executable.Globs, `file globs for the cataloger to match on`)
|
descriptions.Add(&c.Executable.Globs, `file globs for the cataloger to match on`)
|
||||||
|
|
||||||
|
// symbol capture configuration
|
||||||
|
descriptions.Add(&c.Executable.Symbols.CaptureScope, `the scope of symbols to capture from executables (options: "golang")`)
|
||||||
|
descriptions.Add(&c.Executable.Symbols.Types, `the types of symbols to capture, relative to "go tool nm" output (options: "T", "t", "R", "r", "D", "d", "B", "b", "C", "U")`)
|
||||||
|
|
||||||
|
// go symbol configuration
|
||||||
|
descriptions.Add(&c.Executable.Symbols.Go.StandardLibrary, `capture Go standard library symbols (e.g. "fmt", "net/http")`)
|
||||||
|
descriptions.Add(&c.Executable.Symbols.Go.ExtendedStandardLibrary, `capture extended Go standard library symbols (e.g. "golang.org/x/net")`)
|
||||||
|
descriptions.Add(&c.Executable.Symbols.Go.ThirdPartyModules, `capture third-party module symbols (e.g. "github.com/spf13/cobra")`)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,7 +31,8 @@ func TestAllPackageCatalogersReachableInTasks(t *testing.T) {
|
|||||||
taskFactories := task.DefaultPackageTaskFactories()
|
taskFactories := task.DefaultPackageTaskFactories()
|
||||||
taskTagsByName := make(map[string][]string)
|
taskTagsByName := make(map[string][]string)
|
||||||
for _, factory := range taskFactories {
|
for _, factory := range taskFactories {
|
||||||
tsk := factory(task.DefaultCatalogingFactoryConfig())
|
tsk, err := factory(task.DefaultCatalogingFactoryConfig())
|
||||||
|
require.NoError(t, err)
|
||||||
if taskTagsByName[tsk.Name()] != nil {
|
if taskTagsByName[tsk.Name()] != nil {
|
||||||
t.Fatalf("duplicate task name: %q", tsk.Name())
|
t.Fatalf("duplicate task name: %q", tsk.Name())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package task
|
package task
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
@ -8,7 +9,7 @@ import (
|
|||||||
"github.com/scylladb/go-set/strset"
|
"github.com/scylladb/go-set/strset"
|
||||||
)
|
)
|
||||||
|
|
||||||
type factory func(cfg CatalogingFactoryConfig) Task
|
type factory func(cfg CatalogingFactoryConfig) (Task, error)
|
||||||
|
|
||||||
type Factories []factory
|
type Factories []factory
|
||||||
|
|
||||||
@ -16,9 +17,13 @@ func (f Factories) Tasks(cfg CatalogingFactoryConfig) ([]Task, error) {
|
|||||||
var allTasks []Task
|
var allTasks []Task
|
||||||
taskNames := strset.New()
|
taskNames := strset.New()
|
||||||
duplicateTaskNames := strset.New()
|
duplicateTaskNames := strset.New()
|
||||||
var err error
|
var errs []error
|
||||||
for _, fact := range f {
|
for _, fact := range f {
|
||||||
tsk := fact(cfg)
|
tsk, err := fact(cfg)
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
if tsk == nil {
|
if tsk == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -33,8 +38,8 @@ func (f Factories) Tasks(cfg CatalogingFactoryConfig) ([]Task, error) {
|
|||||||
if duplicateTaskNames.Size() > 0 {
|
if duplicateTaskNames.Size() > 0 {
|
||||||
names := duplicateTaskNames.List()
|
names := duplicateTaskNames.List()
|
||||||
sort.Strings(names)
|
sort.Strings(names)
|
||||||
err = fmt.Errorf("duplicate cataloger task names: %v", strings.Join(names, ", "))
|
errs = append(errs, fmt.Errorf("duplicate cataloger task names: %v", strings.Join(names, ", ")))
|
||||||
}
|
}
|
||||||
|
|
||||||
return allTasks, err
|
return allTasks, errors.Join(errs...)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,8 +26,8 @@ func DefaultFileTaskFactories() Factories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newFileDigestCatalogerTaskFactory(tags ...string) factory {
|
func newFileDigestCatalogerTaskFactory(tags ...string) factory {
|
||||||
return func(cfg CatalogingFactoryConfig) Task {
|
return func(cfg CatalogingFactoryConfig) (Task, error) {
|
||||||
return newFileDigestCatalogerTask(cfg.FilesConfig.Selection, cfg.FilesConfig.Hashers, tags...)
|
return newFileDigestCatalogerTask(cfg.FilesConfig.Selection, cfg.FilesConfig.Hashers, tags...), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,8 +57,8 @@ func newFileDigestCatalogerTask(selection file.Selection, hashers []crypto.Hash,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newFileMetadataCatalogerTaskFactory(tags ...string) factory {
|
func newFileMetadataCatalogerTaskFactory(tags ...string) factory {
|
||||||
return func(cfg CatalogingFactoryConfig) Task {
|
return func(cfg CatalogingFactoryConfig) (Task, error) {
|
||||||
return newFileMetadataCatalogerTask(cfg.FilesConfig.Selection, tags...)
|
return newFileMetadataCatalogerTask(cfg.FilesConfig.Selection, tags...), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,8 +88,8 @@ func newFileMetadataCatalogerTask(selection file.Selection, tags ...string) Task
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newFileContentCatalogerTaskFactory(tags ...string) factory {
|
func newFileContentCatalogerTaskFactory(tags ...string) factory {
|
||||||
return func(cfg CatalogingFactoryConfig) Task {
|
return func(cfg CatalogingFactoryConfig) (Task, error) {
|
||||||
return newFileContentCatalogerTask(cfg.FilesConfig.Content, tags...)
|
return newFileContentCatalogerTask(cfg.FilesConfig.Content, tags...), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,12 +114,16 @@ func newFileContentCatalogerTask(cfg filecontent.Config, tags ...string) Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newExecutableCatalogerTaskFactory(tags ...string) factory {
|
func newExecutableCatalogerTaskFactory(tags ...string) factory {
|
||||||
return func(cfg CatalogingFactoryConfig) Task {
|
return func(cfg CatalogingFactoryConfig) (Task, error) {
|
||||||
return newExecutableCatalogerTask(cfg.FilesConfig.Selection, cfg.FilesConfig.Executable, tags...)
|
return newExecutableCatalogerTask(cfg.FilesConfig.Selection, cfg.FilesConfig.Executable, tags...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newExecutableCatalogerTask(selection file.Selection, cfg executable.Config, tags ...string) Task {
|
func newExecutableCatalogerTask(selection file.Selection, cfg executable.Config, tags ...string) (Task, error) {
|
||||||
|
if err := cfg.Validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
fn := func(ctx context.Context, resolver file.Resolver, builder sbomsync.Builder) error {
|
fn := func(ctx context.Context, resolver file.Resolver, builder sbomsync.Builder) error {
|
||||||
if selection == file.NoFilesSelection {
|
if selection == file.NoFilesSelection {
|
||||||
return nil
|
return nil
|
||||||
@ -136,7 +140,7 @@ func newExecutableCatalogerTask(selection file.Selection, cfg executable.Config,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewTask("file-executable-cataloger", fn, commonFileTags(tags)...)
|
return NewTask("file-executable-cataloger", fn, commonFileTags(tags)...), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this should be replaced with a fix that allows passing a coordinate or location iterator to the cataloger
|
// TODO: this should be replaced with a fix that allows passing a coordinate or location iterator to the cataloger
|
||||||
|
|||||||
@ -21,14 +21,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func newPackageTaskFactory(catalogerFactory func(CatalogingFactoryConfig) pkg.Cataloger, tags ...string) factory {
|
func newPackageTaskFactory(catalogerFactory func(CatalogingFactoryConfig) pkg.Cataloger, tags ...string) factory {
|
||||||
return func(cfg CatalogingFactoryConfig) Task {
|
return func(cfg CatalogingFactoryConfig) (Task, error) {
|
||||||
return NewPackageTask(cfg, catalogerFactory(cfg), tags...)
|
return NewPackageTask(cfg, catalogerFactory(cfg), tags...), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSimplePackageTaskFactory(catalogerFactory func() pkg.Cataloger, tags ...string) factory {
|
func newSimplePackageTaskFactory(catalogerFactory func() pkg.Cataloger, tags ...string) factory {
|
||||||
return func(cfg CatalogingFactoryConfig) Task {
|
return func(cfg CatalogingFactoryConfig) (Task, error) {
|
||||||
return NewPackageTask(cfg, catalogerFactory(), tags...)
|
return NewPackageTask(cfg, catalogerFactory(), tags...), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1285,7 +1285,7 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"description": "Symbols captures the selection from the symbol table found in the binary.\nSymbols []Symbol `json:\"symbols,omitempty\" yaml:\"symbols\" mapstructure:\"symbols\"`"
|
"description": "Symbols captures the selection from the symbol table found in the binary."
|
||||||
},
|
},
|
||||||
"toolchains": {
|
"toolchains": {
|
||||||
"items": {
|
"items": {
|
||||||
@ -4238,13 +4238,16 @@
|
|||||||
"Toolchain": {
|
"Toolchain": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"description": "Name is the name of the toolchain (e.g., \"gcc\", \"clang\", \"ld\", etc.)."
|
||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"description": "Version is the version of the toolchain."
|
||||||
},
|
},
|
||||||
"kind": {
|
"kind": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"description": "Kind indicates the type of toolchain (e.g., compiler, linker, runtime)."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|||||||
@ -1285,7 +1285,7 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"description": "Symbols captures the selection from the symbol table found in the binary.\nSymbols []Symbol `json:\"symbols,omitempty\" yaml:\"symbols\" mapstructure:\"symbols\"`"
|
"description": "Symbols captures the selection from the symbol table found in the binary."
|
||||||
},
|
},
|
||||||
"toolchains": {
|
"toolchains": {
|
||||||
"items": {
|
"items": {
|
||||||
@ -4238,13 +4238,16 @@
|
|||||||
"Toolchain": {
|
"Toolchain": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"description": "Name is the name of the toolchain (e.g., \"gcc\", \"clang\", \"ld\", etc.)."
|
||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"description": "Version is the version of the toolchain."
|
||||||
},
|
},
|
||||||
"kind": {
|
"kind": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"description": "Kind indicates the type of toolchain (e.g., compiler, linker, runtime)."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|||||||
@ -24,20 +24,11 @@ import (
|
|||||||
"github.com/anchore/syft/syft/internal/unionreader"
|
"github.com/anchore/syft/syft/internal/unionreader"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SymbolCaptureScope defines the scope of symbols to capture from executables. For the meantime only golang binaries are supported,
|
||||||
|
// however, in the future this can be expanded to include rust audit binaries, libraries only, applications only, or all binaries.
|
||||||
type SymbolCaptureScope string
|
type SymbolCaptureScope string
|
||||||
|
|
||||||
// type SymbolTypes string
|
const SymbolScopeGolang SymbolCaptureScope = "golang" // only binaries built with the golang toolchain
|
||||||
|
|
||||||
const (
|
|
||||||
SymbolScopeAll SymbolCaptureScope = "all" // any and all binaries
|
|
||||||
SymbolScopeLibraries SymbolCaptureScope = "libraries" // binaries with exported symbols
|
|
||||||
SymbolScopeApplications SymbolCaptureScope = "applications" // binaries with an entry point
|
|
||||||
SymbolScopeGolang SymbolCaptureScope = "golang" // only binaries built with the golang toolchain
|
|
||||||
SymbolScopeNone SymbolCaptureScope = "none" // do not capture any symbols
|
|
||||||
|
|
||||||
// SymbolTypeCode SymbolTypes = "code"
|
|
||||||
// SymbolTypeData SymbolTypes = "data"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
// MIMETypes are the MIME types that will be considered for executable cataloging.
|
// MIMETypes are the MIME types that will be considered for executable cataloging.
|
||||||
@ -90,6 +81,64 @@ type GoSymbolConfig struct {
|
|||||||
UnexportedSymbols bool `json:"unexported-symbols" yaml:"unexported-symbols" mapstructure:"unexported-symbols"`
|
UnexportedSymbols bool `json:"unexported-symbols" yaml:"unexported-symbols" mapstructure:"unexported-symbols"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate checks for logical configuration inconsistencies and returns an error if any are found.
|
||||||
|
func (c Config) Validate() error {
|
||||||
|
return c.Symbols.Validate()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks for logical configuration inconsistencies in symbol capture settings.
|
||||||
|
func (s SymbolConfig) Validate() error {
|
||||||
|
// validate that all CaptureScope values are valid
|
||||||
|
for _, scope := range s.CaptureScope {
|
||||||
|
if !isValidCaptureScope(scope) {
|
||||||
|
return fmt.Errorf("invalid symbol capture scope %q: valid values are %q", scope, SymbolScopeGolang)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate NM types if specified
|
||||||
|
if len(s.Types) > 0 {
|
||||||
|
for _, t := range s.Types {
|
||||||
|
if !isValidNMType(t) {
|
||||||
|
return fmt.Errorf("invalid NM type %q: valid values are %v", t, validNMTypes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remaining validations only apply when Go symbol capture is enabled
|
||||||
|
if !s.hasGolangScope() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// if Go symbol capture is enabled, at least one of exported/unexported must be true
|
||||||
|
if !s.Go.ExportedSymbols && !s.Go.UnexportedSymbols {
|
||||||
|
return fmt.Errorf("both exported-symbols and unexported-symbols are disabled; no Go symbols would be captured")
|
||||||
|
}
|
||||||
|
|
||||||
|
// if Go symbol capture is enabled, at least one module source must be enabled
|
||||||
|
if !s.Go.StandardLibrary && !s.Go.ExtendedStandardLibrary && !s.Go.ThirdPartyModules {
|
||||||
|
return fmt.Errorf("all module sources (standard-library, extended-standard-library, third-party-modules) are disabled; no meaningful Go symbols would be captured")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SymbolConfig) hasGolangScope() bool {
|
||||||
|
for _, scope := range s.CaptureScope {
|
||||||
|
if scope == SymbolScopeGolang {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isValidCaptureScope(scope SymbolCaptureScope) bool {
|
||||||
|
switch scope { //nolint:gocritic // lets elect a pattern as if we'll have multiple options in the future...
|
||||||
|
case SymbolScopeGolang:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
type Cataloger struct {
|
type Cataloger struct {
|
||||||
config Config
|
config Config
|
||||||
}
|
}
|
||||||
@ -101,10 +150,8 @@ func DefaultConfig() Config {
|
|||||||
MIMETypes: m,
|
MIMETypes: m,
|
||||||
Globs: nil,
|
Globs: nil,
|
||||||
Symbols: SymbolConfig{
|
Symbols: SymbolConfig{
|
||||||
CaptureScope: []SymbolCaptureScope{
|
CaptureScope: []SymbolCaptureScope{}, // important! by default we do not capture any symbols unless explicitly configured
|
||||||
SymbolScopeGolang,
|
Types: []string{"T"}, // by default only capture "T" (text/code) symbols, since vulnerability data tracks accessible function symbols
|
||||||
},
|
|
||||||
Types: []string{"T", "t"},
|
|
||||||
Go: GoSymbolConfig{
|
Go: GoSymbolConfig{
|
||||||
StandardLibrary: true,
|
StandardLibrary: true,
|
||||||
ExtendedStandardLibrary: true,
|
ExtendedStandardLibrary: true,
|
||||||
|
|||||||
273
syft/file/cataloger/executable/config_test.go
Normal file
273
syft/file/cataloger/executable/config_test.go
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
package executable
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/file"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDefaultConfig_SymbolCaptureIsDisabled(t *testing.T) {
|
||||||
|
// symbol capture should be disabled by default -- this is an expensive operation space-wise in the SBOM
|
||||||
|
// and should only be enabled when explicitly configured by the user.
|
||||||
|
cfg := DefaultConfig()
|
||||||
|
|
||||||
|
require.Empty(t, cfg.Symbols.CaptureScope, "symbol capture should be disabled by default (empty capture scope)")
|
||||||
|
|
||||||
|
// verify that shouldCaptureSymbols returns false for any executable when using default config
|
||||||
|
assert.False(t, shouldCaptureSymbols(nil, cfg.Symbols), "should not capture symbols for nil executable")
|
||||||
|
assert.False(t, shouldCaptureSymbols(&file.Executable{}, cfg.Symbols), "should not capture symbols for empty executable")
|
||||||
|
assert.False(t, shouldCaptureSymbols(&file.Executable{
|
||||||
|
Toolchains: []file.Toolchain{
|
||||||
|
{Name: "go", Version: "1.21.0", Kind: file.ToolchainKindCompiler},
|
||||||
|
},
|
||||||
|
}, cfg.Symbols), "should not capture symbols even for go binaries when using default config")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfig_Validate(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
cfg Config
|
||||||
|
wantErr require.ErrorAssertionFunc
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "default config is valid",
|
||||||
|
cfg: DefaultConfig(),
|
||||||
|
wantErr: require.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid config with golang scope enabled",
|
||||||
|
cfg: Config{
|
||||||
|
Symbols: SymbolConfig{
|
||||||
|
CaptureScope: []SymbolCaptureScope{SymbolScopeGolang},
|
||||||
|
Go: GoSymbolConfig{
|
||||||
|
ExportedSymbols: true,
|
||||||
|
ThirdPartyModules: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: require.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty capture scope with Go settings is valid",
|
||||||
|
cfg: Config{
|
||||||
|
Symbols: SymbolConfig{
|
||||||
|
CaptureScope: []SymbolCaptureScope{},
|
||||||
|
Go: GoSymbolConfig{
|
||||||
|
ExportedSymbols: true,
|
||||||
|
ThirdPartyModules: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: require.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid capture scope",
|
||||||
|
cfg: Config{
|
||||||
|
Symbols: SymbolConfig{
|
||||||
|
CaptureScope: []SymbolCaptureScope{"invalid-scope"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: require.Error,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid NM type",
|
||||||
|
cfg: Config{
|
||||||
|
Symbols: SymbolConfig{
|
||||||
|
Types: []string{"X", "Y"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: require.Error,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid NM types",
|
||||||
|
cfg: Config{
|
||||||
|
Symbols: SymbolConfig{
|
||||||
|
Types: []string{"T", "t", "R"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: require.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "both exported and unexported disabled with golang scope",
|
||||||
|
cfg: Config{
|
||||||
|
Symbols: SymbolConfig{
|
||||||
|
CaptureScope: []SymbolCaptureScope{SymbolScopeGolang},
|
||||||
|
Go: GoSymbolConfig{
|
||||||
|
ExportedSymbols: false,
|
||||||
|
UnexportedSymbols: false,
|
||||||
|
ThirdPartyModules: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: require.Error,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "both exported and unexported disabled without golang scope is valid",
|
||||||
|
cfg: Config{
|
||||||
|
Symbols: SymbolConfig{
|
||||||
|
CaptureScope: []SymbolCaptureScope{},
|
||||||
|
Go: GoSymbolConfig{
|
||||||
|
ExportedSymbols: false,
|
||||||
|
UnexportedSymbols: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: require.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "all module sources disabled with golang scope",
|
||||||
|
cfg: Config{
|
||||||
|
Symbols: SymbolConfig{
|
||||||
|
CaptureScope: []SymbolCaptureScope{SymbolScopeGolang},
|
||||||
|
Go: GoSymbolConfig{
|
||||||
|
ExportedSymbols: true,
|
||||||
|
StandardLibrary: false,
|
||||||
|
ExtendedStandardLibrary: false,
|
||||||
|
ThirdPartyModules: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: require.Error,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "all module sources disabled without golang scope is valid",
|
||||||
|
cfg: Config{
|
||||||
|
Symbols: SymbolConfig{
|
||||||
|
CaptureScope: []SymbolCaptureScope{},
|
||||||
|
Go: GoSymbolConfig{
|
||||||
|
ExportedSymbols: true,
|
||||||
|
StandardLibrary: false,
|
||||||
|
ExtendedStandardLibrary: false,
|
||||||
|
ThirdPartyModules: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: require.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "only standard library enabled is valid",
|
||||||
|
cfg: Config{
|
||||||
|
Symbols: SymbolConfig{
|
||||||
|
CaptureScope: []SymbolCaptureScope{SymbolScopeGolang},
|
||||||
|
Go: GoSymbolConfig{
|
||||||
|
ExportedSymbols: true,
|
||||||
|
StandardLibrary: true,
|
||||||
|
ExtendedStandardLibrary: false,
|
||||||
|
ThirdPartyModules: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: require.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "only extended stdlib enabled is valid",
|
||||||
|
cfg: Config{
|
||||||
|
Symbols: SymbolConfig{
|
||||||
|
CaptureScope: []SymbolCaptureScope{SymbolScopeGolang},
|
||||||
|
Go: GoSymbolConfig{
|
||||||
|
ExportedSymbols: true,
|
||||||
|
StandardLibrary: false,
|
||||||
|
ExtendedStandardLibrary: true,
|
||||||
|
ThirdPartyModules: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: require.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "only third party modules enabled is valid",
|
||||||
|
cfg: Config{
|
||||||
|
Symbols: SymbolConfig{
|
||||||
|
CaptureScope: []SymbolCaptureScope{SymbolScopeGolang},
|
||||||
|
Go: GoSymbolConfig{
|
||||||
|
ExportedSymbols: true,
|
||||||
|
StandardLibrary: false,
|
||||||
|
ExtendedStandardLibrary: false,
|
||||||
|
ThirdPartyModules: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: require.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "only unexported symbols enabled is valid",
|
||||||
|
cfg: Config{
|
||||||
|
Symbols: SymbolConfig{
|
||||||
|
CaptureScope: []SymbolCaptureScope{SymbolScopeGolang},
|
||||||
|
Go: GoSymbolConfig{
|
||||||
|
ExportedSymbols: false,
|
||||||
|
UnexportedSymbols: true,
|
||||||
|
ThirdPartyModules: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: require.NoError,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
err := tt.cfg.Validate()
|
||||||
|
tt.wantErr(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSymbolConfig_Validate_ErrorMessages(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
cfg SymbolConfig
|
||||||
|
wantErrContain string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "invalid capture scope error message",
|
||||||
|
cfg: SymbolConfig{
|
||||||
|
CaptureScope: []SymbolCaptureScope{"rust"},
|
||||||
|
},
|
||||||
|
wantErrContain: "invalid symbol capture scope",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid NM type error message",
|
||||||
|
cfg: SymbolConfig{
|
||||||
|
Types: []string{"Z"},
|
||||||
|
},
|
||||||
|
wantErrContain: "invalid NM type",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "both export options disabled error message",
|
||||||
|
cfg: SymbolConfig{
|
||||||
|
CaptureScope: []SymbolCaptureScope{SymbolScopeGolang},
|
||||||
|
Go: GoSymbolConfig{
|
||||||
|
ExportedSymbols: false,
|
||||||
|
UnexportedSymbols: false,
|
||||||
|
ThirdPartyModules: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErrContain: "both exported-symbols and unexported-symbols are disabled",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "all module sources disabled error message",
|
||||||
|
cfg: SymbolConfig{
|
||||||
|
CaptureScope: []SymbolCaptureScope{SymbolScopeGolang},
|
||||||
|
Go: GoSymbolConfig{
|
||||||
|
ExportedSymbols: true,
|
||||||
|
StandardLibrary: false,
|
||||||
|
ExtendedStandardLibrary: false,
|
||||||
|
ThirdPartyModules: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErrContain: "all module sources",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
err := tt.cfg.Validate()
|
||||||
|
require.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), tt.wantErrContain)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -21,6 +21,21 @@ var goNMTypes = []string{
|
|||||||
"U", // referenced but undefined symbol
|
"U", // referenced but undefined symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validNMTypes returns the list of valid NM types for Go symbols.
|
||||||
|
func validNMTypes() []string {
|
||||||
|
return goNMTypes
|
||||||
|
}
|
||||||
|
|
||||||
|
// isValidNMType checks if the given type is a valid NM type.
|
||||||
|
func isValidNMType(t string) bool {
|
||||||
|
for _, valid := range goNMTypes {
|
||||||
|
if t == valid {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
vendorPrefix = "vendor/"
|
vendorPrefix = "vendor/"
|
||||||
extendedStdlibPrefix = "golang.org/x/"
|
extendedStdlibPrefix = "golang.org/x/"
|
||||||
|
|||||||
@ -11,20 +11,7 @@ func shouldCaptureSymbols(data *file.Executable, cfg SymbolConfig) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, scope := range cfg.CaptureScope {
|
for _, scope := range cfg.CaptureScope {
|
||||||
switch scope {
|
switch scope { //nolint:gocritic // lets elect a pattern as if we'll have multiple options in the future...
|
||||||
case SymbolScopeNone:
|
|
||||||
// explicit "none" means don't capture (but continue checking other scopes)
|
|
||||||
continue
|
|
||||||
case SymbolScopeAll:
|
|
||||||
return true
|
|
||||||
case SymbolScopeLibraries:
|
|
||||||
if data.HasExports {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case SymbolScopeApplications:
|
|
||||||
if data.HasEntrypoint {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case SymbolScopeGolang:
|
case SymbolScopeGolang:
|
||||||
if hasGolangToolchain(data) {
|
if hasGolangToolchain(data) {
|
||||||
return true
|
return true
|
||||||
|
|||||||
@ -19,7 +19,7 @@ func TestShouldCaptureSymbols(t *testing.T) {
|
|||||||
name: "nil data returns false",
|
name: "nil data returns false",
|
||||||
data: nil,
|
data: nil,
|
||||||
cfg: SymbolConfig{
|
cfg: SymbolConfig{
|
||||||
CaptureScope: []SymbolCaptureScope{SymbolScopeAll},
|
CaptureScope: []SymbolCaptureScope{SymbolScopeGolang},
|
||||||
},
|
},
|
||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
@ -31,62 +31,6 @@ func TestShouldCaptureSymbols(t *testing.T) {
|
|||||||
},
|
},
|
||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "scope none returns false",
|
|
||||||
data: &file.Executable{},
|
|
||||||
cfg: SymbolConfig{
|
|
||||||
CaptureScope: []SymbolCaptureScope{SymbolScopeNone},
|
|
||||||
},
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "scope all returns true",
|
|
||||||
data: &file.Executable{},
|
|
||||||
cfg: SymbolConfig{
|
|
||||||
CaptureScope: []SymbolCaptureScope{SymbolScopeAll},
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "scope libraries with exports returns true",
|
|
||||||
data: &file.Executable{
|
|
||||||
HasExports: true,
|
|
||||||
},
|
|
||||||
cfg: SymbolConfig{
|
|
||||||
CaptureScope: []SymbolCaptureScope{SymbolScopeLibraries},
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "scope libraries without exports returns false",
|
|
||||||
data: &file.Executable{
|
|
||||||
HasExports: false,
|
|
||||||
},
|
|
||||||
cfg: SymbolConfig{
|
|
||||||
CaptureScope: []SymbolCaptureScope{SymbolScopeLibraries},
|
|
||||||
},
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "scope applications with entrypoint returns true",
|
|
||||||
data: &file.Executable{
|
|
||||||
HasEntrypoint: true,
|
|
||||||
},
|
|
||||||
cfg: SymbolConfig{
|
|
||||||
CaptureScope: []SymbolCaptureScope{SymbolScopeApplications},
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "scope applications without entrypoint returns false",
|
|
||||||
data: &file.Executable{
|
|
||||||
HasEntrypoint: false,
|
|
||||||
},
|
|
||||||
cfg: SymbolConfig{
|
|
||||||
CaptureScope: []SymbolCaptureScope{SymbolScopeApplications},
|
|
||||||
},
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "scope golang with go toolchain returns true",
|
name: "scope golang with go toolchain returns true",
|
||||||
data: &file.Executable{
|
data: &file.Executable{
|
||||||
@ -119,38 +63,6 @@ func TestShouldCaptureSymbols(t *testing.T) {
|
|||||||
},
|
},
|
||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "multiple scopes with one match returns true",
|
|
||||||
data: &file.Executable{
|
|
||||||
HasExports: false,
|
|
||||||
HasEntrypoint: true,
|
|
||||||
},
|
|
||||||
cfg: SymbolConfig{
|
|
||||||
CaptureScope: []SymbolCaptureScope{SymbolScopeLibraries, SymbolScopeApplications},
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "multiple scopes with no match returns false",
|
|
||||||
data: &file.Executable{
|
|
||||||
HasExports: false,
|
|
||||||
HasEntrypoint: false,
|
|
||||||
},
|
|
||||||
cfg: SymbolConfig{
|
|
||||||
CaptureScope: []SymbolCaptureScope{SymbolScopeLibraries, SymbolScopeApplications},
|
|
||||||
},
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "none scope followed by matching scope returns true",
|
|
||||||
data: &file.Executable{
|
|
||||||
HasEntrypoint: true,
|
|
||||||
},
|
|
||||||
cfg: SymbolConfig{
|
|
||||||
CaptureScope: []SymbolCaptureScope{SymbolScopeNone, SymbolScopeApplications},
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "go toolchain among multiple toolchains returns true",
|
name: "go toolchain among multiple toolchains returns true",
|
||||||
data: &file.Executable{
|
data: &file.Executable{
|
||||||
@ -210,7 +122,6 @@ func TestHasGolangToolchain(t *testing.T) {
|
|||||||
Toolchains: []file.Toolchain{
|
Toolchains: []file.Toolchain{
|
||||||
{Name: "gcc", Version: "12.0.0", Kind: file.ToolchainKindCompiler},
|
{Name: "gcc", Version: "12.0.0", Kind: file.ToolchainKindCompiler},
|
||||||
{Name: "go", Version: "1.21.0", Kind: file.ToolchainKindCompiler},
|
{Name: "go", Version: "1.21.0", Kind: file.ToolchainKindCompiler},
|
||||||
{Name: "ld", Version: "2.38", Kind: file.ToolchainKindLinker},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: true,
|
want: true,
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
# Stage 1: Build binaries for multiple platforms
|
FROM golang:1.24
|
||||||
FROM golang:1.24 AS builder
|
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
@ -8,18 +7,8 @@ RUN go mod download
|
|||||||
|
|
||||||
COPY main.go ./
|
COPY main.go ./
|
||||||
|
|
||||||
# build ELF (Linux)
|
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /hello_linux .
|
||||||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o hello_linux .
|
|
||||||
|
|
||||||
# build Mach-O (macOS)
|
RUN CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o /hello_mac .
|
||||||
RUN CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o hello_mac .
|
|
||||||
|
|
||||||
# build PE (Windows)
|
RUN CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o /hello.exe .
|
||||||
RUN CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o hello.exe .
|
|
||||||
|
|
||||||
# Stage 2: Minimal image with just the binaries
|
|
||||||
FROM scratch
|
|
||||||
|
|
||||||
COPY --from=builder /app/hello_linux /
|
|
||||||
COPY --from=builder /app/hello_mac /
|
|
||||||
COPY --from=builder /app/hello.exe /
|
|
||||||
|
|||||||
@ -1 +1,6 @@
|
|||||||
FROM silkeh/clang:18@sha256:6984fdf656b270ff3129e339a25083e0f8355f681b72fdeb5407da21a9bbf74d
|
FROM alpine:3.21
|
||||||
|
|
||||||
|
RUN apk add --no-cache clang18 musl-dev make
|
||||||
|
|
||||||
|
# create symlink so 'clang' command works (Alpine installs as clang-18)
|
||||||
|
RUN ln -s /usr/bin/clang-18 /usr/bin/clang
|
||||||
|
|||||||
@ -7,15 +7,13 @@ type (
|
|||||||
// RelocationReadOnly indicates the RELRO security protection level applied to an ELF binary.
|
// RelocationReadOnly indicates the RELRO security protection level applied to an ELF binary.
|
||||||
RelocationReadOnly string
|
RelocationReadOnly string
|
||||||
|
|
||||||
// SymbolType string
|
// ToolchainKind represents the type of toolchain used to build the executable. Today only "compiler" is supported,
|
||||||
|
// however, this can be expanded in the future to include linkers, runtimes, etc.
|
||||||
ToolchainKind string
|
ToolchainKind string
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ToolchainKindCompiler ToolchainKind = "compiler"
|
ToolchainKindCompiler ToolchainKind = "compiler"
|
||||||
ToolchainKindLinker ToolchainKind = "linker"
|
|
||||||
ToolchainKindRuntime ToolchainKind = "runtime"
|
|
||||||
|
|
||||||
ELF ExecutableFormat = "elf" // Executable and Linkable Format used on Unix-like systems
|
ELF ExecutableFormat = "elf" // Executable and Linkable Format used on Unix-like systems
|
||||||
MachO ExecutableFormat = "macho" // Mach object file format used on macOS and iOS
|
MachO ExecutableFormat = "macho" // Mach object file format used on macOS and iOS
|
||||||
@ -44,7 +42,6 @@ type Executable struct {
|
|||||||
ELFSecurityFeatures *ELFSecurityFeatures `json:"elfSecurityFeatures,omitempty" yaml:"elfSecurityFeatures" mapstructure:"elfSecurityFeatures"`
|
ELFSecurityFeatures *ELFSecurityFeatures `json:"elfSecurityFeatures,omitempty" yaml:"elfSecurityFeatures" mapstructure:"elfSecurityFeatures"`
|
||||||
|
|
||||||
// Symbols captures the selection from the symbol table found in the binary.
|
// Symbols captures the selection from the symbol table found in the binary.
|
||||||
// Symbols []Symbol `json:"symbols,omitempty" yaml:"symbols" mapstructure:"symbols"`
|
|
||||||
SymbolNames []string `json:"symbolNames,omitempty" yaml:"symbolNames" mapstructure:"symbolNames"`
|
SymbolNames []string `json:"symbolNames,omitempty" yaml:"symbolNames" mapstructure:"symbolNames"`
|
||||||
|
|
||||||
// Toolchains captures information about the compiler, linker, runtime, or other toolchains used to build (or otherwise exist within) the executable.
|
// Toolchains captures information about the compiler, linker, runtime, or other toolchains used to build (or otherwise exist within) the executable.
|
||||||
@ -52,9 +49,14 @@ type Executable struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Toolchain struct {
|
type Toolchain struct {
|
||||||
Name string `json:"name" yaml:"name" mapstructure:"name"`
|
// Name is the name of the toolchain (e.g., "gcc", "clang", "ld", etc.).
|
||||||
Version string `json:"version,omitempty" yaml:"version,omitempty" mapstructure:"version"`
|
Name string `json:"name" yaml:"name" mapstructure:"name"`
|
||||||
Kind ToolchainKind `json:"kind" yaml:"kind" mapstructure:"kind"`
|
|
||||||
|
// Version is the version of the toolchain.
|
||||||
|
Version string `json:"version,omitempty" yaml:"version,omitempty" mapstructure:"version"`
|
||||||
|
|
||||||
|
// Kind indicates the type of toolchain (e.g., compiler, linker, runtime).
|
||||||
|
Kind ToolchainKind `json:"kind" yaml:"kind" mapstructure:"kind"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ELFSecurityFeatures captures security hardening and protection mechanisms in ELF binaries.
|
// ELFSecurityFeatures captures security hardening and protection mechanisms in ELF binaries.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user