Skip to content

Commit

Permalink
Docker scan JAS support, dumb copy with broken imports jfrog#4
Browse files Browse the repository at this point in the history
  • Loading branch information
guyshe-jfrog committed Jan 18, 2024
1 parent d44be67 commit 9b27a9f
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 50 deletions.
25 changes: 6 additions & 19 deletions commands/audit/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ import (
"os"

"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/jfrog/jfrog-cli-security/scangraph"
"github.com/jfrog/jfrog-cli-security/utils"
"github.com/jfrog/jfrog-cli-core/v2/utils/dependencies"
"github.com/jfrog/jfrog-cli-core/v2/xray/scangraph"

Check failure on line 9 in commands/audit/audit.go

View workflow job for this annotation

GitHub Actions / test (ubuntu)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/scangraph; to add it:

Check failure on line 9 in commands/audit/audit.go

View workflow job for this annotation

GitHub Actions / test (windows)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/scangraph; to add it:

Check failure on line 9 in commands/audit/audit.go

View workflow job for this annotation

GitHub Actions / test (macos)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/scangraph; to add it:
clientutils "github.com/jfrog/jfrog-client-go/utils"
"github.com/jfrog/jfrog-client-go/utils/log"
"github.com/jfrog/jfrog-client-go/xray"
"github.com/jfrog/jfrog-client-go/xray/services"
"golang.org/x/sync/errgroup"

xrayutils "github.com/jfrog/jfrog-cli-security/utils"
xrayutils "github.com/jfrog/jfrog-cli-core/v2/xray/utils"

Check failure on line 15 in commands/audit/audit.go

View workflow job for this annotation

GitHub Actions / test (ubuntu)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/utils; to add it:

Check failure on line 15 in commands/audit/audit.go

View workflow job for this annotation

GitHub Actions / test (windows)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/utils; to add it:

Check failure on line 15 in commands/audit/audit.go

View workflow job for this annotation

GitHub Actions / test (macos)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/utils; to add it:
)

type AuditCommand struct {
Expand Down Expand Up @@ -83,8 +82,6 @@ func (auditCmd *AuditCommand) CreateXrayGraphScanParams() *services.XrayGraphSca
}

func (auditCmd *AuditCommand) Run() (err error) {
// If no workingDirs were provided by the user, we apply a recursive scan on the root repository
isRecursiveScan := len(auditCmd.workingDirs) == 0
workingDirs, err := coreutils.GetFullPathsWorkingDirs(auditCmd.workingDirs)
if err != nil {
return
Expand All @@ -96,8 +93,7 @@ func (auditCmd *AuditCommand) Run() (err error) {
SetFixableOnly(auditCmd.fixableOnly).
SetGraphBasicParams(auditCmd.AuditBasicParams).
SetThirdPartyApplicabilityScan(auditCmd.thirdPartyApplicabilityScan).
SetExclusions(auditCmd.exclusions).
SetIsRecursiveScan(isRecursiveScan)
SetExclusions(auditCmd.exclusions)
auditResults, err := RunAudit(auditParams)
if err != nil {
return
Expand Down Expand Up @@ -160,15 +156,15 @@ func RunAudit(auditParams *AuditParams) (results *xrayutils.Results, err error)
return
}
results.XrayVersion = auditParams.xrayVersion
results.ExtendedScanResults.EntitledForJas, err = isEntitledForJas(xrayManager, auditParams.xrayVersion)
results.ExtendedScanResults.EntitledForJas, err = xrayutils.IsEntitledForJas(xrayManager, auditParams.xrayVersion)
if err != nil {
return
}

errGroup := new(errgroup.Group)
if results.ExtendedScanResults.EntitledForJas {
// Download (if needed) the analyzer manager in a background routine.
errGroup.Go(utils.DownloadAnalyzerManagerIfNeeded)
errGroup.Go(dependencies.DownloadAnalyzerManagerIfNeeded)

Check failure on line 167 in commands/audit/audit.go

View workflow job for this annotation

GitHub Actions / Static-Check

undefined: dependencies.DownloadAnalyzerManagerIfNeeded (typecheck)
}

// The sca scan doesn't require the analyzer manager, so it can run separately from the analyzer manager download routine.
Expand All @@ -185,12 +181,3 @@ func RunAudit(auditParams *AuditParams) (results *xrayutils.Results, err error)
}
return
}

func isEntitledForJas(xrayManager *xray.XrayServicesManager, xrayVersion string) (entitled bool, err error) {
if e := clientutils.ValidateMinimumVersion(clientutils.Xray, xrayVersion, xrayutils.EntitlementsMinVersion); e != nil {
log.Debug(e)
return
}
entitled, err = xrayManager.IsEntitled(xrayutils.ApplicabilityFeatureId)
return
}
47 changes: 41 additions & 6 deletions commands/audit/jas/applicability/applicabilitymanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import (
"path/filepath"

jfrogappsconfig "github.com/jfrog/jfrog-apps-config/go"
"github.com/jfrog/jfrog-cli-security/commands/audit/jas"
"github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas"

"github.com/jfrog/gofrog/datastructures"
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/jfrog/jfrog-cli-security/utils"
"github.com/jfrog/jfrog-cli-core/v2/xray/utils"
"github.com/jfrog/jfrog-client-go/utils/log"
"github.com/jfrog/jfrog-client-go/xray/services"
"github.com/owenrumney/go-sarif/v2/sarif"
Expand All @@ -17,9 +17,10 @@ import (
)

const (
applicabilityScanType = "analyze-applicability"
applicabilityScanCommand = "ca"
applicabilityDocsUrlSuffix = "contextual-analysis"
applicabilityScanType = "analyze-applicability"
applicabilityScanCommand = "ca"
applicabilityDocsUrlSuffix = "contextual-analysis"
applicabilityDockerScanScanType = "analyze-applicability-docker-scan"
)

type ApplicabilityScanManager struct {
Expand All @@ -29,6 +30,7 @@ type ApplicabilityScanManager struct {
xrayResults []services.ScanResponse
scanner *jas.JasScanner
thirdPartyScan bool
commandType string
}

// The getApplicabilityScanResults function runs the applicability scan flow, which includes the following steps:
Expand All @@ -55,6 +57,37 @@ func RunApplicabilityScan(xrayResults []services.ScanResponse, directDependencie
return
}

// The getApplicabilityScanResults function runs the applicability scan flow, which includes the following steps:
// Creating an ApplicabilityScanManager object.
// Checking if the scanned project is eligible for applicability scan.
// Running the analyzer manager executable.
// Parsing the analyzer manager results.
// Return values:
// map[string]string: A map containing the applicability result of each XRAY CVE.
// bool: true if the user is entitled to the applicability scan, false otherwise.
// error: An error object (if any).
func RunApplicabilityWithScanCves(xrayResults []services.ScanResponse, cveList []string,
scannedTechnologies []coreutils.Technology, scanner *jas.JasScanner) (results []*sarif.Run, err error) {
applicabilityScanManager := newApplicabilityScanManagerCves(xrayResults, cveList, scanner)
if err = applicabilityScanManager.scanner.Run(applicabilityScanManager); err != nil {
err = utils.ParseAnalyzerManagerError(utils.Applicability, err)
return
}
results = applicabilityScanManager.applicabilityScanResults
return
}

func newApplicabilityScanManagerCves(xrayScanResults []services.ScanResponse, cveList []string, scanner *jas.JasScanner) (manager *ApplicabilityScanManager) {
return &ApplicabilityScanManager{
applicabilityScanResults: []*sarif.Run{},
directDependenciesCves: cveList,
xrayResults: xrayScanResults,
scanner: scanner,
thirdPartyScan: false,
commandType: applicabilityDockerScanScanType,
}
}

func newApplicabilityScanManager(xrayScanResults []services.ScanResponse, directDependencies []string, scanner *jas.JasScanner, thirdPartyScan bool) (manager *ApplicabilityScanManager) {
directDependenciesCves, indirectDependenciesCves := extractDependenciesCvesFromScan(xrayScanResults, directDependencies)
return &ApplicabilityScanManager{
Expand All @@ -64,6 +97,7 @@ func newApplicabilityScanManager(xrayScanResults []services.ScanResponse, direct
xrayResults: xrayScanResults,
scanner: scanner,
thirdPartyScan: thirdPartyScan,
commandType: applicabilityScanType,
}
}

Expand Down Expand Up @@ -152,6 +186,7 @@ type scanConfiguration struct {
CveWhitelist []string `yaml:"cve-whitelist"`
IndirectCveWhitelist []string `yaml:"indirect-cve-whitelist"`
SkippedDirs []string `yaml:"skipped-folders"`
ScanType string `yaml:"scantype"`
}

func (asm *ApplicabilityScanManager) createConfigFile(module jfrogappsconfig.Module) error {
Expand All @@ -169,7 +204,7 @@ func (asm *ApplicabilityScanManager) createConfigFile(module jfrogappsconfig.Mod
{
Roots: roots,
Output: asm.scanner.ResultsFileName,
Type: applicabilityScanType,
Type: asm.commandType,
GrepDisable: false,
CveWhitelist: asm.directDependenciesCves,
IndirectCveWhitelist: asm.indirectDependenciesCves,
Expand Down
21 changes: 12 additions & 9 deletions commands/audit/jas/secrets/secretsscanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,23 @@ import (
"strings"

jfrogappsconfig "github.com/jfrog/jfrog-apps-config/go"
"github.com/jfrog/jfrog-cli-security/commands/audit/jas"
"github.com/jfrog/jfrog-cli-security/utils"
"github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas"
"github.com/jfrog/jfrog-cli-core/v2/xray/utils"
"github.com/jfrog/jfrog-client-go/utils/log"
"github.com/owenrumney/go-sarif/v2/sarif"
)

const (
secretsScanCommand = "sec"
secretsScannerType = "secrets-scan"
secretsDocsUrlSuffix = "secrets"
secretsScanCommand = "sec"
SecretsScannerType = "secrets-scan" // #nosec
SecretsScannerDockerScanType = "secrets-docker-scan" // #nosec
secretsDocsUrlSuffix = "secrets"
)

type SecretScanManager struct {
secretsScannerResults []*sarif.Run
scanner *jas.JasScanner
scanType string
}

// The getSecretsScanResults function runs the secrets scan flow, which includes the following steps:
Expand All @@ -29,8 +31,8 @@ type SecretScanManager struct {
// Return values:
// []utils.IacOrSecretResult: a list of the secrets that were found.
// error: An error object (if any).
func RunSecretsScan(scanner *jas.JasScanner) (results []*sarif.Run, err error) {
secretScanManager := newSecretsScanManager(scanner)
func RunSecretsScan(scanner *jas.JasScanner, scanType string) (results []*sarif.Run, err error) {
secretScanManager := newSecretsScanManager(scanner, scanType)
log.Info("Running secrets scanning...")
if err = secretScanManager.scanner.Run(secretScanManager); err != nil {
err = utils.ParseAnalyzerManagerError(utils.Secrets, err)
Expand All @@ -43,10 +45,11 @@ func RunSecretsScan(scanner *jas.JasScanner) (results []*sarif.Run, err error) {
return
}

func newSecretsScanManager(scanner *jas.JasScanner) (manager *SecretScanManager) {
func newSecretsScanManager(scanner *jas.JasScanner, scanType string) (manager *SecretScanManager) {
return &SecretScanManager{
secretsScannerResults: []*sarif.Run{},
scanner: scanner,
scanType: scanType,
}
}

Expand Down Expand Up @@ -89,7 +92,7 @@ func (s *SecretScanManager) createConfigFile(module jfrogappsconfig.Module) erro
{
Roots: roots,
Output: s.scanner.ResultsFileName,
Type: secretsScannerType,
Type: s.scanType,
SkippedDirs: jas.GetExcludePatterns(module, module.Scanners.Secrets),
},
},
Expand Down
15 changes: 8 additions & 7 deletions commands/audit/jasrunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ package audit

import (
"errors"

"github.com/jfrog/jfrog-cli-core/v2/utils/config"
"github.com/jfrog/jfrog-cli-security/commands/audit/jas"
"github.com/jfrog/jfrog-cli-security/commands/audit/jas/applicability"
"github.com/jfrog/jfrog-cli-security/commands/audit/jas/iac"
"github.com/jfrog/jfrog-cli-security/commands/audit/jas/sast"
"github.com/jfrog/jfrog-cli-security/commands/audit/jas/secrets"
"github.com/jfrog/jfrog-cli-security/utils"
"github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas"

Check failure on line 7 in commands/audit/jasrunner.go

View workflow job for this annotation

GitHub Actions / test (ubuntu)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas; to add it:

Check failure on line 7 in commands/audit/jasrunner.go

View workflow job for this annotation

GitHub Actions / test (windows)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas; to add it:

Check failure on line 7 in commands/audit/jasrunner.go

View workflow job for this annotation

GitHub Actions / test (macos)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas; to add it:
"github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas/applicability"

Check failure on line 8 in commands/audit/jasrunner.go

View workflow job for this annotation

GitHub Actions / test (ubuntu)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas/applicability; to add it:

Check failure on line 8 in commands/audit/jasrunner.go

View workflow job for this annotation

GitHub Actions / test (windows)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas/applicability; to add it:

Check failure on line 8 in commands/audit/jasrunner.go

View workflow job for this annotation

GitHub Actions / test (macos)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas/applicability; to add it:
"github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas/iac"

Check failure on line 9 in commands/audit/jasrunner.go

View workflow job for this annotation

GitHub Actions / test (ubuntu)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas/iac; to add it:

Check failure on line 9 in commands/audit/jasrunner.go

View workflow job for this annotation

GitHub Actions / test (windows)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas/iac; to add it:

Check failure on line 9 in commands/audit/jasrunner.go

View workflow job for this annotation

GitHub Actions / test (macos)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas/iac; to add it:
"github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas/sast"

Check failure on line 10 in commands/audit/jasrunner.go

View workflow job for this annotation

GitHub Actions / test (ubuntu)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas/sast; to add it:

Check failure on line 10 in commands/audit/jasrunner.go

View workflow job for this annotation

GitHub Actions / test (windows)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas/sast; to add it:

Check failure on line 10 in commands/audit/jasrunner.go

View workflow job for this annotation

GitHub Actions / test (macos)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas/sast; to add it:
"github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas/secrets"

Check failure on line 11 in commands/audit/jasrunner.go

View workflow job for this annotation

GitHub Actions / test (ubuntu)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas/secrets; to add it:

Check failure on line 11 in commands/audit/jasrunner.go

View workflow job for this annotation

GitHub Actions / test (windows)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas/secrets; to add it:

Check failure on line 11 in commands/audit/jasrunner.go

View workflow job for this annotation

GitHub Actions / test (macos)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas/secrets; to add it:
"github.com/jfrog/jfrog-cli-core/v2/xray/utils"
"github.com/jfrog/jfrog-client-go/utils/io"
"github.com/jfrog/jfrog-client-go/utils/log"
)
Expand Down Expand Up @@ -41,7 +42,7 @@ func runJasScannersAndSetResults(scanResults *utils.Results, directDependencies
if progress != nil {
progress.SetHeadlineMsg("Running secrets scanning")
}
scanResults.ExtendedScanResults.SecretsScanResults, err = secrets.RunSecretsScan(scanner)
scanResults.ExtendedScanResults.SecretsScanResults, err = secrets.RunSecretsScan(scanner, secrets.SecretsScannerType)
if err != nil {
return
}
Expand Down
50 changes: 42 additions & 8 deletions commands/scan/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,20 @@ import (
"regexp"
"strings"

"github.com/jfrog/jfrog-cli-security/scangraph"
"golang.org/x/exp/slices"

rtutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils"
"github.com/jfrog/jfrog-cli-core/v2/xray/scangraph"
xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils"
"golang.org/x/sync/errgroup"

"github.com/jfrog/gofrog/parallel"
"github.com/jfrog/jfrog-cli-core/v2/common/format"
outputFormat "github.com/jfrog/jfrog-cli-core/v2/common/format"
"github.com/jfrog/jfrog-cli-core/v2/common/spec"
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/jfrog/jfrog-cli-security/formats"
xrutils "github.com/jfrog/jfrog-cli-security/utils"
"github.com/jfrog/jfrog-cli-core/v2/xray/formats"

Check failure on line 25 in commands/scan/scan.go

View workflow job for this annotation

GitHub Actions / test (ubuntu)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/formats; to add it:

Check failure on line 25 in commands/scan/scan.go

View workflow job for this annotation

GitHub Actions / test (windows)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/formats; to add it:

Check failure on line 25 in commands/scan/scan.go

View workflow job for this annotation

GitHub Actions / test (macos)

no required module provides package github.com/jfrog/jfrog-cli-core/v2/xray/formats; to add it:
xrutils "github.com/jfrog/jfrog-cli-core/v2/xray/utils"
"github.com/jfrog/jfrog-client-go/artifactory/services/fspatterns"
clientutils "github.com/jfrog/jfrog-client-go/utils"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
Expand All @@ -46,7 +49,7 @@ type ScanCommand struct {
// The location of the downloaded Xray indexer binary on the local file system.
indexerPath string
indexerTempDir string
outputFormat outputFormat.OutputFormat
outputFormat format.OutputFormat
projectKey string
minSeverityFilter string
watches []string
Expand Down Expand Up @@ -78,7 +81,7 @@ func (scanCmd *ScanCommand) SetThreads(threads int) *ScanCommand {
return scanCmd
}

func (scanCmd *ScanCommand) SetOutputFormat(format outputFormat.OutputFormat) *ScanCommand {
func (scanCmd *ScanCommand) SetOutputFormat(format format.OutputFormat) *ScanCommand {
scanCmd.outputFormat = format
return scanCmd
}
Expand Down Expand Up @@ -249,6 +252,23 @@ func (scanCmd *ScanCommand) Run() (err error) {
scanResults.XrayVersion = xrayVersion
scanResults.ScaResults = []xrutils.ScaScanResult{{XrayResults: flatResults}}

scanResults.ExtendedScanResults.EntitledForJas, err = xrutils.IsEntitledForJas(xrayManager, xrayVersion)
errGroup := new(errgroup.Group)
if scanResults.ExtendedScanResults.EntitledForJas {
// Download (if needed) the analyzer manager in a background routine.
errGroup.Go(rtutils.DownloadAnalyzerManagerIfNeeded)

Check failure on line 259 in commands/scan/scan.go

View workflow job for this annotation

GitHub Actions / Static-Check

undefined: rtutils.DownloadAnalyzerManagerIfNeeded (typecheck)
}
// Wait for the Download of the AnalyzerManager to complete.
if err = errGroup.Wait(); err != nil {
err = errors.New("failed while trying to get Analyzer Manager: " + err.Error())
}

if scanResults.ExtendedScanResults.EntitledForJas {
cveList := cveListFromVulnerabilities(flatResults)
workingDirs := []string{scanCmd.spec.Files[0].Pattern}
scanResults.JasError = runJasScannersAndSetResults(scanResults, cveList, scanCmd.serverDetails, workingDirs)

Check failure on line 269 in commands/scan/scan.go

View workflow job for this annotation

GitHub Actions / Static-Check

undefined: runJasScannersAndSetResults (typecheck)
}

if err = xrutils.NewResultsWriter(scanResults).
SetOutputFormat(scanCmd.outputFormat).
SetIncludeVulnerabilities(scanCmd.includeVulnerabilities).
Expand Down Expand Up @@ -454,6 +474,20 @@ func appendErrorSlice(scanErrors []formats.SimpleJsonError, errorsToAdd [][]form
return scanErrors
}

func ConditionalUploadDefaultScanFunc(serverDetails *config.ServerDetails, fileSpec *spec.SpecFiles, threads int, scanOutputFormat format.OutputFormat) error {
return NewScanCommand().SetServerDetails(serverDetails).SetSpec(fileSpec).SetThreads(threads).SetOutputFormat(scanOutputFormat).SetFail(true).SetPrintExtendedTable(false).Run()
func cveListFromVulnerabilities(flatResults []services.ScanResponse) []string {
var cveList []string
var technologiesList []string
for _, result := range flatResults {
for _, vulnerability := range result.Vulnerabilities {
for _, cve := range vulnerability.Cves {
if !slices.Contains(cveList, cve.Id) && (cve.Id != "") {
cveList = append(cveList, cve.Id)
}
}
if !slices.Contains(technologiesList, vulnerability.Technology) && (vulnerability.Technology != "") {
technologiesList = append(technologiesList, vulnerability.Technology)
}
}
}
return cveList
}
1 change: 1 addition & 0 deletions formats/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func ConvertToVulnerabilityScanTableRow(rows []VulnerabilityOrViolationRow) (tab
tableRows = append(tableRows, vulnerabilityScanTableRow{
severity: rows[i].Severity,
severityNumValue: rows[i].SeverityNumValue,
applicable: rows[i].Applicable,
impactedPackageName: rows[i].ImpactedDependencyName,
impactedPackageVersion: rows[i].ImpactedDependencyVersion,
ImpactedPackageType: rows[i].ImpactedDependencyType,
Expand Down
3 changes: 2 additions & 1 deletion formats/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ type vulnerabilityTableRow struct {
}

type vulnerabilityScanTableRow struct {
severity string `col-name:"Severity"`
severity string `col-name:"Severity"`
applicable string `col-name:"Contextual\nAnalysis" omitempty:"true"`
// For sorting
severityNumValue int
directPackages []directPackagesTableRow `embed-table:"true"`
Expand Down

0 comments on commit 9b27a9f

Please sign in to comment.