Skip to content

Commit c51c29d

Browse files
committed
set statusnote if all detail fields are empty
Signed-off-by: Irena Liu <[email protected]>
1 parent a7f86b8 commit c51c29d

File tree

4 files changed

+129
-11
lines changed

4 files changed

+129
-11
lines changed

internal/testing/testdata/exampledata/cyclonedx-vex-false-positive.json

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,38 @@
4545
]
4646
}
4747
]
48+
},
49+
{
50+
"id": "CVE-2024-0004",
51+
"source": {
52+
"name": "NVD",
53+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-0004"
54+
},
55+
"ratings": [
56+
{
57+
"source": {
58+
"name": "NVD",
59+
"url": "https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator"
60+
},
61+
"score": 6.0,
62+
"severity": "medium",
63+
"method": "CVSSv31"
64+
}
65+
],
66+
"analysis": {
67+
"state": "false_positive"
68+
},
69+
"affects": [
70+
{
71+
"ref": "urn:uuid:4e671687-395b-41f5-a30f-a58921a69b80/1#test-component-2-no-detail",
72+
"versions": [
73+
{
74+
"version": "1.0.0",
75+
"status": "unaffected"
76+
}
77+
]
78+
}
79+
]
4880
}
4981
]
5082
}

internal/testing/testdata/exampledata/cyclonedx-vex-resolved-with-pedigree.json

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,38 @@
4545
]
4646
}
4747
]
48+
},
49+
{
50+
"id": "CVE-2024-0003",
51+
"source": {
52+
"name": "NVD",
53+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-0003"
54+
},
55+
"ratings": [
56+
{
57+
"source": {
58+
"name": "NVD",
59+
"url": "https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator"
60+
},
61+
"score": 7.5,
62+
"severity": "high",
63+
"method": "CVSSv31"
64+
}
65+
],
66+
"analysis": {
67+
"state": "resolved_with_pedigree"
68+
},
69+
"affects": [
70+
{
71+
"ref": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79/1#test-component-no-detail",
72+
"versions": [
73+
{
74+
"version": "1.0.0",
75+
"status": "affected"
76+
}
77+
]
78+
}
79+
]
4880
}
4981
]
5082
}

internal/testing/testdata/testdata.go

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,22 @@ var (
326326
StatusNotes: "Vulnerability was falsely identified or associated with this component",
327327
KnownSince: time.Unix(0, 0).UTC(),
328328
}
329-
// Vulnerability specs for new test cases
329+
// VexData for resolved_with_pedigree status without detail (maps to VexStatusFixed)
330+
VexDataResolvedWithPedigreeNoDetail = &generated.VexStatementInputSpec{
331+
Status: generated.VexStatusFixed,
332+
VexJustification: generated.VexJustificationNotProvided,
333+
Statement: "",
334+
StatusNotes: "CDX state: resolved_with_pedigree",
335+
KnownSince: time.Unix(0, 0).UTC(),
336+
}
337+
// VexData for false_positive status without detail (maps to VexStatusNotAffected)
338+
VexDataFalsePositiveNoDetail = &generated.VexStatementInputSpec{
339+
Status: generated.VexStatusNotAffected,
340+
VexJustification: generated.VexJustificationNotProvided,
341+
Statement: "",
342+
StatusNotes: "CDX state: false_positive",
343+
KnownSince: time.Unix(0, 0).UTC(),
344+
}
330345
VulnSpecResolvedWithPedigree = &generated.VulnerabilityInputSpec{
331346
Type: "cve",
332347
VulnerabilityID: "cve-2024-0001",
@@ -335,6 +350,15 @@ var (
335350
Type: "cve",
336351
VulnerabilityID: "cve-2024-0002",
337352
}
353+
// Vulnerability specs for no-detail test cases
354+
VulnSpecResolvedWithPedigreeNoDetail = &generated.VulnerabilityInputSpec{
355+
Type: "cve",
356+
VulnerabilityID: "cve-2024-0003",
357+
}
358+
VulnSpecFalsePositiveNoDetail = &generated.VulnerabilityInputSpec{
359+
Type: "cve",
360+
VulnerabilityID: "cve-2024-0004",
361+
}
338362
// VulnMetadata for resolved_with_pedigree test
339363
CycloneDXResolvedWithPedigreeVulnMetadata = []assembler.VulnMetadataIngest{
340364
{
@@ -345,6 +369,14 @@ var (
345369
Timestamp: time.Unix(0, 0).UTC(),
346370
},
347371
},
372+
{
373+
Vulnerability: VulnSpecResolvedWithPedigreeNoDetail,
374+
VulnMetadata: &generated.VulnerabilityMetadataInputSpec{
375+
ScoreType: generated.VulnerabilityScoreTypeCvssv31,
376+
ScoreValue: 7.5,
377+
Timestamp: time.Unix(0, 0).UTC(),
378+
},
379+
},
348380
}
349381
// VulnMetadata for false_positive test
350382
CycloneDXFalsePositiveVulnMetadata = []assembler.VulnMetadataIngest{
@@ -356,6 +388,14 @@ var (
356388
Timestamp: time.Unix(0, 0).UTC(),
357389
},
358390
},
391+
{
392+
Vulnerability: VulnSpecFalsePositiveNoDetail,
393+
VulnMetadata: &generated.VulnerabilityMetadataInputSpec{
394+
ScoreType: generated.VulnerabilityScoreTypeCvssv31,
395+
ScoreValue: 6.0,
396+
Timestamp: time.Unix(0, 0).UTC(),
397+
},
398+
},
359399
}
360400

361401
topLevelPkg, _ = asmhelpers.PurlToPkg("pkg:guac/cdx/ABC")
@@ -387,7 +427,7 @@ var (
387427
HasSBOM: &model.HasSBOMInputSpec{
388428
Uri: "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
389429
Algorithm: "sha256",
390-
Digest: "a9e5e5fcc0939b4e9ddf74a5863ff577bef9bbf8086d99a4dafb8154c451b56f",
430+
Digest: "32981b0c4f87df9243c0e9b8a9600f2e19aae0c0cb76122edfe4a54ef59b9d48",
391431
KnownSince: parseRfc3339("2024-01-15T10:30:00Z"),
392432
},
393433
},
@@ -400,22 +440,25 @@ var (
400440
HasSBOM: &model.HasSBOMInputSpec{
401441
Uri: "urn:uuid:4e671687-395b-41f5-a30f-a58921a69b80",
402442
Algorithm: "sha256",
403-
Digest: "738690dd4acaf82b417072354ee631a20a50453278053b558770c6f65906f11d",
443+
Digest: "0731373583749ae046d0992e9b417d4b2960f75d7a979c72fd0b7a258566d520",
404444
KnownSince: parseRfc3339("2024-01-15T10:30:00Z"),
405445
},
406446
},
407447
}
408448
// Predicates for resolved_with_pedigree test
409-
// The affects ref is "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79/1#test-component"
410-
// The parser splits on "#" and uses "test-component" as pkdIdentifier
411-
// Then creates PURL as pkg:guac/pkg/[email protected] using guacCDXPkgPurl
412449
resolvedWithPedigreePkg, _ = asmhelpers.PurlToPkg("pkg:guac/pkg/[email protected]")
450+
resolvedWithPedigreeNoDetailPkg, _ = asmhelpers.PurlToPkg("pkg:guac/pkg/[email protected]")
413451
CycloneDXResolvedWithPedigreeVexIngest = []assembler.VexIngest{
414452
{
415453
Pkg: resolvedWithPedigreePkg,
416454
Vulnerability: VulnSpecResolvedWithPedigree,
417455
VexData: VexDataResolvedWithPedigree,
418456
},
457+
{
458+
Pkg: resolvedWithPedigreeNoDetailPkg,
459+
Vulnerability: VulnSpecResolvedWithPedigreeNoDetail,
460+
VexData: VexDataResolvedWithPedigreeNoDetail,
461+
},
419462
}
420463
CycloneDXResolvedWithPedigreePredicates = assembler.IngestPredicates{
421464
HasSBOM: HasSBOMVexResolvedWithPedigree,
@@ -424,22 +467,24 @@ var (
424467
// Note: No CertifyVuln because status is Fixed (not Affected/UnderInvestigation)
425468
}
426469
// Predicates for false_positive test
427-
// The affects ref is "urn:uuid:4e671687-395b-41f5-a30f-a58921a69b80/1#test-component-2"
428-
// The parser splits on "#" and uses "test-component-2" as pkdIdentifier
429-
// Then creates PURL as pkg:guac/pkg/[email protected] using guacCDXPkgPurl
430470
falsePositivePkg, _ = asmhelpers.PurlToPkg("pkg:guac/pkg/[email protected]")
471+
falsePositiveNoDetailPkg, _ = asmhelpers.PurlToPkg("pkg:guac/pkg/[email protected]")
431472
CycloneDXFalsePositiveVexIngest = []assembler.VexIngest{
432473
{
433474
Pkg: falsePositivePkg,
434475
Vulnerability: VulnSpecFalsePositive,
435476
VexData: VexDataFalsePositive,
436477
},
478+
{
479+
Pkg: falsePositiveNoDetailPkg,
480+
Vulnerability: VulnSpecFalsePositiveNoDetail,
481+
VexData: VexDataFalsePositiveNoDetail,
482+
},
437483
}
438484
CycloneDXFalsePositivePredicates = assembler.IngestPredicates{
439485
HasSBOM: HasSBOMVexFalsePositive,
440486
VulnMetadata: CycloneDXFalsePositiveVulnMetadata,
441487
Vex: CycloneDXFalsePositiveVexIngest,
442-
// Note: No CertifyVuln because status is NotAffected (not Affected/UnderInvestigation)
443488
}
444489

445490
// DSSE/SLSA Testdata

pkg/ingestor/parser/cyclonedx/parser_cyclonedx.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,8 @@ func (c *cyclonedxParser) getVulnerabilities(ctx context.Context) error {
579579
vd.KnownSince = publishedTime
580580
vd.Statement = vulnerability.Description
581581

582+
// Extract StatusNotes from analysis detail field.
583+
// This applies to all analysis states including resolved_with_pedigree and false_positive.
582584
if vulnerability.Analysis.Detail != "" {
583585
vd.StatusNotes = vulnerability.Analysis.Detail
584586
} else if vulnerability.Analysis.Response != nil {
@@ -587,7 +589,14 @@ func (c *cyclonedxParser) getVulnerabilities(ctx context.Context) error {
587589
response = append(response, string(res))
588590
}
589591
vd.StatusNotes = strings.Join(response, ",")
590-
} else {
592+
} else if vulnerability.Analysis.State != cdx.IASResolved &&
593+
vulnerability.Analysis.State != cdx.IASExploitable &&
594+
vulnerability.Analysis.State != cdx.IASInTriage &&
595+
vulnerability.Analysis.State != cdx.IASNotAffected {
596+
// Only preserve the CDX state enum information if it's not one of the original 4 states, since those provide additional context beyond what's already captured in vd.Status
597+
// Original states: IASResolved, IASExploitable, IASInTriage, IASNotAffected
598+
vd.StatusNotes = fmt.Sprintf("CDX state: %s", string(vulnerability.Analysis.State))
599+
} else if vulnerability.Detail != "" {
591600
vd.StatusNotes = vulnerability.Detail
592601
}
593602
} else {

0 commit comments

Comments
 (0)