1package models 2 3import ( 4 "time" 5 6 "github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability" 7) 8 9// CveContents has CveContent 10type CveContents map[CveContentType]CveContent 11 12// NewCveContents create CveContents 13func NewCveContents(conts ...CveContent) CveContents { 14 m := CveContents{} 15 for _, cont := range conts { 16 m[cont.Type] = cont 17 } 18 return m 19} 20 21// CveContentStr has CveContentType and Value 22type CveContentStr struct { 23 Type CveContentType 24 Value string 25} 26 27// Except returns CveContents except given keys for enumeration 28func (v CveContents) Except(exceptCtypes ...CveContentType) (values CveContents) { 29 values = CveContents{} 30 for ctype, content := range v { 31 found := false 32 for _, exceptCtype := range exceptCtypes { 33 if ctype == exceptCtype { 34 found = true 35 break 36 } 37 } 38 if !found { 39 values[ctype] = content 40 } 41 } 42 return 43} 44 45// SourceLinks returns link of source 46func (v CveContents) SourceLinks(lang, myFamily, cveID string) (values []CveContentStr) { 47 if lang == "ja" { 48 if cont, found := v[Jvn]; found && 0 < len(cont.SourceLink) { 49 values = append(values, CveContentStr{Jvn, cont.SourceLink}) 50 } 51 } 52 53 order := CveContentTypes{Nvd, NvdXML, NewCveContentType(myFamily)} 54 for _, ctype := range order { 55 if cont, found := v[ctype]; found { 56 if cont.SourceLink == "" { 57 continue 58 } 59 values = append(values, CveContentStr{ctype, cont.SourceLink}) 60 } 61 } 62 63 if len(values) == 0 { 64 return []CveContentStr{{ 65 Type: Nvd, 66 Value: "https://nvd.nist.gov/vuln/detail/" + cveID, 67 }} 68 } 69 return values 70} 71 72/* 73// Severities returns Severities 74func (v CveContents) Severities(myFamily string) (values []CveContentStr) { 75 order := CveContentTypes{NVD, NewCveContentType(myFamily)} 76 order = append(order, AllCveContetTypes.Except(append(order)...)...) 77 78 for _, ctype := range order { 79 if cont, found := v[ctype]; found && 0 < len(cont.Severity) { 80 values = append(values, CveContentStr{ 81 Type: ctype, 82 Value: cont.Severity, 83 }) 84 } 85 } 86 return 87} 88*/ 89 90// CveContentCpes has CveContentType and Value 91type CveContentCpes struct { 92 Type CveContentType 93 Value []Cpe 94} 95 96// Cpes returns affected CPEs of this Vulnerability 97func (v CveContents) Cpes(myFamily string) (values []CveContentCpes) { 98 order := CveContentTypes{NewCveContentType(myFamily)} 99 order = append(order, AllCveContetTypes.Except(order...)...) 100 101 for _, ctype := range order { 102 if cont, found := v[ctype]; found && 0 < len(cont.Cpes) { 103 values = append(values, CveContentCpes{ 104 Type: ctype, 105 Value: cont.Cpes, 106 }) 107 } 108 } 109 return 110} 111 112// CveContentRefs has CveContentType and Cpes 113type CveContentRefs struct { 114 Type CveContentType 115 Value []Reference 116} 117 118// References returns References 119func (v CveContents) References(myFamily string) (values []CveContentRefs) { 120 order := CveContentTypes{NewCveContentType(myFamily)} 121 order = append(order, AllCveContetTypes.Except(order...)...) 122 123 for _, ctype := range order { 124 if cont, found := v[ctype]; found && 0 < len(cont.References) { 125 values = append(values, CveContentRefs{ 126 Type: ctype, 127 Value: cont.References, 128 }) 129 } 130 } 131 132 return 133} 134 135// CweIDs returns related CweIDs of the vulnerability 136func (v CveContents) CweIDs(myFamily string) (values []CveContentStr) { 137 order := CveContentTypes{NewCveContentType(myFamily)} 138 order = append(order, AllCveContetTypes.Except(order...)...) 139 for _, ctype := range order { 140 if cont, found := v[ctype]; found && 0 < len(cont.CweIDs) { 141 for _, cweID := range cont.CweIDs { 142 for _, val := range values { 143 if val.Value == cweID { 144 continue 145 } 146 } 147 values = append(values, CveContentStr{ 148 Type: ctype, 149 Value: cweID, 150 }) 151 } 152 } 153 } 154 return 155} 156 157// UniqCweIDs returns Uniq CweIDs 158func (v CveContents) UniqCweIDs(myFamily string) (values []CveContentStr) { 159 uniq := map[string]CveContentStr{} 160 for _, cwes := range v.CweIDs(myFamily) { 161 uniq[cwes.Value] = cwes 162 } 163 for _, cwe := range uniq { 164 values = append(values, cwe) 165 } 166 return values 167} 168 169// CveContent has abstraction of various vulnerability information 170type CveContent struct { 171 Type CveContentType `json:"type"` 172 CveID string `json:"cveID"` 173 Title string `json:"title"` 174 Summary string `json:"summary"` 175 Cvss2Score float64 `json:"cvss2Score"` 176 Cvss2Vector string `json:"cvss2Vector"` 177 Cvss2Severity string `json:"cvss2Severity"` 178 Cvss3Score float64 `json:"cvss3Score"` 179 Cvss3Vector string `json:"cvss3Vector"` 180 Cvss3Severity string `json:"cvss3Severity"` 181 SourceLink string `json:"sourceLink"` 182 Cpes []Cpe `json:"cpes,omitempty"` 183 References References `json:"references,omitempty"` 184 CweIDs []string `json:"cweIDs,omitempty"` 185 Published time.Time `json:"published"` 186 LastModified time.Time `json:"lastModified"` 187 Mitigation string `json:"mitigation"` // RedHat API 188 Optional map[string]string `json:"optional,omitempty"` 189} 190 191// Empty checks the content is empty 192func (c CveContent) Empty() bool { 193 return c.Summary == "" 194} 195 196// CveContentType is a source of CVE information 197type CveContentType string 198 199// NewCveContentType create CveContentType 200func NewCveContentType(name string) CveContentType { 201 switch name { 202 case "nvdxml": 203 return NvdXML 204 case "nvd": 205 return Nvd 206 case "jvn": 207 return Jvn 208 case "redhat", "centos": 209 return RedHat 210 case "oracle": 211 return Oracle 212 case "ubuntu": 213 return Ubuntu 214 case "debian", vulnerability.DebianOVAL: 215 return Debian 216 case "redhat_api": 217 return RedHatAPI 218 case "debian_security_tracker": 219 return DebianSecurityTracker 220 case "microsoft": 221 return Microsoft 222 case "wordpress": 223 return WPVulnDB 224 case "amazon": 225 return Amazon 226 case "trivy": 227 return Trivy 228 // case vulnerability.NodejsSecurityWg: 229 // return NodeSec 230 // case vulnerability.PythonSafetyDB: 231 // return PythonSec 232 // case vulnerability.RustSec: 233 // return RustSec 234 // case vulnerability.PhpSecurityAdvisories: 235 // return PhpSec 236 // case vulnerability.RubySec: 237 // return RubySec 238 default: 239 return Unknown 240 } 241} 242 243const ( 244 // NvdXML is NvdXML 245 NvdXML CveContentType = "nvdxml" 246 247 // Nvd is Nvd 248 Nvd CveContentType = "nvd" 249 250 // Jvn is Jvn 251 Jvn CveContentType = "jvn" 252 253 // RedHat is RedHat 254 RedHat CveContentType = "redhat" 255 256 // RedHatAPI is RedHat 257 RedHatAPI CveContentType = "redhat_api" 258 259 // DebianSecurityTracker is Debian Security tracker 260 DebianSecurityTracker CveContentType = "debian_security_tracker" 261 262 // Debian is Debian 263 Debian CveContentType = "debian" 264 265 // Ubuntu is Ubuntu 266 Ubuntu CveContentType = "ubuntu" 267 268 // Oracle is Oracle Linux 269 Oracle CveContentType = "oracle" 270 271 // Amazon is Amazon Linux 272 Amazon CveContentType = "amazon" 273 274 // SUSE is SUSE Linux 275 SUSE CveContentType = "suse" 276 277 // Microsoft is Microsoft 278 Microsoft CveContentType = "microsoft" 279 280 // WPVulnDB is WordPress 281 WPVulnDB CveContentType = "wpvulndb" 282 283 // Trivy is Trivy 284 Trivy CveContentType = "trivy" 285 286 // NodeSec : for JS 287 // NodeSec CveContentType = "node" 288 289 // // PythonSec : for PHP 290 // PythonSec CveContentType = "python" 291 292 // // PhpSec : for PHP 293 // PhpSec CveContentType = "php" 294 295 // // RubySec : for Ruby 296 // RubySec CveContentType = "ruby" 297 298 // // RustSec : for Rust 299 // RustSec CveContentType = "rust" 300 301 // Unknown is Unknown 302 Unknown CveContentType = "unknown" 303) 304 305// CveContentTypes has slide of CveContentType 306type CveContentTypes []CveContentType 307 308// AllCveContetTypes has all of CveContentTypes 309var AllCveContetTypes = CveContentTypes{ 310 Nvd, 311 NvdXML, 312 Jvn, 313 RedHat, 314 RedHatAPI, 315 Debian, 316 Ubuntu, 317 Amazon, 318 SUSE, 319 DebianSecurityTracker, 320 WPVulnDB, 321 Trivy, 322 // NodeSec, 323 // PythonSec, 324 // PhpSec, 325 // RubySec, 326 // RustSec, 327} 328 329// Except returns CveContentTypes except for given args 330func (c CveContentTypes) Except(excepts ...CveContentType) (excepted CveContentTypes) { 331 for _, ctype := range c { 332 found := false 333 for _, except := range excepts { 334 if ctype == except { 335 found = true 336 break 337 } 338 } 339 if !found { 340 excepted = append(excepted, ctype) 341 } 342 } 343 return 344} 345 346// Cpe is Common Platform Enumeration 347type Cpe struct { 348 URI string `json:"uri"` 349 FormattedString string `json:"formattedString"` 350} 351 352// References is a slice of Reference 353type References []Reference 354 355// Reference has a related link of the CVE 356type Reference struct { 357 Source string `json:"source"` 358 Link string `json:"link"` 359 RefID string `json:"refID"` 360} 361