142 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package models
 | 
						|
 | 
						|
import (
 | 
						|
	"path/filepath"
 | 
						|
 | 
						|
	"github.com/aquasecurity/trivy/pkg/scanner/library"
 | 
						|
	"github.com/aquasecurity/trivy/pkg/vulnsrc/vulnerability"
 | 
						|
	"github.com/future-architect/vuls/util"
 | 
						|
	"golang.org/x/xerrors"
 | 
						|
 | 
						|
	"github.com/aquasecurity/go-dep-parser/pkg/types"
 | 
						|
	"github.com/knqyf263/go-version"
 | 
						|
)
 | 
						|
 | 
						|
// LibraryScanner has libraries information
 | 
						|
type LibraryScanner struct {
 | 
						|
	Path string
 | 
						|
	Libs []types.Library
 | 
						|
}
 | 
						|
 | 
						|
// Scan : scan target library
 | 
						|
func (s LibraryScanner) Scan() ([]VulnInfo, error) {
 | 
						|
	scanner := library.NewScanner(filepath.Base(string(s.Path)))
 | 
						|
	if scanner == nil {
 | 
						|
		return nil, xerrors.New("unknown file type")
 | 
						|
	}
 | 
						|
 | 
						|
	util.Log.Info("Updating library db...")
 | 
						|
	err := scanner.UpdateDB()
 | 
						|
	if err != nil {
 | 
						|
		return nil, xerrors.Errorf("failed to update %s advisories: %w", scanner.Type(), err)
 | 
						|
	}
 | 
						|
 | 
						|
	var vulnerabilities []VulnInfo
 | 
						|
	for _, pkg := range s.Libs {
 | 
						|
		v, err := version.NewVersion(pkg.Version)
 | 
						|
		if err != nil {
 | 
						|
			util.Log.Debugf("new version cant detected %s@%s", pkg.Name, pkg.Version)
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		tvulns, err := scanner.Detect(pkg.Name, v)
 | 
						|
		if err != nil {
 | 
						|
			return nil, xerrors.Errorf("failed to detect %s vulnerabilities: %w", scanner.Type(), err)
 | 
						|
		}
 | 
						|
 | 
						|
		vulns := s.convertFanalToVuln(tvulns)
 | 
						|
		vulnerabilities = append(vulnerabilities, vulns...)
 | 
						|
	}
 | 
						|
 | 
						|
	return vulnerabilities, nil
 | 
						|
}
 | 
						|
 | 
						|
func (s LibraryScanner) convertFanalToVuln(tvulns []vulnerability.DetectedVulnerability) (vulns []VulnInfo) {
 | 
						|
	for _, tvuln := range tvulns {
 | 
						|
		vinfo, _ := s.getVulnDetail(tvuln)
 | 
						|
		vulns = append(vulns, vinfo)
 | 
						|
	}
 | 
						|
	return vulns
 | 
						|
}
 | 
						|
 | 
						|
func (s LibraryScanner) getVulnDetail(tvuln vulnerability.DetectedVulnerability) (vinfo VulnInfo, err error) {
 | 
						|
	details, err := vulnerability.Get(tvuln.VulnerabilityID)
 | 
						|
	if err != nil {
 | 
						|
		return vinfo, err
 | 
						|
	} else if len(details) == 0 {
 | 
						|
		return vinfo, xerrors.Errorf("Unknown vulnID : %s", tvuln.VulnerabilityID)
 | 
						|
	}
 | 
						|
	vinfo.CveID = tvuln.VulnerabilityID
 | 
						|
	vinfo.CveContents = getCveContents(details)
 | 
						|
	if tvuln.FixedVersion != "" {
 | 
						|
 | 
						|
		vinfo.LibraryFixedIns = []LibraryFixedIn{
 | 
						|
			{
 | 
						|
				Key:     s.GetLibraryKey(),
 | 
						|
				Name:    tvuln.PkgName,
 | 
						|
				FixedIn: tvuln.FixedVersion,
 | 
						|
			},
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return vinfo, nil
 | 
						|
}
 | 
						|
 | 
						|
func getCveContents(details map[string]vulnerability.Vulnerability) (contents map[CveContentType]CveContent) {
 | 
						|
	contents = map[CveContentType]CveContent{}
 | 
						|
	for source, detail := range details {
 | 
						|
		refs := []Reference{}
 | 
						|
		for _, refURL := range detail.References {
 | 
						|
			refs = append(refs, Reference{Source: refURL, Link: refURL})
 | 
						|
		}
 | 
						|
 | 
						|
		content := CveContent{
 | 
						|
			Type:          NewCveContentType(source),
 | 
						|
			CveID:         detail.ID,
 | 
						|
			Title:         detail.Title,
 | 
						|
			Summary:       detail.Description,
 | 
						|
			Cvss3Score:    detail.CvssScoreV3,
 | 
						|
			Cvss3Severity: string(detail.SeverityV3),
 | 
						|
			Cvss2Score:    detail.CvssScore,
 | 
						|
			Cvss2Severity: string(detail.Severity),
 | 
						|
			References:    refs,
 | 
						|
 | 
						|
			//SourceLink    string            `json:"sourceLink"`
 | 
						|
			//Cvss2Vector   string            `json:"cvss2Vector"`
 | 
						|
			//Cvss3Vector   string            `json:"cvss3Vector"`
 | 
						|
			//Cvss3Severity string            `json:"cvss3Severity"`
 | 
						|
			//Cpes          []Cpe             `json:"cpes,omitempty"`
 | 
						|
			//CweIDs        []string          `json:"cweIDs,omitempty"`
 | 
						|
			//Published     time.Time         `json:"published"`
 | 
						|
			//LastModified  time.Time         `json:"lastModified"`
 | 
						|
			//Mitigation    string            `json:"mitigation"` // RedHat API
 | 
						|
			//Optional      map[string]string `json:"optional,omitempty"`
 | 
						|
		}
 | 
						|
		contents[NewCveContentType(source)] = content
 | 
						|
	}
 | 
						|
	return contents
 | 
						|
}
 | 
						|
 | 
						|
// LibraryMap is filename and library type
 | 
						|
var LibraryMap = map[string]string{
 | 
						|
	"package-lock.json": "node",
 | 
						|
	"yarn.lock":         "node",
 | 
						|
	"Gemfile.lock":      "ruby",
 | 
						|
	"Cargo.lock":        "rust",
 | 
						|
	"composer.json":     "php",
 | 
						|
	"Pipfile.lock":      "python",
 | 
						|
	"poetry.lock":       "python",
 | 
						|
}
 | 
						|
 | 
						|
// GetLibraryKey returns target library key
 | 
						|
func (s LibraryScanner) GetLibraryKey() string {
 | 
						|
	fileName := filepath.Base(s.Path)
 | 
						|
	return LibraryMap[fileName]
 | 
						|
}
 | 
						|
 | 
						|
// LibraryFixedIn has library fixed information
 | 
						|
type LibraryFixedIn struct {
 | 
						|
	Key     string `json:"key,omitempty"`
 | 
						|
	Name    string `json:"name,omitempty"`
 | 
						|
	FixedIn string `json:"fixedIn,omitempty"`
 | 
						|
}
 |