mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-23 07:29:00 -08:00
103 lines
2.7 KiB
Go
103 lines
2.7 KiB
Go
package node
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
version "github.com/knqyf263/go-version"
|
|
"github.com/aquasecurity/trivy/pkg/vulnsrc/vulnerability"
|
|
|
|
"golang.org/x/xerrors"
|
|
|
|
"github.com/aquasecurity/go-dep-parser/pkg/npm"
|
|
ptypes "github.com/aquasecurity/go-dep-parser/pkg/types"
|
|
"github.com/aquasecurity/go-dep-parser/pkg/yarn"
|
|
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
|
)
|
|
|
|
const (
|
|
ScannerTypeNpm = "npm"
|
|
ScannerTypeYarn = "yarn"
|
|
)
|
|
|
|
type Scanner struct {
|
|
db AdvisoryDB
|
|
scannerType string
|
|
}
|
|
|
|
func NewScanner(scannerType string) *Scanner {
|
|
return &Scanner{scannerType: scannerType}
|
|
}
|
|
|
|
func (s *Scanner) Detect(pkgName string, pkgVer *version.Version) ([]vulnerability.DetectedVulnerability, error) {
|
|
replacer := strings.NewReplacer(".alpha", "-alpha", ".beta", "-beta", ".rc", "-rc", " <", ", <", " >", ", >")
|
|
var vulns []vulnerability.DetectedVulnerability
|
|
for _, advisory := range s.db[pkgName] {
|
|
// e.g. <= 2.15.0 || >= 3.0.0 <= 3.8.2
|
|
// => {"<=2.15.0", ">= 3.0.0, <= 3.8.2"}
|
|
var vulnerableVersions []string
|
|
for _, version := range strings.Split(advisory.VulnerableVersions, " || ") {
|
|
version = strings.TrimSpace(version)
|
|
vulnerableVersions = append(vulnerableVersions, replacer.Replace(version))
|
|
}
|
|
|
|
if !utils.MatchVersions(pkgVer, vulnerableVersions) {
|
|
continue
|
|
}
|
|
|
|
var patchedVersions []string
|
|
for _, version := range strings.Split(advisory.PatchedVersions, " || ") {
|
|
version = strings.TrimSpace(version)
|
|
patchedVersions = append(patchedVersions, replacer.Replace(version))
|
|
}
|
|
|
|
if utils.MatchVersions(pkgVer, patchedVersions) {
|
|
continue
|
|
}
|
|
|
|
if len(advisory.Cves) == 0 {
|
|
advisory.Cves = []string{fmt.Sprintf("NSWG-ECO-%d", advisory.ID)}
|
|
}
|
|
|
|
for _, cveID := range advisory.Cves {
|
|
vuln := vulnerability.DetectedVulnerability{
|
|
VulnerabilityID: cveID,
|
|
PkgName: pkgName,
|
|
Title: strings.TrimSpace(advisory.Title),
|
|
InstalledVersion: pkgVer.String(),
|
|
FixedVersion: strings.Join(patchedVersions, ", "),
|
|
}
|
|
vulns = append(vulns, vuln)
|
|
}
|
|
}
|
|
return vulns, nil
|
|
}
|
|
|
|
func (s *Scanner) ParseLockfile(f *os.File) ([]ptypes.Library, error) {
|
|
if s.Type() == ScannerTypeNpm {
|
|
return s.parseNpm(f)
|
|
}
|
|
return s.parseYarn(f)
|
|
}
|
|
|
|
func (s *Scanner) parseNpm(f *os.File) ([]ptypes.Library, error) {
|
|
libs, err := npm.Parse(f)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("invalid package-lock.json format: %w", err)
|
|
}
|
|
return libs, nil
|
|
}
|
|
|
|
func (s *Scanner) parseYarn(f *os.File) ([]ptypes.Library, error) {
|
|
libs, err := yarn.Parse(f)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("invalid yarn.lock format: %w", err)
|
|
}
|
|
return libs, nil
|
|
}
|
|
|
|
func (s *Scanner) Type() string {
|
|
return s.scannerType
|
|
}
|