Skip to content

Commit 34e386f

Browse files
committed
feat: translate each Evidence Path on a finding into a separate legacy JSON finding
- the output is one JSON entry per route to the finding. - The code creates a separate vulnerability for each dependency_path evidence chain. Each vulnerability is a clone except their "from" fields vary to reflect the evidence. - This allows snyk-to-html to aggregate them under one common name with multiple "Introduced Through" paths.
1 parent 96785a1 commit 34e386f

File tree

1 file changed

+70
-21
lines changed

1 file changed

+70
-21
lines changed

internal/legacy/transform/transform.go

Lines changed: 70 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ const (
1515
cvssVer3 = "3.1"
1616
snykAssigner = "Snyk"
1717

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"
2021
)
2122

2223
// SnykSchemaToLegacyParams is a struct to encapsulate necessary values to the
@@ -305,39 +306,85 @@ func ProcessEvidenceForFinding(vuln *definitions.Vulnerability, ev *testapi.Evid
305306
return nil
306307
}
307308

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
309310
// 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}
312316
for _, problem := range finding.Attributes.Problems {
313-
err := ProcessProblemForVuln(&vuln, &problem, logger)
317+
err := ProcessProblemForVuln(&baseVuln, &problem, logger)
314318
if err != nil {
315319
return nil, fmt.Errorf("handling problem for finding: %w", err)
316320
}
317321
}
318322

319323
for _, location := range finding.Attributes.Locations {
320-
err := ProcessLocationForVuln(&vuln, &location, logger)
324+
err := ProcessLocationForVuln(&baseVuln, &location, logger)
321325
if err != nil {
322326
return nil, fmt.Errorf("processing location for finding: %w", err)
323327
}
324328
}
325329

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+
}
327338

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
328345
for _, ev := range finding.Attributes.Evidence {
329-
err := ProcessEvidenceForFinding(&vuln, &ev)
346+
evDisc, err := ev.Discriminator()
330347
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)
332354
}
333355
}
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)
338385
}
339386

340-
return &vuln, nil
387+
return vulns, nil
341388
}
342389

343390
// ConvertSnykSchemaFindingsToLegacy is a function that converts snyk schema findings into
@@ -365,17 +412,19 @@ func ConvertSnykSchemaFindingsToLegacy(params *SnykSchemaToLegacyParams) (*defin
365412
}
366413

367414
for _, finding := range params.Findings {
368-
vuln, err := FindingToLegacyVuln(&finding, params.Logger)
415+
vulns, err := FindingToLegacyVulns(&finding, params.Logger)
369416
if err != nil {
370417
return nil, params.ErrFactory.NewLegacyJSONTransformerError(fmt.Errorf("converting finding to legacy vuln: %w", err))
371418
}
372419

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])
377427
}
378-
res.Vulnerabilities = append(res.Vulnerabilities, *vuln)
379428
}
380429

381430
return &res, nil

0 commit comments

Comments
 (0)