VulnerabilityMerger.kt
package com.depanalyzer.repository
import com.depanalyzer.report.Vulnerability
import com.depanalyzer.report.VulnerabilitySeverity
import com.depanalyzer.report.VulnerabilitySource
object VulnerabilityMerger {
fun mergeVulnerabilities(
ossIndexVulns: Map<String, List<Vulnerability>>,
nvdVulns: Map<String, List<Vulnerability>>
): Map<String, List<Vulnerability>> {
val mergedByCveId = mutableMapOf<String, Vulnerability>()
ossIndexVulns.values.flatten().forEach { vuln ->
mergedByCveId[vuln.cveId] = vuln
}
nvdVulns.values.flatten().forEach { nvdVuln ->
val cveId = nvdVuln.cveId
if (cveId in mergedByCveId) {
val existing = mergedByCveId[cveId]!!
val mergedScore = nvdVuln.cvssScore ?: existing.cvssScore
val mergedSeverity = if (mergedScore != null) {
VulnerabilitySeverity.fromCvssScore(mergedScore)
} else {
existing.severity
}
mergedByCveId[cveId] = existing.copy(
cvssScore = mergedScore,
severity = mergedSeverity,
source = VulnerabilitySource.BOTH,
referenceUrl = nvdVuln.referenceUrl ?: existing.referenceUrl,
description = nvdVuln.description ?: existing.description
)
} else {
mergedByCveId[cveId] = nvdVuln.copy(source = VulnerabilitySource.NVD)
}
}
val result = mutableMapOf<String, List<Vulnerability>>()
ossIndexVulns.keys.forEach { key ->
result[key] = emptyList()
}
nvdVulns.keys.forEach { key ->
result[key] = emptyList()
}
mergedByCveId.values
.groupBy { "${it.affectedDependency.groupId}:${it.affectedDependency.artifactId}:${it.affectedDependency.version}" }
.forEach { (key, vulns) ->
result[key] = vulns
}
return result
}
}