Skip to content

Commit

Permalink
fix queryVulnsViaVulnNodeNeighbors to check for certifyVex edges (#1540)
Browse files Browse the repository at this point in the history
* fix queryVulnsViaVulnNodeNeighbors to check for certifyVex edges

Signed-off-by: Ridwan Hoq <[email protected]>

* use certify vex edge to query instead

Signed-off-by: Ridwan Hoq <[email protected]>

* make edgeTypes local variables instead of args

Signed-off-by: Ridwan Hoq <[email protected]>

* missed a usage of edgeType

Signed-off-by: Ridwan Hoq <[email protected]>

* replace []table.Row{} with nil in all the returns

Signed-off-by: Ridwan Hoq <[email protected]>

* Refactor vulnerability printing logic

Signed-off-by: Ridwan Hoq <[email protected]>

---------

Signed-off-by: Ridwan Hoq <[email protected]>
  • Loading branch information
ridhoq authored Dec 27, 2023
1 parent c91c538 commit d825ccf
Showing 1 changed file with 88 additions and 60 deletions.
148 changes: 88 additions & 60 deletions cmd/guacone/cmd/vulnerability.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,68 +107,86 @@ var queryVulnCmd = &cobra.Command{
}

if opts.vulnerabilityID != "" {
var tableRows []table.Row
printVulnInfoByVulnId(ctx, gqlclient, pkgResponse, t, opts)
} else {
printVulnInfo(ctx, gqlclient, pkgResponse, t, opts)
}
},
}

vulnResponse, err := model.Vulnerabilities(ctx, gqlclient, model.VulnerabilitySpec{VulnerabilityID: &opts.vulnerabilityID})
if err != nil {
logger.Fatalf("error querying for vulnerabilities: %v", err)
}
var path []string
if len(vulnResponse.Vulnerabilities) > 0 {
func printVulnInfo(ctx context.Context, gqlclient graphql.Client, pkgResponse *model.PackagesResponse, t table.Writer, opts queryOptions) {
logger := logging.FromContext(ctx)
var path []string
var tableRows []table.Row

tableRows = append(tableRows, table.Row{vulnResponse.Vulnerabilities[0].Type, vulnResponse.Vulnerabilities[0].Id, "vulnerability ID: " + vulnResponse.Vulnerabilities[0].VulnerabilityIDs[0].VulnerabilityID})
if pkgResponse.Packages[0].Type != guacType {
vulnPath, pkgVulnTableRows, err := queryVulnsViaPackageNeighbors(ctx, gqlclient, pkgResponse.Packages[0].Namespaces[0].Names[0].Versions[0].Id)
if err != nil {
logger.Fatalf("error querying neighbor: %v", err)
}
path = append(path, vulnPath...)
tableRows = append(tableRows, pkgVulnTableRows...)
}

path, err = queryVulnsViaVulnNodeNeighbors(ctx, gqlclient, pkgResponse, vulnResponse.Vulnerabilities, model.EdgeVulnerabilityCertifyVuln, opts.depth, opts.pathsToReturn)
if err != nil {
logger.Fatalf("error querying neighbor: %v", err)
}
} else {
fmt.Printf("Failed to identify vulnerability \n")
}
if len(path) > 0 {
t.AppendRows(tableRows)
fmt.Println(t.Render())
fmt.Printf("Visualizer url: http://localhost:3000/?path=%v\n", strings.Join(removeDuplicateValuesFromPath(path), `,`))
} else {
fmt.Printf("No path to vulnerability ID found!\n")
}
} else {
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.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)
}
path = append(path, depVulnPath...)
tableRows = append(tableRows, depVulnTableRows...)

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)
}
path = append(path, depVulnPath...)
tableRows = append(tableRows, depVulnTableRows...)
if len(path) > 0 {
path = append([]string{pkgResponse.Packages[0].Namespaces[0].Names[0].Versions[0].Id,
pkgResponse.Packages[0].Namespaces[0].Names[0].Id, pkgResponse.Packages[0].Namespaces[0].Id,
pkgResponse.Packages[0].Id}, path...)
t.AppendRows(tableRows)

if len(path) > 0 {
path = append([]string{pkgResponse.Packages[0].Namespaces[0].Names[0].Versions[0].Id,
pkgResponse.Packages[0].Namespaces[0].Names[0].Id, pkgResponse.Packages[0].Namespaces[0].Id,
pkgResponse.Packages[0].Id}, path...)
t.AppendRows(tableRows)
fmt.Println(t.Render())
fmt.Printf("Visualizer url: http://localhost:3000/?path=%v\n", strings.Join(removeDuplicateValuesFromPath(path), `,`))
} else {
fmt.Printf("No path to vulnerabilities found!\n")
}
}

fmt.Println(t.Render())
fmt.Printf("Visualizer url: http://localhost:3000/?path=%v\n", strings.Join(removeDuplicateValuesFromPath(path), `,`))
} else {
fmt.Printf("No path to vulnerabilities found!\n")
}
}
},
func printVulnInfoByVulnId(ctx context.Context, gqlclient graphql.Client, pkgResponse *model.PackagesResponse, t table.Writer, opts queryOptions) {
logger := logging.FromContext(ctx)
var tableRows []table.Row

vulnResponse, err := model.Vulnerabilities(ctx, gqlclient, model.VulnerabilitySpec{VulnerabilityID: &opts.vulnerabilityID})
if err != nil {
logger.Fatalf("error querying for vulnerabilities: %v", err)
}

if len(vulnResponse.Vulnerabilities) == 0 {
fmt.Printf("Failed to identify vulnerability \n")
return
}
var path []string

tableRows = append(tableRows, table.Row{vulnResponse.Vulnerabilities[0].Type, vulnResponse.Vulnerabilities[0].Id, "vulnerability ID: " + vulnResponse.Vulnerabilities[0].VulnerabilityIDs[0].VulnerabilityID})
var vexTableRows []table.Row
path, vexTableRows, err = queryVulnsViaVulnNodeNeighbors(ctx, gqlclient, pkgResponse, vulnResponse.Vulnerabilities, opts.depth, opts.pathsToReturn)

if err != nil {
logger.Fatalf("error querying neighbor: %v", err)
}
if len(vexTableRows) > 0 {
tableRows = append(tableRows, vexTableRows...)
}
if len(path) > 0 {
t.AppendRows(tableRows)
fmt.Println(t.Render())
fmt.Printf("Visualizer url: http://localhost:3000/?path=%v\n", strings.Join(removeDuplicateValuesFromPath(path), `,`))
} else {
fmt.Printf("No path to vulnerability ID found!\n")
}
}

func queryVulnsViaPackageNeighbors(ctx context.Context, gqlclient graphql.Client, pkgVersionID string, edgeTypes []model.Edge) ([]string, []table.Row, error) {
func queryVulnsViaPackageNeighbors(ctx context.Context, gqlclient graphql.Client, pkgVersionID string) ([]string, []table.Row, error) {
var path []string
var tableRows []table.Row
var edgeTypes = []model.Edge{model.EdgePackageCertifyVuln, model.EdgePackageCertifyVexStatement}

pkgVersionNeighborResponse, err := model.Neighbors(ctx, gqlclient, pkgVersionID, edgeTypes)
if err != nil {
return nil, nil, fmt.Errorf("error querying neighbor for vulnerability: %w", err)
Expand Down Expand Up @@ -316,7 +334,7 @@ func searchDependencyPackages(ctx context.Context, gqlclient graphql.Client, top
if !dfsN.expanded {
queue = append(queue, matchingDepPkgVersionID)
}
vulnPath, foundVulnTableRow, err := queryVulnsViaPackageNeighbors(ctx, gqlclient, matchingDepPkgVersionID, []model.Edge{model.EdgePackageCertifyVuln, model.EdgePackageCertifyVexStatement})
vulnPath, foundVulnTableRow, err := queryVulnsViaPackageNeighbors(ctx, gqlclient, matchingDepPkgVersionID)
if err != nil {
return nil, nil, fmt.Errorf("error querying neighbor: %w", err)
}
Expand All @@ -337,21 +355,23 @@ func searchDependencyPackages(ctx context.Context, gqlclient graphql.Client, top
return path, tableRows, nil
}

func queryVulnsViaVulnNodeNeighbors(ctx context.Context, gqlclient graphql.Client, topPkgResponse *model.PackagesResponse, vulnerabilitiesResponses []model.VulnerabilitiesVulnerabilitiesVulnerability, edgeType model.Edge, depth, pathsToReturn int) ([]string, error) {
func queryVulnsViaVulnNodeNeighbors(ctx context.Context, gqlclient graphql.Client, topPkgResponse *model.PackagesResponse, vulnerabilitiesResponses []model.VulnerabilitiesVulnerabilitiesVulnerability, depth int, pathsToReturn int) ([]string, []table.Row, error) {
type vulnNeighbor struct {
node model.NeighborsNeighborsNode
id string
}

var path []string
var vulnNodeNeighborResponses []vulnNeighbor
var tableRows []table.Row

edgeTypes := []model.Edge{model.EdgeVulnerabilityCertifyVuln, model.EdgeVulnerabilityCertifyVexStatement}
for _, vulnerabilitiesResponse := range vulnerabilitiesResponses {
for _, vulnerabilityNodeID := range vulnerabilitiesResponse.VulnerabilityIDs {
vulnNodeNeighborResponse, err := model.Neighbors(ctx, gqlclient, vulnerabilityNodeID.Id, []model.Edge{edgeType})
vulnNodeNeighborResponse, err := model.Neighbors(ctx, gqlclient, vulnerabilityNodeID.Id, edgeTypes)

if err != nil {
return nil, fmt.Errorf("error querying neighbor for vulnerability: %w", err)
return nil, nil, fmt.Errorf("error querying neighbor for vulnerability: %w", err)
}

for _, neighbor := range vulnNodeNeighborResponse.Neighbors {
Expand All @@ -367,7 +387,7 @@ func queryVulnsViaVulnNodeNeighbors(ctx context.Context, gqlclient graphql.Clien
certifyVulnFound = true
pkgPath, err := searchDependencyPackagesReverse(ctx, gqlclient, topPkgResponse.Packages[0].Namespaces[0].Names[0].Versions[0].Id, certifyVuln.Package.Namespaces[0].Names[0].Versions[0].Id, depth)
if err != nil {
return nil, fmt.Errorf("error searching dependency packages match: %w", err)
return nil, nil, fmt.Errorf("error searching dependency packages match: %w", err)
}
if len(pkgPath) > 0 {
fullVulnPath := append([]string{neighbor.id, certifyVuln.Id,
Expand All @@ -378,14 +398,22 @@ func queryVulnsViaVulnNodeNeighbors(ctx context.Context, gqlclient graphql.Clien
numberOfPaths += 1
}
if pathsToReturn != 0 && numberOfPaths == pathsToReturn {
return path, nil
return path, nil, nil
}
}
if certifyVex, ok := neighbor.node.(*model.NeighborsNeighborsCertifyVEXStatement); ok {
certifyVulnFound = true
for _, vuln := range certifyVex.Vulnerability.VulnerabilityIDs {
tableRows = append(tableRows, table.Row{vexLinkStr, certifyVex.Id, "vulnerability ID: " + vuln.VulnerabilityID + ", 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, fmt.Errorf("error certify vulnerability node not found, incomplete data. Please ensure certifier has run")
return nil, nil, fmt.Errorf("error certify vulnerability node not found, incomplete data. Please ensure certifier has run")
}
return path, nil
return path, tableRows, nil
}

func searchDependencyPackagesReverse(ctx context.Context, gqlclient graphql.Client, topPkgID string, searchPkgID string, maxLength int) ([]string, error) {
Expand Down

0 comments on commit d825ccf

Please sign in to comment.