Skip to content

Commit 135b0b5

Browse files
authored
Fix breaking changes in remediation API (#616)
1 parent 675cc37 commit 135b0b5

File tree

7 files changed

+180
-161
lines changed

7 files changed

+180
-161
lines changed

cli/docs/flags.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ var commandFlags = map[string][]string{
173173
binarySca, binarySecrets, binaryWithoutCA, SecretValidation,
174174
},
175175
Enrich: {
176-
Url, user, password, accessToken, ServerId, Threads, InsecureTls,
176+
Url, XrayUrl, user, password, accessToken, ServerId, Threads, InsecureTls,
177177
},
178178
BuildScan: {
179179
Url, XrayUrl, user, password, accessToken, ServerId, scanProjectKey, BuildVuln, OutputFormat, Fail, ExtendedTable, Rescan, InsecureTls, TriggerScanRetries,

go.mod

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ require (
1212
github.com/hashicorp/go-hclog v1.6.3
1313
github.com/hashicorp/go-plugin v1.6.3
1414
github.com/jfrog/build-info-go v1.12.5-0.20251209171349-eb030db986f9
15-
github.com/jfrog/froggit-go v1.20.4
15+
github.com/jfrog/froggit-go v1.20.6
1616
github.com/jfrog/gofrog v1.7.6
1717
github.com/jfrog/jfrog-apps-config v1.0.1
18-
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251210120128-176c677fed4c
19-
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251125083543-e689762c4ff0
20-
github.com/jfrog/jfrog-client-go v1.55.1-0.20251209090954-d6b1c70d3a5e
18+
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251211075913-35ebcd308e93
19+
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251210085744-f8481d179ac5
20+
github.com/jfrog/jfrog-client-go v1.55.1-0.20251211124639-306f15dbcf29
2121
github.com/magiconair/properties v1.8.10
2222
github.com/owenrumney/go-sarif/v3 v3.2.3
2323
github.com/package-url/packageurl-go v0.1.3

go.sum

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -148,18 +148,18 @@ github.com/jfrog/archiver/v3 v3.6.1 h1:LOxnkw9pOn45DzCbZNFV6K0+6dCsQ0L8mR3ZcujO5
148148
github.com/jfrog/archiver/v3 v3.6.1/go.mod h1:VgR+3WZS4N+i9FaDwLZbq+jeU4B4zctXL+gL4EMzfLw=
149149
github.com/jfrog/build-info-go v1.12.5-0.20251209171349-eb030db986f9 h1:CL7lp7Y7srwQ1vy1btX66t4wbztzEGQbqi/9tdEz7xk=
150150
github.com/jfrog/build-info-go v1.12.5-0.20251209171349-eb030db986f9/go.mod h1:9W4U440fdTHwW1HiB/R0VQvz/5q8ZHsms9MWcq+JrdY=
151-
github.com/jfrog/froggit-go v1.20.4 h1:N9XkNV00HNjpI8p6xXlF9DrWmvE9hz3z2XRDAYJDweQ=
152-
github.com/jfrog/froggit-go v1.20.4/go.mod h1:obSG1SlsWjktkuqmKtpq7MNTTL63e0ot+ucTnlOMV88=
151+
github.com/jfrog/froggit-go v1.20.6 h1:Xp7+LlEh0m1KGrQstb+u0aGfjRUtv1eh9xQBV3571jQ=
152+
github.com/jfrog/froggit-go v1.20.6/go.mod h1:obSG1SlsWjktkuqmKtpq7MNTTL63e0ot+ucTnlOMV88=
153153
github.com/jfrog/gofrog v1.7.6 h1:QmfAiRzVyaI7JYGsB7cxfAJePAZTzFz0gRWZSE27c6s=
154154
github.com/jfrog/gofrog v1.7.6/go.mod h1:ntr1txqNOZtHplmaNd7rS4f8jpA5Apx8em70oYEe7+4=
155155
github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYLipdsOFMY=
156156
github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w=
157-
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251210120128-176c677fed4c h1:uMs18TfF/472CsaoI3HAsvyo9B8ChFh855BdicqoT4c=
158-
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251210120128-176c677fed4c/go.mod h1:7cCaRhXorlbyXZgiW5bplCExFxlnROaG21K12d8inpQ=
159-
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251125083543-e689762c4ff0 h1:EsasTBE5i2MyCESS/icZxKIlObpGiOyW9K67MAaEWco=
160-
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251125083543-e689762c4ff0/go.mod h1:d9aADumiyjCBvZLffp8wldvP9XFHxcvk2PoOSUYms2g=
161-
github.com/jfrog/jfrog-client-go v1.55.1-0.20251209090954-d6b1c70d3a5e h1:9le3a99UGdBHZXv7vZ7aqxLyBpwMq+sbTWiOaI9pwCU=
162-
github.com/jfrog/jfrog-client-go v1.55.1-0.20251209090954-d6b1c70d3a5e/go.mod h1:WQ5Y+oKYyHFAlCbHN925bWhnShTd2ruxZ6YTpb76fpU=
157+
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251211075913-35ebcd308e93 h1:rpkJZN0TigpAGY/bfgmLO4nwhyhkr0gkBTLz/0B5zS8=
158+
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251211075913-35ebcd308e93/go.mod h1:7cCaRhXorlbyXZgiW5bplCExFxlnROaG21K12d8inpQ=
159+
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251210085744-f8481d179ac5 h1:GYE67ubwl+ZRw3CcXFUi49EwwQp6k+qS8sX0QuHDHO8=
160+
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251210085744-f8481d179ac5/go.mod h1:BMoGi2rG0udCCeaghqlNgiW3fTmT+TNnfTnBoWFYgcg=
161+
github.com/jfrog/jfrog-client-go v1.55.1-0.20251211124639-306f15dbcf29 h1:u+FMai2cImOJExJ1Ehe8JsrpAXmPyRaDXwM60wV3bPA=
162+
github.com/jfrog/jfrog-client-go v1.55.1-0.20251211124639-306f15dbcf29/go.mod h1:WQ5Y+oKYyHFAlCbHN925bWhnShTd2ruxZ6YTpb76fpU=
163163
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
164164
github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo=
165165
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=

utils/results/conversion/cyclonedxparser/cyclonedxparser.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ func (cdc *CmdResultsCycloneDxConverter) getOrCreateFileComponent(filePathOrUri
334334
return &(*cdc.bom.Components)[len(*cdc.bom.Components)-1]
335335
}
336336

337-
func (cdc *CmdResultsCycloneDxConverter) getOrCreateJasIssue(ref, id, msg, description string, source *cyclonedx.Service, cwe []string, ratings []cyclonedx.VulnerabilityRating, properties ...cyclonedx.Property) (vulnerability *cyclonedx.Vulnerability) {
337+
func (cdc *CmdResultsCycloneDxConverter) getOrCreateJasIssue(ref, id, msg, description string, source *cyclonedx.Service, cwe []string, ratings []cyclonedx.VulnerabilityRating) (vulnerability *cyclonedx.Vulnerability) {
338338
if vulnerability = cdxutils.SearchVulnerabilityByRef(&cdc.bom.BOM, ref); vulnerability != nil {
339339
return
340340
}
@@ -351,7 +351,7 @@ func (cdc *CmdResultsCycloneDxConverter) getOrCreateJasIssue(ref, id, msg, descr
351351
CWE: cwe,
352352
Ratings: ratings,
353353
}
354-
*cdc.bom.Vulnerabilities = append(*cdc.bom.Vulnerabilities, cdxutils.CreateBaseVulnerability(params, properties...))
354+
*cdc.bom.Vulnerabilities = append(*cdc.bom.Vulnerabilities, cdxutils.CreateBaseVulnerability(params))
355355
return &(*cdc.bom.Vulnerabilities)[len(*cdc.bom.Vulnerabilities)-1]
356356
}
357357

utils/results/conversion/summaryparser/summaryparser.go

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ func (sc *CmdResultsSummaryConverter) ParseSecrets(secrets ...[]*sarif.Run) (err
240240
if sc.currentScan.Vulnerabilities.SecretsResults == nil {
241241
sc.currentScan.Vulnerabilities.SecretsResults = &formats.ResultSummary{}
242242
}
243-
return results.ForEachJasIssue(results.CollectRuns(secrets...), sc.entitledForJas, sc.getJasHandler(jasutils.Secrets, false))
243+
return results.ForEachJasIssue(results.CollectRuns(secrets...), sc.entitledForJas, sc.getJasHandler(jasutils.Secrets))
244244
}
245245

246246
func (sc *CmdResultsSummaryConverter) ParseIacs(iacs ...[]*sarif.Run) (err error) {
@@ -255,7 +255,7 @@ func (sc *CmdResultsSummaryConverter) ParseIacs(iacs ...[]*sarif.Run) (err error
255255
if sc.currentScan.Vulnerabilities.IacResults == nil {
256256
sc.currentScan.Vulnerabilities.IacResults = &formats.ResultSummary{}
257257
}
258-
return results.ForEachJasIssue(results.CollectRuns(iacs...), sc.entitledForJas, sc.getJasHandler(jasutils.IaC, false))
258+
return results.ForEachJasIssue(results.CollectRuns(iacs...), sc.entitledForJas, sc.getJasHandler(jasutils.IaC))
259259
}
260260

261261
func (sc *CmdResultsSummaryConverter) ParseSast(sast ...[]*sarif.Run) (err error) {
@@ -269,11 +269,11 @@ func (sc *CmdResultsSummaryConverter) ParseSast(sast ...[]*sarif.Run) (err error
269269
if sc.currentScan.Vulnerabilities.SastResults == nil {
270270
sc.currentScan.Vulnerabilities.SastResults = &formats.ResultSummary{}
271271
}
272-
return results.ForEachJasIssue(results.CollectRuns(sast...), sc.entitledForJas, sc.getJasHandler(jasutils.Sast, false))
272+
return results.ForEachJasIssue(results.CollectRuns(sast...), sc.entitledForJas, sc.getJasHandler(jasutils.Sast))
273273
}
274274

275275
// getJasHandler returns a handler that counts the JAS results (based on severity and CA status) for each issue it handles
276-
func (sc *CmdResultsSummaryConverter) getJasHandler(scanType jasutils.JasScanType, violations bool) results.ParseJasIssueFunc {
276+
func (sc *CmdResultsSummaryConverter) getJasHandler(scanType jasutils.JasScanType) results.ParseJasIssueFunc {
277277
return func(run *sarif.Run, rule *sarif.ReportingDescriptor, severity severityutils.Severity, result *sarif.Result, location *sarif.Location) (err error) {
278278
// Get the count map in the `sc.currentScan` object based on the scanType and violation
279279
resultStatus := formats.NoStatus
@@ -283,23 +283,11 @@ func (sc *CmdResultsSummaryConverter) getJasHandler(scanType jasutils.JasScanTyp
283283
if tokenStatus := sarifutils.GetResultPropertyTokenValidation(result); tokenStatus != "" {
284284
resultStatus = tokenStatus
285285
}
286-
if violations {
287-
count = sc.currentScan.Violations.SecretsResults
288-
} else {
289-
count = sc.currentScan.Vulnerabilities.SecretsResults
290-
}
286+
count = sc.currentScan.Vulnerabilities.SecretsResults
291287
case jasutils.IaC:
292-
if violations {
293-
count = sc.currentScan.Violations.IacResults
294-
} else {
295-
count = sc.currentScan.Vulnerabilities.IacResults
296-
}
288+
count = sc.currentScan.Vulnerabilities.IacResults
297289
case jasutils.Sast:
298-
if violations {
299-
count = sc.currentScan.Violations.SastResults
300-
} else {
301-
count = sc.currentScan.Vulnerabilities.SastResults
302-
}
290+
count = sc.currentScan.Vulnerabilities.SastResults
303291
}
304292
countJasIssues(count, location, severity, resultStatus)
305293
return

utils/xray/remediation/cdxremediation.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@ func AttachFixedVersionsToVulnerabilities(xrayManager *xray.XrayServicesManager,
2323
return fmt.Errorf("failed to get remediation options from Xray: %w", err)
2424
}
2525
log.Verbose(fmt.Sprintf("Remediation options received from Xray: %+v", remediationOptions))
26+
// Right now, we only support QuickestFixStrategy (fixing the actual component to a specific version)
27+
strategy := utils.QuickestFixStrategy
2628
for _, vulnerability := range *bom.Vulnerabilities {
27-
matchVulnerabilityToRemediationOptions(bom, &vulnerability, remediationOptions)
29+
matchVulnerabilityToRemediationOptions(bom, &vulnerability, remediationOptions, strategy)
2830
}
2931
return nil
3032
}
3133

32-
func matchVulnerabilityToRemediationOptions(bom *cyclonedx.BOM, vulnerability *cyclonedx.Vulnerability, remediationOptions utils.CveRemediationResponse) {
34+
func matchVulnerabilityToRemediationOptions(bom *cyclonedx.BOM, vulnerability *cyclonedx.Vulnerability, remediationOptions utils.CveRemediationResponse, strategy utils.FixStrategy) {
3335
if vulnerability.Affects == nil || len(*vulnerability.Affects) == 0 {
3436
log.Debug("No affected components found for vulnerability " + vulnerability.ID + ", skipping attaching fixed versions")
3537
return
@@ -43,7 +45,7 @@ func matchVulnerabilityToRemediationOptions(bom *cyclonedx.BOM, vulnerability *c
4345
continue
4446
}
4547
// Convert remediation steps to fixed versions affected versions
46-
for _, step := range getAffectComponentCveRemediationStepsByFixedVersion(vulnerability.ID, *affectComponent, cveRemediationOptions) {
48+
for _, step := range getAffectComponentCveRemediationStepsByFixedVersion(vulnerability.ID, *affectComponent, cveRemediationOptions, strategy) {
4749
cdxutils.AppendAffectedVersionsIfNotExists(&affect, cyclonedx.AffectedVersions{
4850
Version: step.UpgradeTo.Version,
4951
Status: cyclonedx.VulnerabilityStatusNotAffected,
@@ -56,13 +58,18 @@ func matchVulnerabilityToRemediationOptions(bom *cyclonedx.BOM, vulnerability *c
5658
}
5759
}
5860

59-
func getAffectComponentCveRemediationStepsByFixedVersion(cve string, component cyclonedx.Component, cveRemediationOptions []utils.Option) (steps []utils.OptionStep) {
61+
func getAffectComponentCveRemediationStepsByFixedVersion(cve string, component cyclonedx.Component, cveRemediationOptions []utils.Option, strategy utils.FixStrategy) (steps []utils.OptionStep) {
6062
for _, cveRemediationOption := range cveRemediationOptions {
6163
if cveRemediationOption.Type != utils.InLock {
6264
// We only want InLock remediation type (forcing the actual component to a specific fix version)
6365
continue
6466
}
65-
for _, step := range cveRemediationOption.Steps {
67+
stepsMap, found := cveRemediationOption.Steps[strategy]
68+
if !found || len(stepsMap) == 0 {
69+
log.Debug(fmt.Sprintf("No remediation steps found for strategy '%d' for component '%s' in vulnerability '%s'", strategy, component.Name, cve))
70+
continue
71+
}
72+
for _, step := range stepsMap {
6673
if step.StepType == utils.NoFixVersion {
6774
log.Debug(fmt.Sprintf("No fix version available for component '%s' in vulnerability '%s'", component.Name, cve))
6875
continue

0 commit comments

Comments
 (0)