Skip to content

Commit c6bf3c9

Browse files
authored
Add impactPaths field to rule properties in Sarif output for SCA scan
1 parent 0036661 commit c6bf3c9

File tree

4 files changed

+125
-5
lines changed

4 files changed

+125
-5
lines changed

utils/formats/sarifutils/sarifutils.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ import (
1111
)
1212

1313
const (
14-
WatchSarifPropertyKey = "watch"
15-
PoliciesSarifPropertyKey = "policies"
16-
JasIssueIdSarifPropertyKey = "issueId"
17-
CWEPropertyKey = "CWE"
14+
WatchSarifPropertyKey = "watch"
15+
PoliciesSarifPropertyKey = "policies"
16+
JasIssueIdSarifPropertyKey = "issueId"
17+
CWEPropertyKey = "CWE"
18+
SarifImpactPathsRulePropertyKey = "impactPaths"
1819
)
1920

2021
// Specific JFrog Sarif Utils

utils/formats/sarifutils/test_sarifutils.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package sarifutils
22

33
import (
4+
"github.com/jfrog/jfrog-cli-security/utils/formats"
5+
"github.com/jfrog/jfrog-cli-security/utils/severityutils"
46
"github.com/owenrumney/go-sarif/v2/sarif"
57
)
68

@@ -78,6 +80,14 @@ func CreateRunWithDummyResultAndRuleProperties(result *sarif.Result, properties,
7880
return run
7981
}
8082

83+
func CreateDummyRule(impactPaths [][]formats.ComponentRow, ruleId, ruleDescription, summary, markdownDescription, maxCveScore string) *sarif.ReportingDescriptor {
84+
var ruleProperties = sarif.NewPropertyBag()
85+
ruleProperties.Add(severityutils.SarifSeverityRuleProperty, maxCveScore)
86+
ruleProperties.Add(SarifImpactPathsRulePropertyKey, impactPaths)
87+
return sarif.NewRule(ruleId).WithProperties(ruleProperties.Properties).WithDescription(ruleDescription).WithHelp(sarif.NewMultiformatMessageString(summary).WithMarkdown(markdownDescription))
88+
89+
}
90+
8191
func CreateDummyResultInPath(fileName string) *sarif.Result {
8292
return CreateResultWithOneLocation(fileName, 0, 0, 0, 0, "snippet", "rule", "level")
8393
}

utils/results/conversion/sarifparser/sarifparser.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ type scaParseParams struct {
8585
FixedVersions []string
8686
DirectComponents []formats.ComponentRow
8787
Violation *violationContext
88+
ImpactPaths [][]formats.ComponentRow
8889
}
8990

9091
// holds the violation context for the results
@@ -343,6 +344,7 @@ func addSarifScaVulnerability(cmdType utils.CommandType, sarifResults *[]*sarif.
343344
ImpactedPackagesVersion: impactedPackagesVersion,
344345
FixedVersions: fixedVersions,
345346
DirectComponents: directComponents,
347+
ImpactPaths: impactPaths,
346348
})
347349
cveImpactedComponentRuleId := results.GetScaIssueId(impactedPackagesName, impactedPackagesVersion, results.GetIssueIdentifier(cves, vulnerability.IssueId, "_"))
348350
if _, ok := (*rules)[cveImpactedComponentRuleId]; !ok {
@@ -379,6 +381,7 @@ func addSarifScaSecurityViolation(cmdType utils.CommandType, sarifResults *[]*sa
379381
ImpactedPackagesVersion: impactedPackagesVersion,
380382
FixedVersions: fixedVersions,
381383
DirectComponents: directComponents,
384+
ImpactPaths: impactPaths,
382385
Violation: &violationContext{
383386
Watch: violation.WatchName,
384387
Policies: results.ConvertPolicesToString(violation.Policies),
@@ -419,6 +422,7 @@ func addSarifScaLicenseViolation(cmdType utils.CommandType, sarifResults *[]*sar
419422
ImpactedPackagesVersion: impactedPackagesVersion,
420423
FixedVersions: fixedVersions,
421424
DirectComponents: directComponents,
425+
ImpactPaths: impactPaths,
422426
Violation: &violationContext{
423427
Watch: violation.WatchName,
424428
Policies: results.ConvertPolicesToString(violation.Policies),
@@ -441,6 +445,7 @@ func parseScaToSarifFormat(params scaParseParams) (sarifResults []*sarif.Result,
441445
level := severityutils.SeverityToSarifSeverityLevel(params.Severity)
442446
// Add rule for the cve if not exists
443447
rule = getScaIssueSarifRule(
448+
params.ImpactPaths,
444449
cveImpactedComponentRuleId,
445450
params.GenerateTitleFunc(params.ImpactedPackagesName, params.ImpactedPackagesVersion, issueId, params.Watch),
446451
params.CveScore,
@@ -478,9 +483,12 @@ func parseScaToSarifFormat(params scaParseParams) (sarifResults []*sarif.Result,
478483
return
479484
}
480485

481-
func getScaIssueSarifRule(ruleId, ruleDescription, maxCveScore, summary, markdownDescription string) *sarif.ReportingDescriptor {
486+
func getScaIssueSarifRule(impactPaths [][]formats.ComponentRow, ruleId, ruleDescription, maxCveScore, summary, markdownDescription string) *sarif.ReportingDescriptor {
482487
cveRuleProperties := sarif.NewPropertyBag()
483488
cveRuleProperties.Add(severityutils.SarifSeverityRuleProperty, maxCveScore)
489+
if len(impactPaths) > 0 {
490+
cveRuleProperties.Add(sarifutils.SarifImpactPathsRulePropertyKey, impactPaths)
491+
}
484492
return sarif.NewRule(ruleId).
485493
WithDescription(ruleDescription).
486494
WithHelp(sarif.NewMultiformatMessageString(summary).WithMarkdown(markdownDescription)).

utils/results/conversion/sarifparser/sarifparser_test.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,107 @@ func TestGetDirectDependenciesFormatted(t *testing.T) {
192192
}
193193
}
194194

195+
func TestGetScaIssueSarifRule(t *testing.T) {
196+
impactPathsTC1 := [][]formats.ComponentRow{
197+
{
198+
{
199+
Name: "example-package",
200+
Version: "1.0.0",
201+
},
202+
{
203+
Name: "dependency1",
204+
Version: "1.0.0",
205+
},
206+
},
207+
}
208+
impactPathsTC2 := [][]formats.ComponentRow{
209+
{
210+
{
211+
Name: "example-package",
212+
Version: "2.0.0",
213+
},
214+
{
215+
Name: "dependency1",
216+
Version: "1.0.0",
217+
},
218+
{
219+
Name: "dependency2",
220+
Version: "2.0.0",
221+
},
222+
},
223+
}
224+
impactPathsTC3 := [][]formats.ComponentRow{
225+
{
226+
{
227+
Name: "example-package-1",
228+
Version: "1.0.0",
229+
},
230+
{
231+
Name: "dependency1",
232+
Version: "1.0.0",
233+
},
234+
},
235+
{
236+
{
237+
Name: "example-package-2",
238+
Version: "2.0.0",
239+
},
240+
{
241+
Name: "dependency2",
242+
Version: "2.0.0",
243+
},
244+
},
245+
}
246+
testCases := []struct {
247+
name string
248+
impactPaths [][]formats.ComponentRow
249+
ruleId string
250+
ruleDescription string
251+
maxCveScore string
252+
summary string
253+
markdownDescription string
254+
expectedRule *sarif.ReportingDescriptor
255+
}{
256+
{
257+
name: "rule with impact paths",
258+
impactPaths: impactPathsTC1,
259+
ruleId: "rule-id-tc1",
260+
ruleDescription: "rule-description-tc1",
261+
maxCveScore: "7.5",
262+
summary: "summary-tc1",
263+
markdownDescription: "markdown-description-tc1",
264+
expectedRule: sarifutils.CreateDummyRule(impactPathsTC1, "rule-id-tc1", "rule-description-tc1", "summary-tc1", "markdown-description-tc1", "7.5"),
265+
},
266+
{
267+
name: "rule with impact paths with multiple dependencies",
268+
impactPaths: impactPathsTC2,
269+
ruleId: "rule-id-tc2",
270+
ruleDescription: "rule-description-tc2",
271+
maxCveScore: "8.0",
272+
summary: "summary-tc2",
273+
markdownDescription: "markdown-description-tc2",
274+
expectedRule: sarifutils.CreateDummyRule(impactPathsTC2, "rule-id-tc2", "rule-description-tc2", "summary-tc2", "markdown-description-tc2", "8.0"),
275+
},
276+
{
277+
name: "rule with multiple impact paths",
278+
impactPaths: impactPathsTC3,
279+
ruleId: "rule-id-tc3",
280+
ruleDescription: "rule-description-tc3",
281+
maxCveScore: "9.0",
282+
summary: "summary-tc3",
283+
markdownDescription: "markdown-description-tc3",
284+
expectedRule: sarifutils.CreateDummyRule(impactPathsTC3, "rule-id-tc3", "rule-description-tc3", "summary-tc3", "markdown-description-tc3", "9.0"),
285+
},
286+
}
287+
288+
for _, tc := range testCases {
289+
t.Run(tc.name, func(t *testing.T) {
290+
output := getScaIssueSarifRule(tc.impactPaths, tc.ruleId, tc.ruleDescription, tc.maxCveScore, tc.summary, tc.markdownDescription)
291+
assert.Equal(t, tc.expectedRule, output)
292+
})
293+
}
294+
}
295+
195296
func TestGetScaLicenseViolationMarkdown(t *testing.T) {
196297
testCases := []struct {
197298
name string

0 commit comments

Comments
 (0)