github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/detector/ospkg/debian/debian.go (about)

     1  package debian
     2  
     3  import (
     4  	"time"
     5  
     6  	version "github.com/knqyf263/go-deb-version"
     7  	"golang.org/x/xerrors"
     8  	"k8s.io/utils/clock"
     9  
    10  	dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
    11  	"github.com/aquasecurity/trivy-db/pkg/vulnsrc/debian"
    12  	"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
    13  	osver "github.com/devseccon/trivy/pkg/detector/ospkg/version"
    14  	ftypes "github.com/devseccon/trivy/pkg/fanal/types"
    15  	"github.com/devseccon/trivy/pkg/log"
    16  	"github.com/devseccon/trivy/pkg/scanner/utils"
    17  	"github.com/devseccon/trivy/pkg/types"
    18  )
    19  
    20  var (
    21  	eolDates = map[string]time.Time{
    22  		"1.1": time.Date(1997, 6, 5, 23, 59, 59, 0, time.UTC),
    23  		"1.2": time.Date(1998, 6, 5, 23, 59, 59, 0, time.UTC),
    24  		"1.3": time.Date(1999, 3, 9, 23, 59, 59, 0, time.UTC),
    25  		"2.0": time.Date(2000, 3, 9, 23, 59, 59, 0, time.UTC),
    26  		"2.1": time.Date(2000, 10, 30, 23, 59, 59, 0, time.UTC),
    27  		"2.2": time.Date(2003, 7, 30, 23, 59, 59, 0, time.UTC),
    28  		"3.0": time.Date(2006, 6, 30, 23, 59, 59, 0, time.UTC),
    29  		"3.1": time.Date(2008, 3, 30, 23, 59, 59, 0, time.UTC),
    30  		"4.0": time.Date(2010, 2, 15, 23, 59, 59, 0, time.UTC),
    31  		"5.0": time.Date(2012, 2, 6, 23, 59, 59, 0, time.UTC),
    32  		// LTS
    33  		"6.0": time.Date(2016, 2, 29, 23, 59, 59, 0, time.UTC),
    34  		"7":   time.Date(2018, 5, 31, 23, 59, 59, 0, time.UTC),
    35  		"8":   time.Date(2020, 6, 30, 23, 59, 59, 0, time.UTC),
    36  		"9":   time.Date(2022, 6, 30, 23, 59, 59, 0, time.UTC),
    37  		"10":  time.Date(2024, 6, 30, 23, 59, 59, 0, time.UTC),
    38  		"11":  time.Date(2026, 8, 14, 23, 59, 59, 0, time.UTC),
    39  		"12":  time.Date(2028, 6, 10, 23, 59, 59, 0, time.UTC),
    40  		"13":  time.Date(3000, 1, 1, 23, 59, 59, 0, time.UTC),
    41  	}
    42  )
    43  
    44  type options struct {
    45  	clock clock.Clock
    46  }
    47  
    48  type option func(*options)
    49  
    50  func WithClock(c clock.Clock) option {
    51  	return func(opts *options) {
    52  		opts.clock = c
    53  	}
    54  }
    55  
    56  // Scanner implements the Debian scanner
    57  type Scanner struct {
    58  	vs debian.VulnSrc
    59  	*options
    60  }
    61  
    62  // NewScanner is the factory method to return Scanner
    63  func NewScanner(opts ...option) *Scanner {
    64  	o := &options{
    65  		clock: clock.RealClock{},
    66  	}
    67  
    68  	for _, opt := range opts {
    69  		opt(o)
    70  	}
    71  	return &Scanner{
    72  		vs:      debian.NewVulnSrc(),
    73  		options: o,
    74  	}
    75  }
    76  
    77  // Detect scans and return vulnerabilities using Debian scanner
    78  func (s *Scanner) Detect(osVer string, _ *ftypes.Repository, pkgs []ftypes.Package) ([]types.DetectedVulnerability, error) {
    79  	log.Logger.Info("Detecting Debian vulnerabilities...")
    80  
    81  	osVer = osver.Major(osVer)
    82  	log.Logger.Debugf("debian: os version: %s", osVer)
    83  	log.Logger.Debugf("debian: the number of packages: %d", len(pkgs))
    84  
    85  	var vulns []types.DetectedVulnerability
    86  	for _, pkg := range pkgs {
    87  		sourceVersion, err := version.NewVersion(utils.FormatSrcVersion(pkg))
    88  		if err != nil {
    89  			log.Logger.Debugf("Debian installed package version error: %s", err)
    90  			continue
    91  		}
    92  
    93  		advisories, err := s.vs.Get(osVer, pkg.SrcName)
    94  		if err != nil {
    95  			return nil, xerrors.Errorf("failed to get debian advisories: %w", err)
    96  		}
    97  
    98  		for _, adv := range advisories {
    99  			vuln := types.DetectedVulnerability{
   100  				VulnerabilityID:  adv.VulnerabilityID,
   101  				VendorIDs:        adv.VendorIDs,
   102  				PkgID:            pkg.ID,
   103  				PkgName:          pkg.Name,
   104  				InstalledVersion: utils.FormatVersion(pkg),
   105  				FixedVersion:     adv.FixedVersion,
   106  				PkgRef:           pkg.Ref,
   107  				Status:           adv.Status,
   108  				Layer:            pkg.Layer,
   109  				Custom:           adv.Custom,
   110  				DataSource:       adv.DataSource,
   111  			}
   112  
   113  			if adv.Severity != dbTypes.SeverityUnknown {
   114  				// Package-specific severity
   115  				vuln.SeveritySource = vulnerability.Debian
   116  				vuln.Vulnerability = dbTypes.Vulnerability{
   117  					Severity: adv.Severity.String(),
   118  				}
   119  			}
   120  
   121  			// It means unfixed vulnerability. We don't have to compare versions.
   122  			if adv.FixedVersion == "" {
   123  				vulns = append(vulns, vuln)
   124  				continue
   125  			}
   126  
   127  			var fixedVersion version.Version
   128  			fixedVersion, err = version.NewVersion(adv.FixedVersion)
   129  			if err != nil {
   130  				log.Logger.Debugf("Debian advisory package version error: %s", err)
   131  				continue
   132  			}
   133  
   134  			if sourceVersion.LessThan(fixedVersion) {
   135  				vulns = append(vulns, vuln)
   136  			}
   137  		}
   138  	}
   139  	return vulns, nil
   140  }
   141  
   142  // IsSupportedVersion checks if the version is supported.
   143  func (s *Scanner) IsSupportedVersion(osFamily ftypes.OSType, osVer string) bool {
   144  	return osver.Supported(s.clock, eolDates, osFamily, osver.Major(osVer))
   145  }