@@ -21,8 +21,8 @@ const (
21
21
extension = ".json"
22
22
)
23
23
24
- // Metrics holds the collected data about the conversion process for a single CVE.
25
- var Metrics struct {
24
+ // ConversionMetrics holds the collected data about the conversion process for a single CVE.
25
+ type ConversionMetrics struct {
26
26
CNA string `json:"cna"` // The CNA that assigned the CVE.
27
27
Outcome string `json:"outcome"` // The final outcome of the conversion (e.g., "Successful", "Failed").
28
28
Repos []string `json:"repos"` // A list of repositories extracted from the CVE's references.
@@ -41,21 +41,21 @@ var RefTagDenyList = []string{
41
41
}
42
42
43
43
// extractConversionMetrics examines a CVE and its generated OSV references to populate
44
- // the global Metrics struct with heuristics about the conversion process.
44
+ // the ConversionMetrics struct with heuristics about the conversion process.
45
45
// It captures the assigning CNA and counts the occurrences of each reference type.
46
- func extractConversionMetrics (cve cves.CVE5 , refs []osvschema.Reference ) {
46
+ func extractConversionMetrics (cve cves.CVE5 , refs []osvschema.Reference , metrics * ConversionMetrics ) {
47
47
// Capture the CNA for heuristic analysis.
48
- Metrics .CNA = cve .Metadata .AssignerShortName
48
+ metrics .CNA = cve .Metadata .AssignerShortName
49
49
// TODO(jesslowe): more CNA based analysis
50
50
51
51
// Count number of references of each type
52
52
refTypeCounts := make (map [osvschema.ReferenceType ]int )
53
53
for _ , ref := range refs {
54
54
refTypeCounts [ref .Type ]++
55
55
}
56
- Metrics .RefTypesCount = refTypeCounts
56
+ metrics .RefTypesCount = refTypeCounts
57
57
for refType , count := range refTypeCounts {
58
- Metrics .Notes = append (Metrics .Notes , fmt .Sprintf ("[%s]: Reference Type %s: %d" , cve .Metadata .CVEID , refType , count ))
58
+ metrics .Notes = append (metrics .Notes , fmt .Sprintf ("[%s]: Reference Type %s: %d" , cve .Metadata .CVEID , refType , count ))
59
59
}
60
60
61
61
// TODO(jesslowe): Add more analysis based on ADP containers, CVSS, KEV, CWE, etc.
@@ -64,7 +64,7 @@ func extractConversionMetrics(cve cves.CVE5, refs []osvschema.Reference) {
64
64
// FromCVE5 creates a `vulns.Vulnerability` object from a `cves.CVE5` object.
65
65
// It populates the main fields of the OSV record, including ID, summary, details,
66
66
// references, timestamps, severity, and version information.
67
- func FromCVE5 (cve cves.CVE5 , refs []cves.Reference ) (* vulns.Vulnerability , []string ) {
67
+ func FromCVE5 (cve cves.CVE5 , refs []cves.Reference , metrics * ConversionMetrics ) (* vulns.Vulnerability , []string ) {
68
68
aliases , related := vulns .ExtractReferencedVulns (cve .Metadata .CVEID , cve .Metadata .CVEID , refs )
69
69
var notes []string
70
70
v := vulns.Vulnerability {
@@ -95,7 +95,7 @@ func FromCVE5(cve cves.CVE5, refs []cves.Reference) (*vulns.Vulnerability, []str
95
95
// Add affected version information.
96
96
versionSources , versNotes := AddVersionInfo (cve , & v )
97
97
notes = append (notes , versNotes ... )
98
- Metrics .VersionSources = versionSources
98
+ metrics .VersionSources = versionSources
99
99
// TODO(jesslowe@): Add CWEs.
100
100
101
101
// Combine severity metrics from both CNA and ADP containers.
@@ -147,9 +147,9 @@ func writeOSVToFile(id cves.CVEID, cnaAssigner string, vulnDir string, v *vulns.
147
147
// writeMetricToFile saves the collected conversion metrics to a JSON file.
148
148
// This file provides data for analyzing the success and characteristics of the
149
149
// conversion process for a given CVE.
150
- func writeMetricToFile (id cves.CVEID , vulnDir string ) error {
150
+ func writeMetricToFile (id cves.CVEID , vulnDir string , metrics * ConversionMetrics ) error {
151
151
metricsFile := filepath .Join (vulnDir , string (id )+ ".metrics.json" )
152
- marshalledMetrics , err := json .MarshalIndent (Metrics , "" , " " )
152
+ marshalledMetrics , err := json .MarshalIndent (metrics , "" , " " )
153
153
if err != nil {
154
154
logger .Warn ("Failed to marshal metrics for " + string (id ), slog .String ("cve" , string (id )), slog .Any ("err" , err ))
155
155
return err
@@ -168,18 +168,18 @@ func ConvertAndExportCVEToOSV(cve cves.CVE5, directory string) error {
168
168
cveID := cve .Metadata .CVEID
169
169
cnaAssigner := cve .Metadata .AssignerShortName
170
170
references := identifyPossibleURLs (cve )
171
-
171
+ metrics := & ConversionMetrics {}
172
172
// Create a base OSV record from the CVE.
173
- v , notes := FromCVE5 (cve , references )
174
- Metrics .Notes = append (Metrics .Notes , notes ... )
173
+ v , notes := FromCVE5 (cve , references , metrics )
174
+ metrics .Notes = append (metrics .Notes , notes ... )
175
175
176
176
// Collect metrics about the conversion.
177
- extractConversionMetrics (cve , v .References )
177
+ extractConversionMetrics (cve , v .References , metrics )
178
178
179
179
// Try to extract repository URLs from references.
180
180
repos , repoNotes := cves .ReposFromReferencesCVEList (string (cveID ), references , RefTagDenyList )
181
- Metrics .Notes = append (Metrics .Notes , repoNotes ... )
182
- Metrics .Repos = repos
181
+ metrics .Notes = append (metrics .Notes , repoNotes ... )
182
+ metrics .Repos = repos
183
183
184
184
vulnDir := filepath .Join (directory , cnaAssigner )
185
185
@@ -189,7 +189,7 @@ func ConvertAndExportCVEToOSV(cve cves.CVE5, directory string) error {
189
189
}
190
190
191
191
// Save the conversion metrics to a file.
192
- if err := writeMetricToFile (cveID , vulnDir ); err != nil {
192
+ if err := writeMetricToFile (cveID , vulnDir , metrics ); err != nil {
193
193
return err
194
194
}
195
195
0 commit comments