Skip to content

Commit

Permalink
add vex info to VULN cli (guacsec#1086)
Browse files Browse the repository at this point in the history
Signed-off-by: Brandon Lum <[email protected]>
  • Loading branch information
lumjjb authored Jul 21, 2023
1 parent 7510cab commit 48b2234
Showing 1 changed file with 53 additions and 7 deletions.
60 changes: 53 additions & 7 deletions cmd/guacone/cmd/vulnerability.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,13 +176,14 @@ var queryVulnCmd = &cobra.Command{
var path []string
var tableRows []table.Row
if pkgResponse.Packages[0].Type != guacType {
vulnPath, pkgVulnTableRows, err := queryVulnsViaPackageNeighbors(ctx, gqlclient, pkgResponse.Packages[0].Namespaces[0].Names[0].Versions[0].Id, model.EdgePackageCertifyVuln)
vulnPath, pkgVulnTableRows, err := queryVulnsViaPackageNeighbors(ctx, gqlclient, pkgResponse.Packages[0].Namespaces[0].Names[0].Versions[0].Id, []model.Edge{model.EdgePackageCertifyVuln, model.EdgePackageCertifyVexStatement})
if err != nil {
logger.Fatalf("error querying neighbor: %v", err)
}
path = append(path, vulnPath...)
tableRows = append(tableRows, pkgVulnTableRows...)
}

depVulnPath, depVulnTableRows, err := searchDependencyPackages(ctx, gqlclient, pkgResponse.Packages[0].Namespaces[0].Names[0].Versions[0].Id, opts.depth)
if err != nil {
logger.Fatalf("error searching dependency packages match: %v", err)
Expand All @@ -205,10 +206,10 @@ var queryVulnCmd = &cobra.Command{
},
}

func queryVulnsViaPackageNeighbors(ctx context.Context, gqlclient graphql.Client, pkgVersionID string, edgeType model.Edge) ([]string, []table.Row, error) {
func queryVulnsViaPackageNeighbors(ctx context.Context, gqlclient graphql.Client, pkgVersionID string, edgeTypes []model.Edge) ([]string, []table.Row, error) {
var path []string
var tableRows []table.Row
pkgVersionNeighborResponse, err := model.Neighbors(ctx, gqlclient, pkgVersionID, []model.Edge{edgeType})
pkgVersionNeighborResponse, err := model.Neighbors(ctx, gqlclient, pkgVersionID, edgeTypes)
if err != nil {
return nil, nil, fmt.Errorf("error querying neighbor for vulnerability: %w", err)
}
Expand All @@ -217,32 +218,77 @@ func queryVulnsViaPackageNeighbors(ctx context.Context, gqlclient graphql.Client
if certifyVuln, ok := neighbor.(*model.NeighborsNeighborsCertifyVuln); ok {
certifyVulnFound = true
if vuln, ok := certifyVuln.Vulnerability.(*model.AllCertifyVulnVulnerabilityOSV); ok {
tableRows = append(tableRows, table.Row{certifyVulnStr, vuln.Id, "vulnerability ID: " + vuln.OsvId})
tableRows = append(tableRows, table.Row{certifyVulnStr, certifyVuln.Id, "vulnerability ID: " + vuln.OsvId})
path = append(path, []string{vuln.Id, certifyVuln.Id,
certifyVuln.Package.Namespaces[0].Names[0].Versions[0].Id,
certifyVuln.Package.Namespaces[0].Names[0].Id, certifyVuln.Package.Namespaces[0].Id,
certifyVuln.Package.Id}...)
} else if vuln, ok := certifyVuln.Vulnerability.(*model.AllCertifyVulnVulnerabilityCVE); ok {
tableRows = append(tableRows, table.Row{certifyVulnStr, vuln.Id, "vulnerability ID: " + vuln.CveId})
tableRows = append(tableRows, table.Row{certifyVulnStr, certifyVuln.Id, "vulnerability ID: " + vuln.CveId})
path = append(path, []string{vuln.Id, certifyVuln.Id,
certifyVuln.Package.Namespaces[0].Names[0].Versions[0].Id,
certifyVuln.Package.Namespaces[0].Names[0].Id, certifyVuln.Package.Namespaces[0].Id,
certifyVuln.Package.Id}...)
} else if vuln, ok := certifyVuln.Vulnerability.(*model.AllCertifyVulnVulnerabilityGHSA); ok {
tableRows = append(tableRows, table.Row{certifyVulnStr, vuln.Id, "vulnerability ID: " + vuln.GhsaId})
tableRows = append(tableRows, table.Row{certifyVulnStr, certifyVuln.Id, "vulnerability ID: " + vuln.GhsaId})
path = append(path, []string{vuln.Id, certifyVuln.Id,
certifyVuln.Package.Namespaces[0].Names[0].Versions[0].Id,
certifyVuln.Package.Namespaces[0].Names[0].Id, certifyVuln.Package.Namespaces[0].Id,
certifyVuln.Package.Id}...)
}
}

if certifyVex, ok := neighbor.(*model.NeighborsNeighborsCertifyVEXStatement); ok {
if vuln, ok := certifyVex.Vulnerability.(*model.AllCertifyVEXStatementVulnerabilityOSV); ok {
tableRows = append(tableRows, table.Row{vexLinkStr, certifyVex.Id, "vulnerability ID: " + vuln.OsvId + ", Vex Status: " + string(certifyVex.Status) + ", Subject: " + vexSubjectString(certifyVex.Subject)})
path = append(path, certifyVex.Id, vuln.Id)
} else if vuln, ok := certifyVex.Vulnerability.(*model.AllCertifyVEXStatementVulnerabilityCVE); ok {
tableRows = append(tableRows, table.Row{vexLinkStr, certifyVex.Id, "vulnerability ID: " + vuln.CveId + ", Vex Status: " + string(certifyVex.Status) + ", Subject: " + vexSubjectString(certifyVex.Subject)})
path = append(path, certifyVex.Id, vuln.Id)
} else if vuln, ok := certifyVex.Vulnerability.(*model.AllCertifyVEXStatementVulnerabilityGHSA); ok {
tableRows = append(tableRows, table.Row{vexLinkStr, certifyVex.Id, "vulnerability ID: " + vuln.GhsaId + ", Vex Status: " + string(certifyVex.Status) + ", Subject: " + vexSubjectString(certifyVex.Subject)})
path = append(path, certifyVex.Id, vuln.Id)
}
path = append(path, vexSubjectIds(certifyVex.Subject)...)
}

}
if !certifyVulnFound {
return nil, nil, fmt.Errorf("error certify vulnerability node not found, incomplete data. Please ensure certifier has run")
}
return path, tableRows, nil
}

func vexSubjectString(s model.AllCertifyVEXStatementSubjectPackageOrArtifact) string {
switch v := s.(type) {
case *model.AllCertifyVEXStatementSubjectArtifact:
return fmt.Sprintf("artifact (id:%v) %v:%v", v.Id, v.Algorithm, v.Digest)
case *model.AllCertifyVEXStatementSubjectPackage:
return fmt.Sprintf("package (id:%v) %v:%v/%v@%v",
v.Id,
v.Type,
v.Namespaces[0].Namespace,
v.Namespaces[0].Names[0].Name,
v.Namespaces[0].Names[0].Versions[0].Version)
default:
return "unknown subject"
}
}
func vexSubjectIds(s model.AllCertifyVEXStatementSubjectPackageOrArtifact) []string {
switch v := s.(type) {
case *model.AllCertifyVEXStatementSubjectArtifact:
return []string{v.Id}
case *model.AllCertifyVEXStatementSubjectPackage:
return []string{
v.Id,
v.Namespaces[0].Id,
v.Namespaces[0].Names[0].Id,
v.Namespaces[0].Names[0].Versions[0].Id}
default:
return []string{}
}
}

func searchDependencyPackages(ctx context.Context, gqlclient graphql.Client, topPkgID string, maxLength int) ([]string, []table.Row, error) {
var path []string
var tableRows []table.Row
Expand Down Expand Up @@ -301,7 +347,7 @@ func searchDependencyPackages(ctx context.Context, gqlclient graphql.Client, top

for matchingDepPkgVersion := range matchingDepPkgVersions {
matchingDepPkgVersionID := depPkgVersionsMap[matchingDepPkgVersion]
vulnPath, foundVulnTableRow, err := queryVulnsViaPackageNeighbors(ctx, gqlclient, matchingDepPkgVersionID, model.EdgePackageCertifyVuln)
vulnPath, foundVulnTableRow, err := queryVulnsViaPackageNeighbors(ctx, gqlclient, matchingDepPkgVersionID, []model.Edge{model.EdgePackageCertifyVuln, model.EdgePackageCertifyVexStatement})
if err != nil {
return nil, nil, fmt.Errorf("error querying neighbor: %w", err)
}
Expand Down

0 comments on commit 48b2234

Please sign in to comment.