Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 35 additions & 32 deletions cli/docs/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package docs

import (
"fmt"
"github.com/jfrog/jfrog-cli-security/commands/git"
"strings"

"github.com/jfrog/jfrog-cli-security/commands/git"

"github.com/jfrog/jfrog-cli-core/v2/common/cliutils"
pluginsCommon "github.com/jfrog/jfrog-cli-core/v2/plugins/common"
"github.com/jfrog/jfrog-cli-core/v2/plugins/components"
Expand Down Expand Up @@ -88,25 +89,26 @@ const (
Periodic = "periodic"

// Unique scan and audit flags
scanPrefix = "scan-"
scanRecursive = scanPrefix + Recursive
scanRegexp = scanPrefix + RegexpFlag
scanAnt = scanPrefix + AntFlag
OutputFormat = "format"
BypassArchiveLimits = "bypass-archive-limits"
Watches = "watches"
RepoPath = "repo-path"
Licenses = "licenses"
Fail = "fail"
ExtendedTable = "extended-table"
MinSeverity = "min-severity"
FixableOnly = "fixable-only"
Rescan = "rescan"
Vuln = "vuln"
buildPrefix = "build-"
BuildVuln = buildPrefix + Vuln
ScanVuln = scanPrefix + Vuln
SecretValidation = "validate-secrets"
scanPrefix = "scan-"
scanRecursive = scanPrefix + Recursive
scanRegexp = scanPrefix + RegexpFlag
scanAnt = scanPrefix + AntFlag
OutputFormat = "format"
BypassArchiveLimits = "bypass-archive-limits"
Watches = "watches"
RepoPath = "repo-path"
Licenses = "licenses"
Fail = "fail"
ExtendedTable = "extended-table"
MinSeverity = "min-severity"
FixableOnly = "fixable-only"
SkipNotApplicableCves = "skip-not-applicable-cves"
Rescan = "rescan"
Vuln = "vuln"
buildPrefix = "build-"
BuildVuln = buildPrefix + Vuln
ScanVuln = scanPrefix + Vuln
SecretValidation = "validate-secrets"

// Unique audit flags
auditPrefix = "audit-"
Expand Down Expand Up @@ -150,13 +152,13 @@ var commandFlags = map[string][]string{
url, user, password, accessToken, ServerId, Project, BuildVuln, OutputFormat, Fail, ExtendedTable, Rescan,
},
DockerScan: {
ServerId, Project, Watches, RepoPath, Licenses, OutputFormat, Fail, ExtendedTable, BypassArchiveLimits, MinSeverity, FixableOnly, ScanVuln, SecretValidation,
ServerId, Project, Watches, RepoPath, Licenses, OutputFormat, Fail, ExtendedTable, BypassArchiveLimits, MinSeverity, FixableOnly, ScanVuln, SecretValidation, SkipNotApplicableCves,
},
Audit: {
url, user, password, accessToken, ServerId, InsecureTls, Project, Watches, RepoPath, Licenses, OutputFormat, ExcludeTestDeps,
useWrapperAudit, DepType, RequirementsFile, Fail, ExtendedTable, WorkingDirs, ExclusionsAudit, Mvn, Gradle, Npm,
Pnpm, Yarn, Go, Nuget, Pip, Pipenv, Poetry, MinSeverity, FixableOnly, ThirdPartyContextualAnalysis, Threads,
Sca, Iac, Sast, Secrets, WithoutCA, ScanVuln, SecretValidation, OutputDir, SkipAutoInstall, AllowPartialResults,
Sca, Iac, Sast, Secrets, WithoutCA, ScanVuln, SecretValidation, OutputDir, SkipAutoInstall, AllowPartialResults, SkipNotApplicableCves,
},
CurationAudit: {
CurationOutput, WorkingDirs, Threads, RequirementsFile,
Expand Down Expand Up @@ -216,16 +218,17 @@ var flagsMap = map[string]components.Flag{
"Defines the output format of the command. Acceptable values are: table, json, simple-json and sarif. Note: the json format doesn't include information about scans that are included as part of the Advanced Security package.",
components.WithStrDefaultValue("table"),
),
Fail: components.NewBoolFlag(Fail, fmt.Sprintf("When using one of the flags --%s, --%s or --%s and a 'Fail build' rule is matched, the command will return exit code 3. Set to false if you'd like to see violations with exit code 0.", Watches, Project, RepoPath), components.WithBoolDefaultValue(true)),
ExtendedTable: components.NewBoolFlag(ExtendedTable, "Set to true if you'd like the table to include extended fields such as 'CVSS' & 'Xray Issue Id'. Ignored if provided 'format' is not 'table'."),
BypassArchiveLimits: components.NewBoolFlag(BypassArchiveLimits, "Set to true to bypass the indexer-app archive limits."),
MinSeverity: components.NewStringFlag(MinSeverity, "Set the minimum severity of issues to display. The following values are accepted: Low, Medium, High or Critical."),
FixableOnly: components.NewBoolFlag(FixableOnly, "Set to true if you wish to display issues that have a fixed version only."),
Rescan: components.NewBoolFlag(Rescan, "Set to true when scanning an already successfully scanned build, for example after adding an ignore rule."),
BuildVuln: components.NewBoolFlag(Vuln, "Set to true if you'd like to receive an additional view of all vulnerabilities, regardless of the policy configured in Xray. Ignored if provided 'format' is 'sarif'."),
ScanVuln: components.NewBoolFlag(Vuln, "Set to true if you'd like to receive an additional view of all vulnerabilities, regardless of the policy configured in Xray."),
InsecureTls: components.NewBoolFlag(InsecureTls, "Set to true to skip TLS certificates verification."),
ExcludeTestDeps: components.NewBoolFlag(ExcludeTestDeps, "[Gradle] Set to true if you'd like to exclude Gradle test dependencies from Xray scanning."),
Fail: components.NewBoolFlag(Fail, fmt.Sprintf("When using one of the flags --%s, --%s or --%s and a 'Fail build' rule is matched, the command will return exit code 3. Set to false if you'd like to see violations with exit code 0.", Watches, Project, RepoPath), components.WithBoolDefaultValue(true)),
ExtendedTable: components.NewBoolFlag(ExtendedTable, "Set to true if you'd like the table to include extended fields such as 'CVSS' & 'Xray Issue Id'. Ignored if provided 'format' is not 'table'."),
BypassArchiveLimits: components.NewBoolFlag(BypassArchiveLimits, "Set to true to bypass the indexer-app archive limits."),
MinSeverity: components.NewStringFlag(MinSeverity, "Set the minimum severity of issues to display. The following values are accepted: Low, Medium, High or Critical."),
FixableOnly: components.NewBoolFlag(FixableOnly, "Set to true if you wish to display issues that have a fixed version only."),
SkipNotApplicableCves: components.NewBoolFlag(SkipNotApplicableCves, "Set to true if you wish to not display issues with Not Applicable CVEs"),
Rescan: components.NewBoolFlag(Rescan, "Set to true when scanning an already successfully scanned build, for example after adding an ignore rule."),
BuildVuln: components.NewBoolFlag(Vuln, "Set to true if you'd like to receive an additional view of all vulnerabilities, regardless of the policy configured in Xray. Ignored if provided 'format' is 'sarif'."),
ScanVuln: components.NewBoolFlag(Vuln, "Set to true if you'd like to receive an additional view of all vulnerabilities, regardless of the policy configured in Xray."),
InsecureTls: components.NewBoolFlag(InsecureTls, "Set to true to skip TLS certificates verification."),
ExcludeTestDeps: components.NewBoolFlag(ExcludeTestDeps, "[Gradle] Set to true if you'd like to exclude Gradle test dependencies from Xray scanning."),
useWrapperAudit: components.NewBoolFlag(
UseWrapper,
"Set to false if you wish to not use the gradle or maven wrapper.",
Expand Down
8 changes: 6 additions & 2 deletions cli/scancommands.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package cli
import (
"errors"
"fmt"
"os"
"strings"

buildInfoUtils "github.com/jfrog/build-info-go/utils"
"github.com/jfrog/gofrog/datastructures"
"github.com/jfrog/jfrog-cli-core/v2/common/cliutils"
Expand All @@ -22,8 +25,6 @@ import (
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
"github.com/jfrog/jfrog-client-go/utils/log"
"github.com/urfave/cli"
"os"
"strings"

flags "github.com/jfrog/jfrog-cli-security/cli/docs"
auditSpecificDocs "github.com/jfrog/jfrog-cli-security/cli/docs/auditspecific"
Expand Down Expand Up @@ -250,6 +251,7 @@ func ScanCmd(c *components.Context) error {
SetPrintExtendedTable(c.GetBoolFlagValue(flags.ExtendedTable)).
SetBypassArchiveLimits(c.GetBoolFlagValue(flags.BypassArchiveLimits)).
SetFixableOnly(c.GetBoolFlagValue(flags.FixableOnly)).
SetSkipNotApplicableCves(c.GetBoolFlagValue(flags.SkipNotApplicableCves)).
SetMinSeverityFilter(minSeverity)
if c.IsFlagSet(flags.Watches) {
scanCmd.SetWatches(splitByCommaAndTrim(c.GetStringFlagValue(flags.Watches)))
Expand Down Expand Up @@ -478,6 +480,7 @@ func CreateAuditCmd(c *components.Context) (string, string, *coreConfig.ServerDe
SetPrintExtendedTable(c.GetBoolFlagValue(flags.ExtendedTable)).
SetMinSeverityFilter(minSeverity).
SetFixableOnly(c.GetBoolFlagValue(flags.FixableOnly)).
SetSkipNotApplicableCves(c.GetBoolFlagValue(flags.SkipNotApplicableCves)).
SetThirdPartyApplicabilityScan(c.GetBoolFlagValue(flags.ThirdPartyContextualAnalysis)).
SetScansResultsOutputDir(scansOutputDir).
SetSkipAutoInstall(c.GetBoolFlagValue(flags.SkipAutoInstall)).
Expand Down Expand Up @@ -739,6 +742,7 @@ func DockerScan(c *components.Context, image string) error {
SetPrintExtendedTable(c.GetBoolFlagValue(flags.ExtendedTable)).
SetBypassArchiveLimits(c.GetBoolFlagValue(flags.BypassArchiveLimits)).
SetFixableOnly(c.GetBoolFlagValue(flags.FixableOnly)).
SetSkipNotApplicableCves(c.GetBoolFlagValue(flags.SkipNotApplicableCves)).
SetMinSeverityFilter(minSeverity).
SetThreads(threads).
SetSecretValidation(c.GetBoolFlagValue(flags.SecretValidation))
Expand Down
6 changes: 6 additions & 0 deletions commands/audit/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ func (auditCmd *AuditCommand) Run() (err error) {
SetWorkingDirs(workingDirs).
SetMinSeverityFilter(auditCmd.minSeverityFilter).
SetFixableOnly(auditCmd.fixableOnly).
SetSkipNotApplicableCves(auditCmd.skipNotApplicableCves).
SetGraphBasicParams(auditCmd.AuditBasicParams).
SetCommonGraphScanParams(auditCmd.CreateCommonGraphScanParams()).
SetThirdPartyApplicabilityScan(auditCmd.thirdPartyApplicabilityScan).
Expand Down Expand Up @@ -212,6 +213,11 @@ func RunAudit(auditParams *AuditParams) (cmdResults *results.SecurityCommandResu
auditParallelRunner.Runner.Done()
}()
auditParallelRunner.Runner.Run()

/*Filter out non-applicative results after getting the applicability results*/
if auditParams.skipNotApplicableCves {
jas.FilterSkipNotApplicable(cmdResults)
}
return
}

Expand Down
10 changes: 10 additions & 0 deletions commands/audit/auditparams.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type AuditParams struct {
workingDirs []string
installFunc func(tech string) error
fixableOnly bool
skipNotApplicableCves bool
minSeverityFilter severityutils.Severity
*xrayutils.AuditBasicParams
multiScanId string
Expand Down Expand Up @@ -83,6 +84,15 @@ func (params *AuditParams) SetFixableOnly(fixable bool) *AuditParams {
return params
}

func (params *AuditParams) SkipNotApplicableCves() bool {
return params.skipNotApplicableCves
}

func (params *AuditParams) SetSkipNotApplicableCves(skip bool) *AuditParams {
params.skipNotApplicableCves = skip
return params
}

func (params *AuditParams) MinSeverityFilter() severityutils.Severity {
return params.minSeverityFilter
}
Expand Down
11 changes: 11 additions & 0 deletions commands/scan/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ type ScanCommand struct {
validateSecrets bool
bypassArchiveLimits bool
fixableOnly bool
skipNotApplicableCves bool
progress ioUtils.ProgressMgr
// JAS is only supported for Docker images.
commandSupportsJAS bool
Expand All @@ -97,6 +98,11 @@ func (scanCmd *ScanCommand) SetFixableOnly(fixable bool) *ScanCommand {
return scanCmd
}

func (scanCmd *ScanCommand) SetSkipNotApplicableCves(skip bool) *ScanCommand {
scanCmd.skipNotApplicableCves = skip
return scanCmd
}

func (scanCmd *ScanCommand) SetRunJasScans(run bool) *ScanCommand {
scanCmd.commandSupportsJAS = run
return scanCmd
Expand Down Expand Up @@ -248,6 +254,10 @@ func (scanCmd *ScanCommand) RunAndRecordResults(cmdType utils.CommandType, recor
}
}

if scanCmd.skipNotApplicableCves {
jas.FilterSkipNotApplicable(cmdResults)
}

if err = output.NewResultsWriter(cmdResults).
SetOutputFormat(scanCmd.outputFormat).
SetHasViolationContext(scanCmd.hasViolationContext()).
Expand Down Expand Up @@ -463,6 +473,7 @@ func (scanCmd *ScanCommand) createIndexerHandlerFunc(file *spec.File, cmdResults
SetXrayGraphScanParams(params).
SetXrayVersion(cmdResults.XrayVersion).
SetFixableOnly(scanCmd.fixableOnly).
SetSkipNotApplicableCves(scanCmd.skipNotApplicableCves).
SetSeverityLevel(scanCmd.minSeverityFilter.String())
xrayManager, err := xray.CreateXrayServiceManager(scanGraphParams.ServerDetails())
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions jas/applicability/applicabilitymanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ func RunApplicabilityScan(xrayResults []services.ScanResponse, directDependencie
return
}
results = applicabilityScanManager.applicabilityScanResults

if len(results) > 0 {
log.Info(clientutils.GetLogMsgPrefix(threadId, false)+"Found", sarifutils.GetRulesPropertyCount("applicability", "applicable", results...), "applicable cves")
}
Expand Down
21 changes: 21 additions & 0 deletions jas/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/jfrog/jfrog-cli-security/utils"
"github.com/jfrog/jfrog-cli-security/utils/formats/sarifutils"
"github.com/jfrog/jfrog-cli-security/utils/jasutils"
"github.com/jfrog/jfrog-cli-security/utils/results"
"github.com/jfrog/jfrog-cli-security/utils/severityutils"
"github.com/jfrog/jfrog-cli-security/utils/techutils"
goclientutils "github.com/jfrog/jfrog-client-go/utils"
Expand Down Expand Up @@ -368,3 +369,23 @@ func CreateScannerTempDirectory(scanner *JasScanner, scanType string) (string, e
}
return scannerTempDir, nil
}

func FilterSkipNotApplicable(results *results.SecurityCommandResults) {
for _, target := range results.Targets {
filterScaResultsFromJas(target.ScaResults, target.JasResults)
}
}

func filterScaResultsFromJas(scaResults *results.ScaScanResults, jasResults *results.JasScansResults) {
filteredViolations := []services.Violation{}
for i := range scaResults.XrayResults {
xrayResult := &scaResults.XrayResults[i]
for _, violation := range xrayResult.Violations {
if !sarifutils.IsRuleNameHasProperty("applicability", violation.Cves[0].Id, "not_applicable", jasResults.ApplicabilityScanResults...) {
filteredViolations = append(filteredViolations, violation)
xrayResult.Violations = append(xrayResult.Violations, violation)
}
}
xrayResult.Violations = filteredViolations
}
}
14 changes: 13 additions & 1 deletion utils/formats/sarifutils/sarifutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package sarifutils

import (
"fmt"
"github.com/jfrog/jfrog-cli-security/utils/jasutils"
"path/filepath"
"strings"

"github.com/jfrog/jfrog-cli-security/utils/jasutils"

"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/owenrumney/go-sarif/v2/sarif"
)
Expand Down Expand Up @@ -716,3 +717,14 @@ func GetResultFingerprint(result *sarif.Result) string {
}
return ""
}

func IsRuleNameHasProperty(property, name string, value string, runs ...*sarif.Run) bool {
for _, run := range runs {
for _, rule := range run.Tool.Driver.Rules {
if rule.Name != nil && *rule.Name == name {
return rule.Properties[property] != nil && rule.Properties[property] == value
}
}
}
return false
}
50 changes: 49 additions & 1 deletion utils/formats/sarifutils/sarifutils_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package sarifutils

import (
"github.com/jfrog/jfrog-cli-security/utils/jasutils"
"path/filepath"
"testing"

"github.com/jfrog/jfrog-cli-security/utils/jasutils"

"github.com/jfrog/jfrog-cli-security/utils/severityutils"
"github.com/owenrumney/go-sarif/v2/sarif"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -643,3 +644,50 @@ func TestGetResultFingerprint(t *testing.T) {
assert.Equal(t, test.expectedOutput, GetResultFingerprint(test.result))
}
}

func TestIsRuleNameHasProperty(t *testing.T) {
tests := []struct {
name string
runs []*sarif.Run
parameters []string
expectedOutput bool
}{
{
name: "Empty Run",
runs: []*sarif.Run{},
parameters: []string{"applicability", "CVE-1111-123", "applicable"},
expectedOutput: false,
},
{
name: "Rule Has Applicable Property With CVE Name",
runs: []*sarif.Run{
CreateRunsWithReportingDescriptor("applicability", "CVE-1111-123", "applicable"),
CreateRunsWithReportingDescriptor("applicability", "CVE-2222-123", "applicable"),
},
parameters: []string{"applicability", "CVE-1111-123", "applicable"},
expectedOutput: true,
},
{
name: "UnMatching Names",
runs: []*sarif.Run{
CreateRunsWithReportingDescriptor("applicability", "CVE-1111-123", "applicable"),
CreateRunsWithReportingDescriptor("applicability", "CVE-2222-123", "applicable"),
},
parameters: []string{"applicability", "CVE-3333-123", "applicable"},
expectedOutput: false,
},
{
name: "UnMatching Property value",
runs: []*sarif.Run{
CreateRunsWithReportingDescriptor("applicability", "CVE-1111-123", "not_applicable"),
CreateRunsWithReportingDescriptor("applicability", "CVE-2222-123", "applicable"),
},
parameters: []string{"applicability", "CVE-1111-123", "applicable"},
expectedOutput: false,
},
}

for _, test := range tests {
assert.Equal(t, IsRuleNameHasProperty(test.parameters[0], test.parameters[1], test.parameters[2], test.runs...), test.expectedOutput)
}
}
14 changes: 14 additions & 0 deletions utils/formats/sarifutils/test_sarifutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,17 @@ func CreateThreadFlow(locations ...*sarif.Location) *sarif.ThreadFlow {
}
return stackStrace
}

func CreateRunsWithReportingDescriptor(property, name string, value string) *sarif.Run {
run := CreateRunWithDummyResults(
CreateDummyPassingResult("rule"),
)
for _, rule := range run.Tool.Driver.Rules {
rule.Name = &name
rule.Properties = map[string]interface{}{
property: value,
}
}

return run
}
Loading
Loading