github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/pkg/platform/model/cve.go (about)

     1  package model
     2  
     3  import (
     4  	"github.com/ActiveState/cli/internal/errs"
     5  	"github.com/ActiveState/cli/internal/locale"
     6  	"github.com/ActiveState/cli/pkg/platform/api/mediator"
     7  	"github.com/ActiveState/cli/pkg/platform/api/mediator/model"
     8  	"github.com/ActiveState/cli/pkg/platform/api/mediator/request"
     9  	"github.com/ActiveState/cli/pkg/platform/authentication"
    10  	"github.com/thoas/go-funk"
    11  )
    12  
    13  type Vulnerability model.Vulnerability
    14  type PackageVulnerability struct {
    15  	Name    string          `json:"name"`
    16  	Version string          `json:"version"`
    17  	Details []Vulnerability `json:"cves"`
    18  }
    19  
    20  // FetchProjectVulnerabilities returns the vulnerability information of a project
    21  func FetchProjectVulnerabilities(auth *authentication.Auth, org, project string) (*model.ProjectVulnerabilities, error) {
    22  	// This should be removed by https://www.pivotaltracker.com/story/show/176508740
    23  	if !auth.Authenticated() {
    24  		return nil, errs.AddTips(
    25  			locale.NewError("cve_needs_authentication"),
    26  			locale.T("auth_tip"),
    27  		)
    28  	}
    29  	req := request.VulnerabilitiesByProject(org, project)
    30  	var resp model.ProjectResponse
    31  	med := mediator.New(auth)
    32  	err := med.Run(req, &resp)
    33  	if err != nil {
    34  		return nil, errs.Wrap(err, "Failed to run mediator request.")
    35  	}
    36  
    37  	msg := resp.ProjectVulnerabilities.Message
    38  	if msg != nil {
    39  		if resp.ProjectVulnerabilities.TypeName == "NotFound" {
    40  			return nil, &ErrProjectNotFound{org, project}
    41  		}
    42  		return nil, locale.NewError("project_vulnerability_err", "Request to retrieve vulnerability information failed with error: {{.V0}}", *msg)
    43  	}
    44  
    45  	return &resp.ProjectVulnerabilities, nil
    46  }
    47  
    48  // FetchCommitVulnerabilities returns the vulnerability information of a project
    49  func FetchCommitVulnerabilities(auth *authentication.Auth, commitID string) (*model.CommitVulnerabilities, error) {
    50  	// This should be removed by https://www.pivotaltracker.com/story/show/176508740
    51  	if !auth.Authenticated() {
    52  		return nil, errs.AddTips(
    53  			locale.NewError("cve_needs_authentication"),
    54  			locale.T("auth_tip"),
    55  		)
    56  	}
    57  	req := request.VulnerabilitiesByCommit(commitID)
    58  	var resp model.CommitResponse
    59  	med := mediator.New(auth)
    60  	err := med.Run(req, &resp)
    61  	if err != nil {
    62  		return nil, errs.Wrap(err, "Failed to run mediator request.")
    63  	}
    64  
    65  	msg := resp.Message
    66  	if msg != nil {
    67  		return nil, locale.NewError("commit_vulnerability_err", "Request to retrieve vulnerability information for commit {{.V0}} failed with error: {{.V1}}", commitID, *msg)
    68  	}
    69  
    70  	return removeModerateSeverity(resp.CommitVulnerabilities), nil
    71  }
    72  
    73  func removeModerateSeverity(cv model.CommitVulnerabilities) *model.CommitVulnerabilities {
    74  	res := cv
    75  	res.VulnerabilityHistogram = funk.Filter(cv.VulnerabilityHistogram, func(sc model.SeverityCount) bool {
    76  		return sc.Severity != "MODERATE"
    77  	}).([]model.SeverityCount)
    78  	res.Sources = funk.Map(cv.Sources, func(sv model.SourceVulnerability) model.SourceVulnerability {
    79  		res := sv
    80  		res.Vulnerabilities = funk.Filter(sv.Vulnerabilities, func(v model.Vulnerability) bool {
    81  			return v.Severity != "MODERATE"
    82  		}).([]model.Vulnerability)
    83  		return res
    84  	}).([]model.SourceVulnerability)
    85  	return &res
    86  }
    87  
    88  func ExtractPackageVulnerabilities(sources []model.SourceVulnerability) []PackageVulnerability {
    89  	var packageVulnerabilities []PackageVulnerability
    90  	visited := make(map[string]struct{})
    91  	for _, v := range sources {
    92  		if len(v.Vulnerabilities) == 0 {
    93  			continue
    94  		}
    95  
    96  		// Remove this block with story https://www.pivotaltracker.com/story/show/176508772
    97  		// filter double entries
    98  		if _, ok := visited[v.Name]; ok {
    99  			continue
   100  		}
   101  		visited[v.Name] = struct{}{}
   102  
   103  		vuls := make([]Vulnerability, 0, len(v.Vulnerabilities))
   104  		for _, ve := range v.Vulnerabilities {
   105  			vuls = append(vuls, Vulnerability(ve))
   106  		}
   107  		packageVulnerabilities = append(packageVulnerabilities, PackageVulnerability{
   108  			v.Name, v.Version, vuls,
   109  		})
   110  	}
   111  
   112  	return packageVulnerabilities
   113  }