diff --git a/detector/detector.go b/detector/detector.go index 7b482d3f..59437f87 100644 --- a/detector/detector.go +++ b/detector/detector.go @@ -291,6 +291,8 @@ func DetectGitHubCves(r *models.ScanResult, githubConfs map[string]config.GitHub if len(githubConfs) == 0 { return nil } + + r.GitHubManifests = models.DependencyGraphManifests{} for ownerRepo, setting := range githubConfs { ss := strings.Split(ownerRepo, "/") if len(ss) != 2 { diff --git a/detector/github.go b/detector/github.go index d6b90528..8267f424 100644 --- a/detector/github.go +++ b/detector/github.go @@ -79,12 +79,8 @@ func DetectGitHubSecurityAlerts(r *models.ScanResult, owner, repo, token string, continue } - repoURLPkgName := fmt.Sprintf("%s %s", - alerts.Data.Repository.URL, v.Node.SecurityVulnerability.Package.Name) - m := models.GitHubSecurityAlert{ - PackageName: repoURLPkgName, - Repository: alerts.Data.Repository.URL, + Repository: alerts.Data.Repository.URL, Package: models.GSAVulnerablePackage{ Name: v.Node.SecurityVulnerability.Package.Name, Ecosystem: v.Node.SecurityVulnerability.Package.Ecosystem, @@ -219,7 +215,6 @@ func DetectGitHubDependencyGraph(r *models.ScanResult, owner, repo, token string ) //TODO Proxy httpClient := oauth2.NewClient(context.Background(), src) - r.GitHubManifests = models.DependencyGraphManifests{} return fetchDependencyGraph(r, httpClient, owner, repo, "", "") } @@ -268,9 +263,10 @@ func fetchDependencyGraph(r *models.ScanResult, httpClient *http.Client, owner, dependenciesAfter = "" for _, m := range graph.Data.Repository.DependencyGraphManifests.Edges { - manifest, ok := r.GitHubManifests[m.Node.Filename] + manifest, ok := r.GitHubManifests[m.Node.BlobPath] if !ok { manifest = models.DependencyGraphManifest{ + BlobPath: m.Node.BlobPath, Filename: m.Node.Filename, Repository: m.Node.Repository.URL, Dependencies: []models.Dependency{}, @@ -284,7 +280,7 @@ func fetchDependencyGraph(r *models.ScanResult, httpClient *http.Client, owner, Requirements: d.Node.Requirements, }) } - r.GitHubManifests[m.Node.Filename] = manifest + r.GitHubManifests[m.Node.BlobPath] = manifest if m.Node.Dependencies.PageInfo.HasNextPage { dependenciesAfter = fmt.Sprintf(`(after: \"%s\")`, m.Node.Dependencies.PageInfo.EndCursor) diff --git a/models/github.go b/models/github.go index d67b5799..a210cd39 100644 --- a/models/github.go +++ b/models/github.go @@ -1,21 +1,28 @@ package models import ( + "fmt" "strings" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" ) // DependencyGraphManifests has a map of DependencyGraphManifest -// key: Filename +// key: BlobPath type DependencyGraphManifests map[string]DependencyGraphManifest type DependencyGraphManifest struct { + BlobPath string `json:"blobPath"` Filename string `json:"filename"` Repository string `json:"repository"` Dependencies []Dependency `json:"dependencies"` } +// RepoURLFilename should be same format with GitHubSecurityAlert.RepoURLManifestPath() +func (m DependencyGraphManifest) RepoURLFilename() string { + return fmt.Sprintf("%s/%s", m.Repository, m.Filename) +} + // Ecosystem returns a name of ecosystem(or package manager) of manifest(lock) file in trivy way // https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-the-dependency-graph#supported-package-ecosystems func (m DependencyGraphManifest) Ecosystem() string { diff --git a/models/vulninfos.go b/models/vulninfos.go index f0b207ad..e7d59d30 100644 --- a/models/vulninfos.go +++ b/models/vulninfos.go @@ -299,10 +299,8 @@ func (g GitHubSecurityAlerts) Names() (names []string) { return names } -// GitHubSecurityAlert has detected CVE-ID, PackageName, Status fetched via GitHub API +// GitHubSecurityAlert has detected CVE-ID, GSAVulnerablePackage, Status fetched via GitHub API type GitHubSecurityAlert struct { - // TODO: PackageName deprecated. it will be removed next time. - PackageName string `json:"packageName"` Repository string `json:"repository"` Package GSAVulnerablePackage `json:"package,omitempty"` FixedIn string `json:"fixedIn"` @@ -316,6 +314,11 @@ func (a GitHubSecurityAlert) RepoURLPackageName() string { return fmt.Sprintf("%s %s", a.Repository, a.Package.Name) } +// RepoURLManifestPath should be same format with DependencyGraphManifest.RepoURLFilename() +func (a GitHubSecurityAlert) RepoURLManifestPath() string { + return fmt.Sprintf("%s/%s", a.Repository, a.Package.ManifestPath) +} + type GSAVulnerablePackage struct { Name string `json:"name"` Ecosystem string `json:"ecosystem"` diff --git a/reporter/sbom/cyclonedx.go b/reporter/sbom/cyclonedx.go index 17945f31..8732238e 100644 --- a/reporter/sbom/cyclonedx.go +++ b/reporter/sbom/cyclonedx.go @@ -86,7 +86,7 @@ func cdxComponents(result models.ScanResult, metaBomRef string) (*[]cdx.Componen ghpkgToPURL := map[string]map[string]string{} for _, ghm := range result.GitHubManifests { - ghpkgToPURL[ghm.Filename] = map[string]string{} + ghpkgToPURL[ghm.RepoURLFilename()] = map[string]string{} ghpkgComps := ghpkgToCdxComponents(ghm, ghpkgToPURL) bomRefs[metaBomRef] = append(bomRefs[metaBomRef], ghpkgComps[0].BOMRef) @@ -275,7 +275,7 @@ func ghpkgToCdxComponents(m models.DependencyGraphManifest, ghpkgToPURL map[stri { BOMRef: uuid.NewString(), Type: cdx.ComponentTypeApplication, - Name: m.Filename, + Name: m.BlobPath, Properties: &[]cdx.Property{ { Name: "future-architect:vuls:Type", @@ -286,7 +286,7 @@ func ghpkgToCdxComponents(m models.DependencyGraphManifest, ghpkgToPURL map[stri } for _, dep := range m.Dependencies { - purl := packageurl.NewPackageURL(m.Ecosystem(), "", dep.PackageName, dep.Version(), packageurl.Qualifiers{{Key: "file_path", Value: m.Filename}}, "").ToString() + purl := packageurl.NewPackageURL(m.Ecosystem(), "", dep.PackageName, dep.Version(), packageurl.Qualifiers{{Key: "repo_url", Value: m.Repository}, {Key: "file_path", Value: m.Filename}}, "").ToString() components = append(components, cdx.Component{ BOMRef: purl, Type: cdx.ComponentTypeLibrary, @@ -295,7 +295,7 @@ func ghpkgToCdxComponents(m models.DependencyGraphManifest, ghpkgToPURL map[stri PackageURL: purl, }) - ghpkgToPURL[m.Filename][dep.PackageName] = purl + ghpkgToPURL[m.RepoURLFilename()][dep.PackageName] = purl } return components @@ -496,7 +496,7 @@ func cdxAffects(cve models.VulnInfo, ospkgToPURL map[string]string, libpkgToPURL } for _, alert := range cve.GitHubSecurityAlerts { // TODO: not in dependency graph - if purl, ok := ghpkgToPURL[alert.Package.ManifestPath][alert.Package.Name]; ok { + if purl, ok := ghpkgToPURL[alert.RepoURLManifestPath()][alert.Package.Name]; ok { affects = append(affects, cdx.Affects{ Ref: purl, })