chore(deps): merge go-dep-parser into Trivy (#6094)

Signed-off-by: Arunprasad Rajkumar <arajkuma@redhat.com>
Signed-off-by: guoguangwu <guoguangwu@magic-shield.com>
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: knqyf263 <knqyf263@gmail.com>
Co-authored-by: Masahiro <mur4m4s4.331@gmail.com>
Co-authored-by: Tomoya Amachi <tomoya.amachi@gmail.com>
Co-authored-by: Masahiro <lomycisw@gmail.com>
Co-authored-by: Liz Rice <liz@lizrice.com>
Co-authored-by: Johannes <johannes@jitesoft.com>
Co-authored-by: aprp <doelaudi@gmail.com>
Co-authored-by: rahul2393 <rahulyadavsep92@gmail.com>
Co-authored-by: Arunprasad Rajkumar <ar.arunprasad@gmail.com>
Co-authored-by: Emrecan BATI <emrecanbati@gmail.com>
Co-authored-by: sherif84 <12298259+sherif84@users.noreply.github.com>
Co-authored-by: Sherif Fathalla <sfathall@akamai.com>
Co-authored-by: sherif <sherif.mailbox@gmail.com>
Co-authored-by: Sam Lane <samuel.lane@hotmail.com>
Co-authored-by: Ankush K <akhobragade@gmail.com>
Co-authored-by: Ankush K <akhobragade42@gmail.com>
Co-authored-by: Tauseef <tauseefmlk@gmail.com>
Co-authored-by: Daniel <danfaizer@gmail.com>
Co-authored-by: Matthieu MOREL <mmorel-35@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: afdesk <work@afdesk.com>
Co-authored-by: AndreyLevchenko <levchenko.andrey@gmail.com>
Co-authored-by: Kobus van Schoor <10784365+kobus-v-schoor@users.noreply.github.com>
Co-authored-by: Jan-Otto Kröpke <github@jkroepke.de>
Co-authored-by: jerbob92 <jerbob92@users.noreply.github.com>
Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com>
Co-authored-by: Shira Cohen <97398476+ShiraCohen33@users.noreply.github.com>
Co-authored-by: astevenson-microsoft <78623826+astevenson-microsoft@users.noreply.github.com>
Co-authored-by: Kyriakos Georgiou <kgeorgiou@users.noreply.github.com>
Co-authored-by: mycodeself <mycodeself@users.noreply.github.com>
Co-authored-by: DavidSalame <75929252+davidsalame1@users.noreply.github.com>
Co-authored-by: Tom Fay <tom@teamfay.co.uk>
Co-authored-by: Tom Fay <tomfay@microsoft.com>
Co-authored-by: François Poirotte <fpoirotte@users.noreply.github.com>
Co-authored-by: Guy Ben-Aharon <baguy3@gmail.com>
Co-authored-by: Catminusminus <37803616+Catminusminus@users.noreply.github.com>
Co-authored-by: Lior Vaisman Argon <97836016+VaismanLior@users.noreply.github.com>
Co-authored-by: Matthieu Maitre <mmaitre@microsoft.com>
Co-authored-by: Andrea Scarpino <andrea@scarpino.dev>
Co-authored-by: MorAlon1 <101275199+MorAlon1@users.noreply.github.com>
Co-authored-by: liorj-orca <96177663+liorj-orca@users.noreply.github.com>
Co-authored-by: Nikita Pivkin <100182843+nikpivkin@users.noreply.github.com>
Co-authored-by: guangwu <guoguangwu@magic-shield.com>
Co-authored-by: Nikita Pivkin <nikita.pivkin@smartforce.io>
Co-authored-by: DmitriyLewen <dmitriy.lewen@smartforce.io>
Co-authored-by: yuriShafet <5830215+yuriShafet@users.noreply.github.com>
Co-authored-by: Octogonapus <firey45@gmail.com>
This commit is contained in:
Teppei Fukuda
2024-02-19 15:16:35 +04:00
committed by GitHub
parent 32a02a95dd
commit 74dc5b6804
384 changed files with 63319 additions and 79 deletions

View File

@@ -0,0 +1,162 @@
package mod
import (
"fmt"
"io"
"regexp"
"strconv"
"strings"
"golang.org/x/exp/maps"
"golang.org/x/mod/modfile"
"golang.org/x/xerrors"
dio "github.com/aquasecurity/trivy/pkg/dependency/parser/io"
"github.com/aquasecurity/trivy/pkg/dependency/parser/types"
)
var (
// By convention, modules with a major version equal to or above v2
// have it as suffix in their module path.
VCSUrlMajorVersionSuffixRegex = regexp.MustCompile(`(/v[\d]+)$`)
// gopkg.in/user/pkg.v -> github.com/user/pkg
VCSUrlGoPkgInRegexWithUser = regexp.MustCompile(`^gopkg\.in/([^/]+)/([^.]+)\..*$`)
// gopkg.in without user segment
// Example: gopkg.in/pkg.v3 -> github.com/go-pkg/pkg
VCSUrlGoPkgInRegexWithoutUser = regexp.MustCompile(`^gopkg\.in/([^.]+)\..*$`)
)
type Parser struct {
replace bool // 'replace' represents if the 'replace' directive should be taken into account.
}
func NewParser(replace bool) types.Parser {
return &Parser{
replace: replace,
}
}
func (p *Parser) GetExternalRefs(path string) []types.ExternalRef {
if url := resolveVCSUrl(path); url != "" {
return []types.ExternalRef{
{
Type: types.RefVCS,
URL: url,
},
}
}
return nil
}
func resolveVCSUrl(modulePath string) string {
switch {
case strings.HasPrefix(modulePath, "github.com/"):
return "https://" + VCSUrlMajorVersionSuffixRegex.ReplaceAllString(modulePath, "")
case VCSUrlGoPkgInRegexWithUser.MatchString(modulePath):
return "https://" + VCSUrlGoPkgInRegexWithUser.ReplaceAllString(modulePath, "github.com/$1/$2")
case VCSUrlGoPkgInRegexWithoutUser.MatchString(modulePath):
return "https://" + VCSUrlGoPkgInRegexWithoutUser.ReplaceAllString(modulePath, "github.com/go-$1/$1")
}
return ""
}
// Parse parses a go.mod file
func (p *Parser) Parse(r dio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
libs := make(map[string]types.Library)
goModData, err := io.ReadAll(r)
if err != nil {
return nil, nil, xerrors.Errorf("file read error: %w", err)
}
modFileParsed, err := modfile.Parse("go.mod", goModData, nil)
if err != nil {
return nil, nil, xerrors.Errorf("go.mod parse error: %w", err)
}
skipIndirect := true
if modFileParsed.Go != nil { // Old go.mod file may not include the go version. Go version for these files is less than 1.17
skipIndirect = lessThan117(modFileParsed.Go.Version)
}
for _, require := range modFileParsed.Require {
// Skip indirect dependencies less than Go 1.17
if skipIndirect && require.Indirect {
continue
}
libs[require.Mod.Path] = types.Library{
ID: ModuleID(require.Mod.Path, require.Mod.Version[1:]),
Name: require.Mod.Path,
Version: require.Mod.Version[1:],
Indirect: require.Indirect,
ExternalReferences: p.GetExternalRefs(require.Mod.Path),
}
}
// No need to evaluate the 'replace' directive for indirect dependencies
if p.replace {
for _, rep := range modFileParsed.Replace {
// Check if replaced path is actually in our libs.
old, ok := libs[rep.Old.Path]
if !ok {
continue
}
// If the replace directive has a version on the left side, make sure it matches the version that was imported.
if rep.Old.Version != "" && old.Version != rep.Old.Version[1:] {
continue
}
// Only support replace directive with version on the right side.
// Directive without version is a local path.
if rep.New.Version == "" {
// Delete old lib, since it's a local path now.
delete(libs, rep.Old.Path)
continue
}
// Delete old lib, in case the path has changed.
delete(libs, rep.Old.Path)
// Add replaced library to library register.
libs[rep.New.Path] = types.Library{
ID: ModuleID(rep.New.Path, rep.New.Version[1:]),
Name: rep.New.Path,
Version: rep.New.Version[1:],
Indirect: old.Indirect,
ExternalReferences: p.GetExternalRefs(rep.New.Path),
}
}
}
return maps.Values(libs), nil, nil
}
// Check if the Go version is less than 1.17
func lessThan117(ver string) bool {
ss := strings.Split(ver, ".")
if len(ss) != 2 {
return false
}
major, err := strconv.Atoi(ss[0])
if err != nil {
return false
}
minor, err := strconv.Atoi(ss[1])
if err != nil {
return false
}
return major <= 1 && minor < 17
}
// ModuleID returns a module ID according the Go way.
// Format: <module_name>@v<module_version>
// e.g. github.com/aquasecurity/go-dep-parser@v0.0.0-20230130190635-5e31092b0621
func ModuleID(name, version string) string {
return fmt.Sprintf("%s@v%s", name, version)
}