CVE Mapping
This example demonstrates how to map CPE names to Common Vulnerabilities and Exposures (CVE) for comprehensive vulnerability management and security assessment.
Overview
CVE mapping allows you to correlate software components identified by CPE names with known security vulnerabilities. This is essential for vulnerability assessment, patch management, and security compliance.
Complete Example
go
package main
import (
"fmt"
"log"
"sort"
"time"
"github.com/scagogogo/cpe"
)
func main() {
fmt.Println("=== CVE Mapping Examples ===")
// Example 1: Basic CPE to CVE Mapping
fmt.Println("\n1. Basic CPE to CVE Mapping:")
// Initialize CVE database
cveDB := cpe.NewCVEDatabase()
// Load sample CVE data (in real implementation, this would load from NVD)
err := loadSampleCVEData(cveDB)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Loaded %d CVE entries\n", cveDB.Count())
// Test CPEs for vulnerability lookup
testCPEs := []string{
"cpe:2.3:a:apache:log4j:2.14.1:*:*:*:*:*:*:*",
"cpe:2.3:a:apache:tomcat:8.5.0:*:*:*:*:*:*:*",
"cpe:2.3:a:oracle:java:8.0.291:*:*:*:*:*:*:*",
"cpe:2.3:o:microsoft:windows:10:*:*:*:*:*:*:*",
"cpe:2.3:a:nginx:nginx:1.18.0:*:*:*:*:*:*:*",
}
for _, cpeStr := range testCPEs {
fmt.Printf("\nCPE: %s\n", cpeStr)
cves := cveDB.FindCVEsForCPE(cpeStr)
if len(cves) == 0 {
fmt.Println(" ✅ No known vulnerabilities")
} else {
fmt.Printf(" ⚠️ Found %d vulnerabilities:\n", len(cves))
for i, cve := range cves[:min(3, len(cves))] { // Show first 3
fmt.Printf(" %d. %s (CVSS: %.1f)\n", i+1, cve.ID, cve.BaseScore)
fmt.Printf(" %s\n", truncateString(cve.Description, 60))
}
if len(cves) > 3 {
fmt.Printf(" ... and %d more\n", len(cves)-3)
}
}
}
// Example 2: Version Range Vulnerability Mapping
fmt.Println("\n2. Version Range Vulnerability Mapping:")
// Check vulnerabilities across version ranges
versionRanges := []struct {
product string
vendor string
versions []string
}{
{
product: "log4j",
vendor: "apache",
versions: []string{"2.0", "2.10.0", "2.14.1", "2.15.0", "2.16.0"},
},
{
product: "tomcat",
vendor: "apache",
versions: []string{"8.5.0", "8.5.50", "9.0.0", "9.0.45", "10.0.0"},
},
}
for _, vr := range versionRanges {
fmt.Printf("\n%s %s version vulnerability analysis:\n", vr.vendor, vr.product)
for _, version := range vr.versions {
cpeStr := fmt.Sprintf("cpe:2.3:a:%s:%s:%s:*:*:*:*:*:*:*", vr.vendor, vr.product, version)
cves := cveDB.FindCVEsForCPE(cpeStr)
status := "✅"
riskLevel := "Low"
if len(cves) > 0 {
maxScore := 0.0
for _, cve := range cves {
if cve.BaseScore > maxScore {
maxScore = cve.BaseScore
}
}
switch {
case maxScore >= 9.0:
status = "🔴"
riskLevel = "Critical"
case maxScore >= 7.0:
status = "🟠"
riskLevel = "High"
case maxScore >= 4.0:
status = "🟡"
riskLevel = "Medium"
default:
status = "🟢"
riskLevel = "Low"
}
}
fmt.Printf(" %s v%s: %d CVEs (%s risk)\n", status, version, len(cves), riskLevel)
}
}
// Example 3: System Inventory Vulnerability Assessment
fmt.Println("\n3. System Inventory Vulnerability Assessment:")
// Define a system inventory
systemInventory := []struct {
name string
cpes []string
}{
{
name: "Web Server",
cpes: []string{
"cpe:2.3:o:canonical:ubuntu:20.04:*:*:*:*:*:*:*",
"cpe:2.3:a:apache:http_server:2.4.41:*:*:*:*:*:*:*",
"cpe:2.3:a:apache:tomcat:8.5.0:*:*:*:*:*:*:*",
"cpe:2.3:a:oracle:java:8.0.291:*:*:*:*:*:*:*",
},
},
{
name: "Application Server",
cpes: []string{
"cpe:2.3:o:redhat:enterprise_linux:8:*:*:*:*:*:*:*",
"cpe:2.3:a:apache:tomcat:9.0.45:*:*:*:*:*:*:*",
"cpe:2.3:a:oracle:java:11.0.12:*:*:*:*:*:*:*",
"cpe:2.3:a:apache:log4j:2.14.1:*:*:*:*:*:*:*",
},
},
{
name: "Desktop Workstation",
cpes: []string{
"cpe:2.3:o:microsoft:windows:10:*:*:*:*:*:*:*",
"cpe:2.3:a:microsoft:office:2019:*:*:*:*:*:*:*",
"cpe:2.3:a:mozilla:firefox:95.0:*:*:*:*:*:*:*",
"cpe:2.3:a:adobe:reader:2021.001.20150:*:*:*:*:*:*:*",
},
},
}
fmt.Println("System vulnerability assessment:")
for _, system := range systemInventory {
fmt.Printf("\n%s:\n", system.name)
totalCVEs := 0
criticalCVEs := 0
highCVEs := 0
maxScore := 0.0
for _, cpeStr := range system.cpes {
cves := cveDB.FindCVEsForCPE(cpeStr)
totalCVEs += len(cves)
for _, cve := range cves {
if cve.BaseScore > maxScore {
maxScore = cve.BaseScore
}
if cve.BaseScore >= 9.0 {
criticalCVEs++
} else if cve.BaseScore >= 7.0 {
highCVEs++
}
}
}
riskLevel := calculateRiskLevel(maxScore)
fmt.Printf(" Components: %d\n", len(system.cpes))
fmt.Printf(" Total CVEs: %d\n", totalCVEs)
fmt.Printf(" Critical: %d, High: %d\n", criticalCVEs, highCVEs)
fmt.Printf(" Max CVSS: %.1f\n", maxScore)
fmt.Printf(" Risk Level: %s\n", riskLevel)
}
// Example 4: CVE Timeline Analysis
fmt.Println("\n4. CVE Timeline Analysis:")
targetCPE := "cpe:2.3:a:apache:log4j:2.14.1:*:*:*:*:*:*:*"
cves := cveDB.FindCVEsForCPE(targetCPE)
fmt.Printf("CVE timeline for %s:\n", targetCPE)
if len(cves) == 0 {
fmt.Println(" No CVEs found")
} else {
// Sort CVEs by publication date
sort.Slice(cves, func(i, j int) bool {
return cves[i].PublishedDate.Before(cves[j].PublishedDate)
})
for _, cve := range cves {
fmt.Printf(" %s: %s (CVSS: %.1f)\n",
cve.PublishedDate.Format("2006-01-02"), cve.ID, cve.BaseScore)
}
// Calculate vulnerability trend
if len(cves) > 1 {
firstCVE := cves[0].PublishedDate
lastCVE := cves[len(cves)-1].PublishedDate
timespan := lastCVE.Sub(firstCVE)
fmt.Printf("\nVulnerability trend:\n")
fmt.Printf(" First CVE: %s\n", firstCVE.Format("2006-01-02"))
fmt.Printf(" Latest CVE: %s\n", lastCVE.Format("2006-01-02"))
fmt.Printf(" Timespan: %.0f days\n", timespan.Hours()/24)
fmt.Printf(" Rate: %.2f CVEs/month\n", float64(len(cves))/(timespan.Hours()/24/30))
}
}
// Example 5: Patch Priority Analysis
fmt.Println("\n5. Patch Priority Analysis:")
// Analyze patch priorities for multiple systems
patchCandidates := []string{
"cpe:2.3:a:apache:log4j:2.14.1:*:*:*:*:*:*:*",
"cpe:2.3:a:apache:tomcat:8.5.0:*:*:*:*:*:*:*",
"cpe:2.3:a:oracle:java:8.0.291:*:*:*:*:*:*:*",
"cpe:2.3:a:microsoft:office:2019:*:*:*:*:*:*:*",
}
type patchPriority struct {
cpe string
cveCount int
maxScore float64
priority string
urgency string
}
var priorities []patchPriority
for _, cpeStr := range patchCandidates {
cves := cveDB.FindCVEsForCPE(cpeStr)
maxScore := 0.0
for _, cve := range cves {
if cve.BaseScore > maxScore {
maxScore = cve.BaseScore
}
}
priority := calculatePatchPriority(len(cves), maxScore)
urgency := calculateUrgency(maxScore, cves)
priorities = append(priorities, patchPriority{
cpe: cpeStr,
cveCount: len(cves),
maxScore: maxScore,
priority: priority,
urgency: urgency,
})
}
// Sort by priority (highest score first)
sort.Slice(priorities, func(i, j int) bool {
return priorities[i].maxScore > priorities[j].maxScore
})
fmt.Println("Patch priority ranking:")
for i, p := range priorities {
cpeObj, _ := cpe.ParseCpe23(p.cpe)
fmt.Printf(" %d. %s %s\n", i+1, cpeObj.Vendor, cpeObj.ProductName)
fmt.Printf(" CVEs: %d, Max CVSS: %.1f\n", p.cveCount, p.maxScore)
fmt.Printf(" Priority: %s, Urgency: %s\n", p.priority, p.urgency)
}
// Example 6: CVE Impact Analysis
fmt.Println("\n6. CVE Impact Analysis:")
// Analyze the impact of specific CVEs
impactAnalysis := []string{
"CVE-2021-44228", // Log4Shell
"CVE-2021-45046", // Log4j follow-up
"CVE-2017-5638", // Apache Struts
}
for _, cveID := range impactAnalysis {
fmt.Printf("\n%s Impact Analysis:\n", cveID)
cveInfo := cveDB.GetCVE(cveID)
if cveInfo == nil {
fmt.Println(" CVE not found in database")
continue
}
fmt.Printf(" CVSS Score: %.1f\n", cveInfo.BaseScore)
fmt.Printf(" Published: %s\n", cveInfo.PublishedDate.Format("2006-01-02"))
fmt.Printf(" Description: %s\n", cveInfo.Description)
// Find affected CPEs
affectedCPEs := cveDB.FindCPEsForCVE(cveID)
fmt.Printf(" Affected CPEs: %d\n", len(affectedCPEs))
if len(affectedCPEs) > 0 {
fmt.Println(" Sample affected products:")
for i, cpeStr := range affectedCPEs[:min(5, len(affectedCPEs))] {
cpeObj, _ := cpe.ParseCpe23(cpeStr)
fmt.Printf(" %d. %s %s %s\n", i+1, cpeObj.Vendor, cpeObj.ProductName, cpeObj.Version)
}
}
}
// Example 7: Export CVE Mapping Report
fmt.Println("\n7. Export CVE Mapping Report:")
// Generate comprehensive report
report := cpe.NewCVEMappingReport()
for _, system := range systemInventory {
systemReport := &cpe.SystemVulnerabilityReport{
SystemName: system.name,
Components: make([]*cpe.ComponentVulnerability, 0),
}
for _, cpeStr := range system.cpes {
cves := cveDB.FindCVEsForCPE(cpeStr)
component := &cpe.ComponentVulnerability{
CPE: cpeStr,
Vulnerabilities: cves,
}
systemReport.Components = append(systemReport.Components, component)
}
report.AddSystem(systemReport)
}
// Export to different formats
formats := []string{"json", "csv", "html", "pdf"}
for _, format := range formats {
filename := fmt.Sprintf("cve_mapping_report.%s", format)
err := report.ExportToFile(filename, format)
if err != nil {
log.Printf("Failed to export %s: %v", format, err)
} else {
fmt.Printf("✅ CVE mapping report exported to %s\n", filename)
}
}
}
// Helper functions
func loadSampleCVEData(db *cpe.CVEDatabase) error {
sampleCVEs := []*cpe.CVEEntry{
{
ID: "CVE-2021-44228",
Description: "Apache Log4j2 JNDI features do not protect against attacker controlled LDAP and other JNDI related endpoints.",
BaseScore: 10.0,
PublishedDate: time.Date(2021, 12, 10, 0, 0, 0, 0, time.UTC),
AffectedCPEs: []string{
"cpe:2.3:a:apache:log4j:2.0:*:*:*:*:*:*:*",
"cpe:2.3:a:apache:log4j:2.14.1:*:*:*:*:*:*:*",
},
},
{
ID: "CVE-2021-25122",
Description: "When responding to new h2c connection requests, Apache Tomcat could duplicate request headers and a request header could be used to poison the cache.",
BaseScore: 7.5,
PublishedDate: time.Date(2021, 3, 1, 0, 0, 0, 0, time.UTC),
AffectedCPEs: []string{
"cpe:2.3:a:apache:tomcat:8.5.0:*:*:*:*:*:*:*",
"cpe:2.3:a:apache:tomcat:9.0.0:*:*:*:*:*:*:*",
},
},
}
for _, cve := range sampleCVEs {
db.AddCVE(cve)
}
return nil
}
func calculateRiskLevel(score float64) string {
switch {
case score >= 9.0:
return "🔴 Critical"
case score >= 7.0:
return "🟠 High"
case score >= 4.0:
return "🟡 Medium"
case score > 0:
return "🟢 Low"
default:
return "✅ None"
}
}
func calculatePatchPriority(cveCount int, maxScore float64) string {
if maxScore >= 9.0 || cveCount >= 5 {
return "🔴 Critical"
} else if maxScore >= 7.0 || cveCount >= 3 {
return "🟠 High"
} else if maxScore >= 4.0 || cveCount >= 1 {
return "🟡 Medium"
}
return "🟢 Low"
}
func calculateUrgency(maxScore float64, cves []*cpe.CVEEntry) string {
// Check for recent CVEs (within last 30 days)
recentCVEs := 0
thirtyDaysAgo := time.Now().AddDate(0, 0, -30)
for _, cve := range cves {
if cve.PublishedDate.After(thirtyDaysAgo) {
recentCVEs++
}
}
if maxScore >= 9.0 && recentCVEs > 0 {
return "🚨 Immediate"
} else if maxScore >= 7.0 {
return "⏰ Urgent"
} else if recentCVEs > 0 {
return "📅 Soon"
}
return "📋 Scheduled"
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func truncateString(s string, maxLen int) string {
if len(s) <= maxLen {
return s
}
return s[:maxLen-3] + "..."
}
Key Concepts
1. CVE Mapping Process
- CPE Identification: Identify software components using CPE names
- Vulnerability Lookup: Find CVEs associated with each CPE
- Impact Assessment: Evaluate severity and risk levels
- Prioritization: Rank vulnerabilities for remediation
2. Risk Assessment
- CVSS Scoring: Use Common Vulnerability Scoring System
- Temporal Factors: Consider age and exploit availability
- Environmental Context: Factor in system criticality
- Business Impact: Assess potential business consequences
3. Reporting and Analysis
- Vulnerability Reports: Generate comprehensive security reports
- Trend Analysis: Track vulnerability patterns over time
- Patch Management: Prioritize and schedule updates
- Compliance: Meet security compliance requirements
Best Practices
- Regular Updates: Keep CVE database current
- Automated Scanning: Implement automated vulnerability scanning
- Risk-Based Prioritization: Focus on highest-risk vulnerabilities first
- Documentation: Maintain detailed vulnerability records
- Verification: Validate CVE mappings for accuracy
Integration Patterns
- CI/CD Integration: Include vulnerability scanning in build pipelines
- Asset Management: Link with configuration management databases
- Incident Response: Integrate with security incident workflows
- Compliance Reporting: Generate regulatory compliance reports
Performance Considerations
- Database Optimization: Index CVE data for fast lookups
- Caching: Cache frequently accessed vulnerability data
- Batch Processing: Process multiple CPEs efficiently
- Incremental Updates: Update only changed vulnerability data
Next Steps
- Learn about Storage for persisting vulnerability data
- Explore Advanced Matching for sophisticated detection
- Check out NVD Integration for official vulnerability feeds