github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/scanner/langpkg/scan.go (about)

     1  package langpkg
     2  
     3  import (
     4  	"sort"
     5  
     6  	"golang.org/x/xerrors"
     7  
     8  	"github.com/devseccon/trivy/pkg/detector/library"
     9  	ftypes "github.com/devseccon/trivy/pkg/fanal/types"
    10  	"github.com/devseccon/trivy/pkg/log"
    11  	"github.com/devseccon/trivy/pkg/types"
    12  )
    13  
    14  var (
    15  	PkgTargets = map[ftypes.LangType]string{
    16  		ftypes.PythonPkg:   "Python",
    17  		ftypes.CondaPkg:    "Conda",
    18  		ftypes.GemSpec:     "Ruby",
    19  		ftypes.NodePkg:     "Node.js",
    20  		ftypes.Jar:         "Java",
    21  		ftypes.K8sUpstream: "Kubernetes",
    22  	}
    23  )
    24  
    25  type Scanner interface {
    26  	Packages(target types.ScanTarget, options types.ScanOptions) types.Results
    27  	Scan(target types.ScanTarget, options types.ScanOptions) (types.Results, error)
    28  }
    29  
    30  type scanner struct{}
    31  
    32  func NewScanner() Scanner {
    33  	return &scanner{}
    34  }
    35  
    36  func (s *scanner) Packages(target types.ScanTarget, _ types.ScanOptions) types.Results {
    37  	var results types.Results
    38  	for _, app := range target.Applications {
    39  		if len(app.Libraries) == 0 {
    40  			continue
    41  		}
    42  
    43  		results = append(results, types.Result{
    44  			Target:   targetName(app.Type, app.FilePath),
    45  			Class:    types.ClassLangPkg,
    46  			Type:     app.Type,
    47  			Packages: app.Libraries,
    48  		})
    49  	}
    50  	return results
    51  }
    52  
    53  func (s *scanner) Scan(target types.ScanTarget, _ types.ScanOptions) (types.Results, error) {
    54  	apps := target.Applications
    55  	log.Logger.Infof("Number of language-specific files: %d", len(apps))
    56  	if len(apps) == 0 {
    57  		return nil, nil
    58  	}
    59  
    60  	var results types.Results
    61  	printedTypes := make(map[ftypes.LangType]struct{})
    62  	for _, app := range apps {
    63  		if len(app.Libraries) == 0 {
    64  			continue
    65  		}
    66  
    67  		// Prevent the same log messages from being displayed many times for the same type.
    68  		if _, ok := printedTypes[app.Type]; !ok {
    69  			log.Logger.Infof("Detecting %s vulnerabilities...", app.Type)
    70  			printedTypes[app.Type] = struct{}{}
    71  		}
    72  
    73  		log.Logger.Debugf("Detecting library vulnerabilities, type: %s, path: %s", app.Type, app.FilePath)
    74  		vulns, err := library.Detect(app.Type, app.Libraries)
    75  		if err != nil {
    76  			return nil, xerrors.Errorf("failed vulnerability detection of libraries: %w", err)
    77  		} else if len(vulns) == 0 {
    78  			continue
    79  		}
    80  
    81  		results = append(results, types.Result{
    82  			Target:          targetName(app.Type, app.FilePath),
    83  			Vulnerabilities: vulns,
    84  			Class:           types.ClassLangPkg,
    85  			Type:            app.Type,
    86  		})
    87  	}
    88  	sort.Slice(results, func(i, j int) bool {
    89  		return results[i].Target < results[j].Target
    90  	})
    91  	return results, nil
    92  }
    93  
    94  func targetName(appType ftypes.LangType, filePath string) string {
    95  	if t, ok := PkgTargets[appType]; ok && filePath == "" {
    96  		// When the file path is empty, we will overwrite it with the pre-defined value.
    97  		return t
    98  	}
    99  	return filePath
   100  }