@@ -15,8 +15,9 @@ const (
15
15
cvssVer3 = "3.1"
16
16
snykAssigner = "Snyk"
17
17
18
- legacyTimeFormat = "2006-01-02T15:04:05.000000Z"
19
- logFieldDiscriminator = "discriminator"
18
+ legacyTimeFormat = "2006-01-02T15:04:05.000000Z"
19
+ logFieldDiscriminator = "discriminator"
20
+ errProcessEvidenceForFindingStr = "processing evidence for finding: %w"
20
21
)
21
22
22
23
// SnykSchemaToLegacyParams is a struct to encapsulate necessary values to the
@@ -305,39 +306,85 @@ func ProcessEvidenceForFinding(vuln *definitions.Vulnerability, ev *testapi.Evid
305
306
return nil
306
307
}
307
308
308
- // FindingToLegacyVuln is the beginning of the workflow in converting a snyk schema finding into
309
+ // FindingToLegacyVulns is the beginning of the workflow in converting a snyk schema finding into
309
310
// a legacy vulnerability to provide legacy json outputs.
310
- func FindingToLegacyVuln (finding * testapi.FindingData , logger * zerolog.Logger ) (* definitions.Vulnerability , error ) {
311
- vuln := definitions.Vulnerability {Description : finding .Attributes .Description }
311
+ func FindingToLegacyVulns (
312
+ finding * testapi.FindingData ,
313
+ logger * zerolog.Logger ,
314
+ ) ([]definitions.Vulnerability , error ) {
315
+ baseVuln := definitions.Vulnerability {Description : finding .Attributes .Description }
312
316
for _ , problem := range finding .Attributes .Problems {
313
- err := ProcessProblemForVuln (& vuln , & problem , logger )
317
+ err := ProcessProblemForVuln (& baseVuln , & problem , logger )
314
318
if err != nil {
315
319
return nil , fmt .Errorf ("handling problem for finding: %w" , err )
316
320
}
317
321
}
318
322
319
323
for _ , location := range finding .Attributes .Locations {
320
- err := ProcessLocationForVuln (& vuln , & location , logger )
324
+ err := ProcessLocationForVuln (& baseVuln , & location , logger )
321
325
if err != nil {
322
326
return nil , fmt .Errorf ("processing location for finding: %w" , err )
323
327
}
324
328
}
325
329
326
- vuln .From = []string {}
330
+ baseVuln .Title = finding .Attributes .Title
331
+ baseVuln .Severity = definitions .VulnerabilitySeverity (string (finding .Attributes .Rating .Severity ))
332
+ if finding .Attributes .Risk .RiskScore != nil {
333
+ baseVuln .RiskScore = & finding .Attributes .Risk .RiskScore .Value
334
+ }
335
+
336
+ return processEvidences (finding , & baseVuln )
337
+ }
327
338
339
+ func processEvidences (
340
+ finding * testapi.FindingData ,
341
+ baseVuln * definitions.Vulnerability ,
342
+ ) ([]definitions.Vulnerability , error ) {
343
+ var depPathEvidences []testapi.Evidence
344
+ var otherEvidences []testapi.Evidence
328
345
for _ , ev := range finding .Attributes .Evidence {
329
- err := ProcessEvidenceForFinding ( & vuln , & ev )
346
+ evDisc , err := ev . Discriminator ( )
330
347
if err != nil {
331
- return nil , fmt .Errorf ("processing evidence for finding: %w" , err )
348
+ return nil , fmt .Errorf ("getting evidence discriminator: %w" , err )
349
+ }
350
+ if evDisc == string (testapi .DependencyPath ) {
351
+ depPathEvidences = append (depPathEvidences , ev )
352
+ } else {
353
+ otherEvidences = append (otherEvidences , ev )
332
354
}
333
355
}
334
- vuln .Title = finding .Attributes .Title
335
- vuln .Severity = definitions .VulnerabilitySeverity (string (finding .Attributes .Rating .Severity ))
336
- if finding .Attributes .Risk .RiskScore != nil {
337
- vuln .RiskScore = & finding .Attributes .Risk .RiskScore .Value
356
+
357
+ var vulns []definitions.Vulnerability
358
+ if len (depPathEvidences ) > 0 {
359
+ // Create a new legacy vulnerability for each dependency path evidence.
360
+ for _ , depPathEv := range depPathEvidences {
361
+ vuln := * baseVuln
362
+ vuln .From = []string {}
363
+ err := ProcessEvidenceForFinding (& vuln , & depPathEv )
364
+ if err != nil {
365
+ return nil , fmt .Errorf (errProcessEvidenceForFindingStr , err )
366
+ }
367
+ for _ , otherEv := range otherEvidences {
368
+ err := ProcessEvidenceForFinding (& vuln , & otherEv )
369
+ if err != nil {
370
+ return nil , fmt .Errorf (errProcessEvidenceForFindingStr , err )
371
+ }
372
+ }
373
+ vulns = append (vulns , vuln )
374
+ }
375
+ } else {
376
+ vuln := * baseVuln
377
+ vuln .From = []string {}
378
+ for _ , ev := range finding .Attributes .Evidence {
379
+ err := ProcessEvidenceForFinding (& vuln , & ev )
380
+ if err != nil {
381
+ return nil , fmt .Errorf (errProcessEvidenceForFindingStr , err )
382
+ }
383
+ }
384
+ vulns = append (vulns , vuln )
338
385
}
339
386
340
- return & vuln , nil
387
+ return vulns , nil
341
388
}
342
389
343
390
// ConvertSnykSchemaFindingsToLegacy is a function that converts snyk schema findings into
@@ -365,17 +412,19 @@ func ConvertSnykSchemaFindingsToLegacy(params *SnykSchemaToLegacyParams) (*defin
365
412
}
366
413
367
414
for _ , finding := range params .Findings {
368
- vuln , err := FindingToLegacyVuln (& finding , params .Logger )
415
+ vulns , err := FindingToLegacyVulns (& finding , params .Logger )
369
416
if err != nil {
370
417
return nil , params .ErrFactory .NewLegacyJSONTransformerError (fmt .Errorf ("converting finding to legacy vuln: %w" , err ))
371
418
}
372
419
373
- // The package manager can be specific to the vulnerability. If it's not set,
374
- // fall back to the one from the root of the dependency graph.
375
- if vuln .PackageManager == nil {
376
- vuln .PackageManager = & params .PackageManager
420
+ for i := range vulns {
421
+ // The package manager can be specific to the vulnerability. If it's not set,
422
+ // fall back to the one from the root of the dependency graph.
423
+ if vulns [i ].PackageManager == nil {
424
+ vulns [i ].PackageManager = & params .PackageManager
425
+ }
426
+ res .Vulnerabilities = append (res .Vulnerabilities , vulns [i ])
377
427
}
378
- res .Vulnerabilities = append (res .Vulnerabilities , * vuln )
379
428
}
380
429
381
430
return & res , nil
0 commit comments