Compare commits
	
		
			5 Commits
		
	
	
		
			v0.26.0
			...
			MaineK00n/
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					492cae6dff | ||
| 
						 | 
					d8173cdd42 | ||
| 
						 | 
					9beb5fc9f0 | ||
| 
						 | 
					0b4dfa0b31 | ||
| 
						 | 
					0a47a26553 | 
@@ -1949,7 +1949,7 @@ var oneCVEtoNVulnerabilityTrivy = []byte(`
 | 
			
		||||
			],
 | 
			
		||||
			"VendorSeverity": {
 | 
			
		||||
			  "ghsa": 2,
 | 
			
		||||
			  "nvd": 2,
 | 
			
		||||
			  "nvd": 3,
 | 
			
		||||
			  "ruby-advisory-db": 2
 | 
			
		||||
			},
 | 
			
		||||
			"CVSS": {
 | 
			
		||||
@@ -1958,6 +1958,8 @@ var oneCVEtoNVulnerabilityTrivy = []byte(`
 | 
			
		||||
				"V3Score": 5.9
 | 
			
		||||
			  },
 | 
			
		||||
			  "nvd": {
 | 
			
		||||
			  	"V40Vector": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N",
 | 
			
		||||
				"V40Score": 8.9,
 | 
			
		||||
				"V3Vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N",
 | 
			
		||||
				"V3Score": 5.9
 | 
			
		||||
			  }
 | 
			
		||||
@@ -2027,7 +2029,7 @@ var oneCVEtoNVulnerabilityTrivy = []byte(`
 | 
			
		||||
			],
 | 
			
		||||
			"VendorSeverity": {
 | 
			
		||||
			  "ghsa": 2,
 | 
			
		||||
			  "nvd": 2,
 | 
			
		||||
			  "nvd": 3,
 | 
			
		||||
			  "ruby-advisory-db": 2
 | 
			
		||||
			},
 | 
			
		||||
			"CVSS": {
 | 
			
		||||
@@ -2036,6 +2038,8 @@ var oneCVEtoNVulnerabilityTrivy = []byte(`
 | 
			
		||||
				"V3Score": 5.9
 | 
			
		||||
			  },
 | 
			
		||||
			  "nvd": {
 | 
			
		||||
			  	"V40Vector": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N",
 | 
			
		||||
				"V40Score": 8.9,
 | 
			
		||||
				"V3Vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N",
 | 
			
		||||
				"V3Score": 5.9
 | 
			
		||||
			  }
 | 
			
		||||
@@ -2545,7 +2549,7 @@ var oneCVEtoNVulnerabilitySR = &models.ScanResult{
 | 
			
		||||
						CveID:         "CVE-2023-26154",
 | 
			
		||||
						Title:         "pubnub Insufficient Entropy vulnerability",
 | 
			
		||||
						Summary:       "Versions of the package pubnub before 7.4.0; all versions of the package com.pubnub:pubnub; versions of the package pubnub before 6.19.0; all versions of the package github.com/pubnub/go; versions of the package github.com/pubnub/go/v7 before 7.2.0; versions of the package pubnub before 7.3.0; versions of the package pubnub/pubnub before 6.1.0; versions of the package pubnub before 5.3.0; versions of the package pubnub before 0.4.0; versions of the package pubnub/c-core before 4.5.0; versions of the package com.pubnub:pubnub-kotlin before 7.7.0; versions of the package pubnub/swift before 6.2.0; versions of the package pubnub before 5.2.0; versions of the package pubnub before 4.3.0 are vulnerable to Insufficient Entropy via the getKey function, due to inefficient implementation of the AES-256-CBC cryptographic algorithm. The provided encrypt function is less secure when hex encoding and trimming are applied, leaving half of the bits in the key always the same for every encoded message or file.\r\r**Note:**\r\rIn order to exploit this vulnerability, the attacker needs to invest resources in preparing the attack and brute-force the encryption.",
 | 
			
		||||
						Cvss3Severity: "MEDIUM",
 | 
			
		||||
						Cvss3Severity: "HIGH",
 | 
			
		||||
						References: models.References{
 | 
			
		||||
							{
 | 
			
		||||
								Source: "trivy",
 | 
			
		||||
@@ -2648,12 +2652,14 @@ var oneCVEtoNVulnerabilitySR = &models.ScanResult{
 | 
			
		||||
						LastModified: time.Date(2023, time.December, 11, 17, 48, 3, 653, time.UTC),
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						Type:        "trivy:nvd",
 | 
			
		||||
						CveID:       "CVE-2023-26154",
 | 
			
		||||
						Title:       "pubnub Insufficient Entropy vulnerability",
 | 
			
		||||
						Summary:     "Versions of the package pubnub before 7.4.0; all versions of the package com.pubnub:pubnub; versions of the package pubnub before 6.19.0; all versions of the package github.com/pubnub/go; versions of the package github.com/pubnub/go/v7 before 7.2.0; versions of the package pubnub before 7.3.0; versions of the package pubnub/pubnub before 6.1.0; versions of the package pubnub before 5.3.0; versions of the package pubnub before 0.4.0; versions of the package pubnub/c-core before 4.5.0; versions of the package com.pubnub:pubnub-kotlin before 7.7.0; versions of the package pubnub/swift before 6.2.0; versions of the package pubnub before 5.2.0; versions of the package pubnub before 4.3.0 are vulnerable to Insufficient Entropy via the getKey function, due to inefficient implementation of the AES-256-CBC cryptographic algorithm. The provided encrypt function is less secure when hex encoding and trimming are applied, leaving half of the bits in the key always the same for every encoded message or file.\r\r**Note:**\r\rIn order to exploit this vulnerability, the attacker needs to invest resources in preparing the attack and brute-force the encryption.",
 | 
			
		||||
						Cvss3Score:  5.9,
 | 
			
		||||
						Cvss3Vector: "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N",
 | 
			
		||||
						Type:         "trivy:nvd",
 | 
			
		||||
						CveID:        "CVE-2023-26154",
 | 
			
		||||
						Title:        "pubnub Insufficient Entropy vulnerability",
 | 
			
		||||
						Summary:      "Versions of the package pubnub before 7.4.0; all versions of the package com.pubnub:pubnub; versions of the package pubnub before 6.19.0; all versions of the package github.com/pubnub/go; versions of the package github.com/pubnub/go/v7 before 7.2.0; versions of the package pubnub before 7.3.0; versions of the package pubnub/pubnub before 6.1.0; versions of the package pubnub before 5.3.0; versions of the package pubnub before 0.4.0; versions of the package pubnub/c-core before 4.5.0; versions of the package com.pubnub:pubnub-kotlin before 7.7.0; versions of the package pubnub/swift before 6.2.0; versions of the package pubnub before 5.2.0; versions of the package pubnub before 4.3.0 are vulnerable to Insufficient Entropy via the getKey function, due to inefficient implementation of the AES-256-CBC cryptographic algorithm. The provided encrypt function is less secure when hex encoding and trimming are applied, leaving half of the bits in the key always the same for every encoded message or file.\r\r**Note:**\r\rIn order to exploit this vulnerability, the attacker needs to invest resources in preparing the attack and brute-force the encryption.",
 | 
			
		||||
						Cvss3Score:   5.9,
 | 
			
		||||
						Cvss3Vector:  "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N",
 | 
			
		||||
						Cvss40Score:  8.9,
 | 
			
		||||
						Cvss40Vector: "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N",
 | 
			
		||||
						References: models.References{
 | 
			
		||||
							{
 | 
			
		||||
								Source: "trivy",
 | 
			
		||||
 
 | 
			
		||||
@@ -82,8 +82,7 @@ func Convert(results types.Results) (result *models.ScanResult, err error) {
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				slices.SortFunc(severities, trivydbTypes.CompareSeverityString)
 | 
			
		||||
				slices.Reverse(severities)
 | 
			
		||||
				slices.SortFunc(severities, func(a, b string) int { return -trivydbTypes.CompareSeverityString(a, b) })
 | 
			
		||||
 | 
			
		||||
				vulnInfo.CveContents[models.CveContentType(fmt.Sprintf("%s:%s", models.Trivy, source))] = []models.CveContent{{
 | 
			
		||||
					Type:          models.CveContentType(fmt.Sprintf("%s:%s", models.Trivy, source)),
 | 
			
		||||
@@ -100,7 +99,7 @@ func Convert(results types.Results) (result *models.ScanResult, err error) {
 | 
			
		||||
			for source, cvss := range vuln.CVSS {
 | 
			
		||||
				if cs, ok := vulnInfo.CveContents[models.CveContentType(fmt.Sprintf("%s:%s", models.Trivy, source))]; ok &&
 | 
			
		||||
					slices.ContainsFunc(cs, func(c models.CveContent) bool {
 | 
			
		||||
						return c.Cvss2Score == cvss.V2Score && c.Cvss2Vector == cvss.V2Vector && c.Cvss3Score == cvss.V3Score && c.Cvss3Vector == cvss.V3Vector
 | 
			
		||||
						return c.Cvss2Score == cvss.V2Score && c.Cvss2Vector == cvss.V2Vector && c.Cvss3Score == cvss.V3Score && c.Cvss3Vector == cvss.V3Vector && c.Cvss40Score == cvss.V40Score && c.Cvss40Vector == cvss.V40Vector
 | 
			
		||||
					}) {
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
@@ -114,6 +113,8 @@ func Convert(results types.Results) (result *models.ScanResult, err error) {
 | 
			
		||||
					Cvss2Vector:  cvss.V2Vector,
 | 
			
		||||
					Cvss3Score:   cvss.V3Score,
 | 
			
		||||
					Cvss3Vector:  cvss.V3Vector,
 | 
			
		||||
					Cvss40Score:  cvss.V40Score,
 | 
			
		||||
					Cvss40Vector: cvss.V40Vector,
 | 
			
		||||
					Published:    published,
 | 
			
		||||
					LastModified: lastModified,
 | 
			
		||||
					References:   references,
 | 
			
		||||
 
 | 
			
		||||
@@ -204,7 +204,7 @@ func Detect(rs []models.ScanResult, dir string) ([]models.ScanResult, error) {
 | 
			
		||||
			return nil, xerrors.Errorf("Failed to fill with gost: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := FillCvesWithNvdJvnFortinet(&r, config.Conf.CveDict, config.Conf.LogOpts); err != nil {
 | 
			
		||||
		if err := FillCvesWithGoCVEDictionary(&r, config.Conf.CveDict, config.Conf.LogOpts); err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("Failed to fill with CVE: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -435,8 +435,8 @@ func DetectWordPressCves(r *models.ScanResult, wpCnf config.WpScanConf) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FillCvesWithNvdJvnFortinet fills CVE detail with NVD, JVN, Fortinet
 | 
			
		||||
func FillCvesWithNvdJvnFortinet(r *models.ScanResult, cnf config.GoCveDictConf, logOpts logging.LogOpts) (err error) {
 | 
			
		||||
// FillCvesWithGoCVEDictionary fills CVE detail with NVD, JVN, Fortinet, MITRE
 | 
			
		||||
func FillCvesWithGoCVEDictionary(r *models.ScanResult, cnf config.GoCveDictConf, logOpts logging.LogOpts) (err error) {
 | 
			
		||||
	cveIDs := []string{}
 | 
			
		||||
	for _, v := range r.ScannedCves {
 | 
			
		||||
		cveIDs = append(cveIDs, v.CveID)
 | 
			
		||||
@@ -461,6 +461,7 @@ func FillCvesWithNvdJvnFortinet(r *models.ScanResult, cnf config.GoCveDictConf,
 | 
			
		||||
		nvds, exploits, mitigations := models.ConvertNvdToModel(d.CveID, d.Nvds)
 | 
			
		||||
		jvns := models.ConvertJvnToModel(d.CveID, d.Jvns)
 | 
			
		||||
		fortinets := models.ConvertFortinetToModel(d.CveID, d.Fortinets)
 | 
			
		||||
		mitres := models.ConvertMitreToModel(d.CveID, d.Mitres)
 | 
			
		||||
 | 
			
		||||
		alerts := fillCertAlerts(&d)
 | 
			
		||||
		for cveID, vinfo := range r.ScannedCves {
 | 
			
		||||
@@ -475,18 +476,16 @@ func FillCvesWithNvdJvnFortinet(r *models.ScanResult, cnf config.GoCveDictConf,
 | 
			
		||||
				}
 | 
			
		||||
				for _, con := range append(jvns, fortinets...) {
 | 
			
		||||
					if !con.Empty() {
 | 
			
		||||
						found := false
 | 
			
		||||
						for _, cveCont := range vinfo.CveContents[con.Type] {
 | 
			
		||||
							if con.SourceLink == cveCont.SourceLink {
 | 
			
		||||
								found = true
 | 
			
		||||
								break
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
						if !found {
 | 
			
		||||
						if !slices.ContainsFunc(vinfo.CveContents[con.Type], func(e models.CveContent) bool {
 | 
			
		||||
							return con.SourceLink == e.SourceLink
 | 
			
		||||
						}) {
 | 
			
		||||
							vinfo.CveContents[con.Type] = append(vinfo.CveContents[con.Type], con)
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				for _, con := range mitres {
 | 
			
		||||
					vinfo.CveContents[con.Type] = append(vinfo.CveContents[con.Type], con)
 | 
			
		||||
				}
 | 
			
		||||
				vinfo.AlertDict = alerts
 | 
			
		||||
				vinfo.Exploits = append(vinfo.Exploits, exploits...)
 | 
			
		||||
				vinfo.Mitigations = append(vinfo.Mitigations, mitigations...)
 | 
			
		||||
 
 | 
			
		||||
@@ -181,7 +181,7 @@ func getMinusDiffCves(previous, current models.ScanResult) models.VulnInfos {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isCveInfoUpdated(cveID string, previous, current models.ScanResult) bool {
 | 
			
		||||
	cTypes := append([]models.CveContentType{models.Nvd, models.Jvn}, models.GetCveContentTypes(current.Family)...)
 | 
			
		||||
	cTypes := append([]models.CveContentType{models.Mitre, models.Nvd, models.Jvn}, models.GetCveContentTypes(current.Family)...)
 | 
			
		||||
 | 
			
		||||
	prevLastModified := map[models.CveContentType][]time.Time{}
 | 
			
		||||
	preVinfo, ok := previous.ScannedCves[cveID]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										60
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								go.mod
									
									
									
									
									
								
							@@ -14,11 +14,11 @@ require (
 | 
			
		||||
	github.com/aquasecurity/trivy-db v0.0.0-20240425111931-1fe1d505d3ff
 | 
			
		||||
	github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48
 | 
			
		||||
	github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2 v1.27.2
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/config v1.27.18
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/credentials v1.17.18
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/service/s3 v1.55.1
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/service/sts v1.28.12
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2 v1.30.0
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/config v1.27.21
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/credentials v1.17.21
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/service/s3 v1.56.1
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/service/sts v1.29.1
 | 
			
		||||
	github.com/c-robinson/iplib v1.0.8
 | 
			
		||||
	github.com/cenkalti/backoff v2.2.1+incompatible
 | 
			
		||||
	github.com/d4l3k/messagediff v1.2.2-0.20190829033028-7e0a312ae40b
 | 
			
		||||
@@ -51,14 +51,14 @@ require (
 | 
			
		||||
	github.com/sirupsen/logrus v1.9.3
 | 
			
		||||
	github.com/spf13/cobra v1.8.1
 | 
			
		||||
	github.com/vulsio/go-cti v0.0.5-0.20240318121747-822b3ef289cb
 | 
			
		||||
	github.com/vulsio/go-cve-dictionary v0.10.2-0.20240319004433-af03be313b77
 | 
			
		||||
	github.com/vulsio/go-cve-dictionary v0.10.2-0.20240628072614-73f15707be8e
 | 
			
		||||
	github.com/vulsio/go-exploitdb v0.4.7-0.20240318122115-ccb3abc151a1
 | 
			
		||||
	github.com/vulsio/go-kev v0.1.4-0.20240318121733-b3386e67d3fb
 | 
			
		||||
	github.com/vulsio/go-msfdb v0.2.4-0.20240318121704-8bfc812656dc
 | 
			
		||||
	github.com/vulsio/gost v0.4.6-0.20240501065222-d47d2e716bfa
 | 
			
		||||
	github.com/vulsio/goval-dictionary v0.9.5
 | 
			
		||||
	github.com/vulsio/goval-dictionary v0.9.6-0.20240625074017-1da5dfb8b28a
 | 
			
		||||
	go.etcd.io/bbolt v1.3.10
 | 
			
		||||
	golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
 | 
			
		||||
	golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8
 | 
			
		||||
	golang.org/x/oauth2 v0.21.0
 | 
			
		||||
	golang.org/x/sync v0.7.0
 | 
			
		||||
	golang.org/x/text v0.16.0
 | 
			
		||||
@@ -97,7 +97,7 @@ require (
 | 
			
		||||
	github.com/Microsoft/hcsshim v0.12.0 // indirect
 | 
			
		||||
	github.com/OneOfOne/xxhash v1.2.8 // indirect
 | 
			
		||||
	github.com/ProtonMail/go-crypto v1.1.0-alpha.2 // indirect
 | 
			
		||||
	github.com/PuerkitoBio/goquery v1.9.1 // indirect
 | 
			
		||||
	github.com/PuerkitoBio/goquery v1.9.2 // indirect
 | 
			
		||||
	github.com/VividCortex/ewma v1.2.0 // indirect
 | 
			
		||||
	github.com/agext/levenshtein v1.2.3 // indirect
 | 
			
		||||
	github.com/agnivade/levenshtein v1.1.1 // indirect
 | 
			
		||||
@@ -113,18 +113,18 @@ require (
 | 
			
		||||
	github.com/aquasecurity/trivy-checks v0.11.0 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go v1.53.9 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.8 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.12 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.12 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.9 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.12 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/service/ecr v1.28.2 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.11 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.9 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/service/sso v1.20.11 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.14 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.14 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.12 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/service/sso v1.21.1 // indirect
 | 
			
		||||
	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.25.1 // indirect
 | 
			
		||||
	github.com/aws/smithy-go v1.20.2 // indirect
 | 
			
		||||
	github.com/beorn7/perks v1.0.1 // indirect
 | 
			
		||||
	github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
 | 
			
		||||
@@ -197,7 +197,7 @@ require (
 | 
			
		||||
	github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
 | 
			
		||||
	github.com/hashicorp/errwrap v1.1.0 // indirect
 | 
			
		||||
	github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
 | 
			
		||||
	github.com/hashicorp/go-getter v1.7.4 // indirect
 | 
			
		||||
	github.com/hashicorp/go-getter v1.7.5 // indirect
 | 
			
		||||
	github.com/hashicorp/go-multierror v1.1.1 // indirect
 | 
			
		||||
	github.com/hashicorp/go-safetemp v1.0.0 // indirect
 | 
			
		||||
	github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
 | 
			
		||||
@@ -209,8 +209,8 @@ require (
 | 
			
		||||
	github.com/inconshreveable/log15 v3.0.0-testing.5+incompatible // indirect
 | 
			
		||||
	github.com/inconshreveable/mousetrap v1.1.0 // indirect
 | 
			
		||||
	github.com/jackc/pgpassfile v1.0.0 // indirect
 | 
			
		||||
	github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect
 | 
			
		||||
	github.com/jackc/pgx/v5 v5.5.5 // indirect
 | 
			
		||||
	github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
 | 
			
		||||
	github.com/jackc/pgx/v5 v5.6.0 // indirect
 | 
			
		||||
	github.com/jackc/puddle/v2 v2.2.1 // indirect
 | 
			
		||||
	github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
 | 
			
		||||
	github.com/jinzhu/inflection v1.0.0 // indirect
 | 
			
		||||
@@ -281,7 +281,7 @@ require (
 | 
			
		||||
	github.com/rivo/uniseg v0.4.7 // indirect
 | 
			
		||||
	github.com/rubenv/sql-migrate v1.5.2 // indirect
 | 
			
		||||
	github.com/russross/blackfriday/v2 v2.1.0 // indirect
 | 
			
		||||
	github.com/sagikazarmark/locafero v0.4.0 // indirect
 | 
			
		||||
	github.com/sagikazarmark/locafero v0.6.0 // indirect
 | 
			
		||||
	github.com/sagikazarmark/slog-shim v0.1.0 // indirect
 | 
			
		||||
	github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect
 | 
			
		||||
	github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect
 | 
			
		||||
@@ -295,7 +295,7 @@ require (
 | 
			
		||||
	github.com/spf13/afero v1.11.0 // indirect
 | 
			
		||||
	github.com/spf13/cast v1.6.0 // indirect
 | 
			
		||||
	github.com/spf13/pflag v1.0.5 // indirect
 | 
			
		||||
	github.com/spf13/viper v1.18.2 // indirect
 | 
			
		||||
	github.com/spf13/viper v1.19.0 // indirect
 | 
			
		||||
	github.com/stretchr/objx v0.5.2 // indirect
 | 
			
		||||
	github.com/stretchr/testify v1.9.0 // indirect
 | 
			
		||||
	github.com/subosito/gotenv v1.6.0 // indirect
 | 
			
		||||
@@ -322,12 +322,12 @@ require (
 | 
			
		||||
	go.uber.org/multierr v1.11.0 // indirect
 | 
			
		||||
	go.uber.org/zap v1.27.0 // indirect
 | 
			
		||||
	golang.org/x/crypto v0.24.0 // indirect
 | 
			
		||||
	golang.org/x/mod v0.17.0 // indirect
 | 
			
		||||
	golang.org/x/mod v0.18.0 // indirect
 | 
			
		||||
	golang.org/x/net v0.26.0 // indirect
 | 
			
		||||
	golang.org/x/sys v0.21.0 // indirect
 | 
			
		||||
	golang.org/x/term v0.21.0 // indirect
 | 
			
		||||
	golang.org/x/time v0.5.0 // indirect
 | 
			
		||||
	golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
 | 
			
		||||
	golang.org/x/tools v0.22.0 // indirect
 | 
			
		||||
	google.golang.org/api v0.172.0 // indirect
 | 
			
		||||
	google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7 // indirect
 | 
			
		||||
	google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 // indirect
 | 
			
		||||
@@ -339,8 +339,8 @@ require (
 | 
			
		||||
	gopkg.in/warnings.v0 v0.1.2 // indirect
 | 
			
		||||
	gopkg.in/yaml.v2 v2.4.0 // indirect
 | 
			
		||||
	gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
			
		||||
	gorm.io/driver/mysql v1.5.6 // indirect
 | 
			
		||||
	gorm.io/driver/postgres v1.5.7 // indirect
 | 
			
		||||
	gorm.io/driver/mysql v1.5.7 // indirect
 | 
			
		||||
	gorm.io/driver/postgres v1.5.9 // indirect
 | 
			
		||||
	gorm.io/gorm v1.25.10 // indirect
 | 
			
		||||
	gotest.tools/v3 v3.5.0 // indirect
 | 
			
		||||
	helm.sh/helm/v3 v3.15.1 // indirect
 | 
			
		||||
@@ -355,10 +355,10 @@ require (
 | 
			
		||||
	k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
 | 
			
		||||
	k8s.io/kubectl v0.30.0 // indirect
 | 
			
		||||
	k8s.io/utils v0.0.0-20231127182322-b307cd553661 // indirect
 | 
			
		||||
	modernc.org/libc v1.50.5 // indirect
 | 
			
		||||
	modernc.org/libc v1.53.4 // indirect
 | 
			
		||||
	modernc.org/mathutil v1.6.0 // indirect
 | 
			
		||||
	modernc.org/memory v1.8.0 // indirect
 | 
			
		||||
	modernc.org/sqlite v1.29.10 // indirect
 | 
			
		||||
	modernc.org/sqlite v1.30.1 // indirect
 | 
			
		||||
	mvdan.cc/sh/v3 v3.8.0 // indirect
 | 
			
		||||
	oras.land/oras-go v1.2.5 // indirect
 | 
			
		||||
	sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
 | 
			
		||||
@@ -367,3 +367,5 @@ require (
 | 
			
		||||
	sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
 | 
			
		||||
	sigs.k8s.io/yaml v1.4.0 // indirect
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
replace github.com/aquasecurity/trivy-db => ../trivy-db
 | 
			
		||||
							
								
								
									
										124
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										124
									
								
								go.sum
									
									
									
									
									
								
							@@ -258,8 +258,8 @@ github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8
 | 
			
		||||
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
 | 
			
		||||
github.com/ProtonMail/go-crypto v1.1.0-alpha.2 h1:bkyFVUP+ROOARdgCiJzNQo2V2kiB97LyUpzH9P6Hrlg=
 | 
			
		||||
github.com/ProtonMail/go-crypto v1.1.0-alpha.2/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
 | 
			
		||||
github.com/PuerkitoBio/goquery v1.9.1 h1:mTL6XjbJTZdpfL+Gwl5U2h1l9yEkJjhmlTeV9VPW7UI=
 | 
			
		||||
github.com/PuerkitoBio/goquery v1.9.1/go.mod h1:cW1n6TmIMDoORQU5IU/P1T3tGFunOeXEpGP2WHRwkbY=
 | 
			
		||||
github.com/PuerkitoBio/goquery v1.9.2 h1:4/wZksC3KgkQw7SQgkKotmKljk0M6V8TUvA8Wb4yPeE=
 | 
			
		||||
github.com/PuerkitoBio/goquery v1.9.2/go.mod h1:GHPCaP0ODyyxqcNoFGYlAprUFH81NuRPd0GX3Zu2Mvk=
 | 
			
		||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=
 | 
			
		||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
 | 
			
		||||
github.com/Ullaakut/nmap/v2 v2.2.2 h1:178Ety3d8T21sF6WZxyj7QVZUhnC1tL1J+tHLLW507Q=
 | 
			
		||||
@@ -319,42 +319,42 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:W
 | 
			
		||||
github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
 | 
			
		||||
github.com/aws/aws-sdk-go v1.53.9 h1:6oipls9+L+l2Me5rklqlX3xGWNWGcMinY3F69q9Q+Cg=
 | 
			
		||||
github.com/aws/aws-sdk-go v1.53.9/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2 v1.27.2 h1:pLsTXqX93rimAOZG2FIYraDQstZaaGVVN4tNw65v0h8=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2 v1.27.2/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2 v1.30.0 h1:6qAwtzlfcTtcL8NHtbDQAqgM5s6NDipQTkPxyH/6kAA=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2 v1.30.0/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 h1:x6xsQXGSmW6frevwDA+vi/wqhp1ct18mVXYN08/93to=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2/go.mod h1:lPprDr1e6cJdyYeGXnRaJoP4Md+cDBvi2eOj00BlGmg=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/config v1.27.18 h1:wFvAnwOKKe7QAyIxziwSKjmer9JBMH1vzIL6W+fYuKk=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/config v1.27.18/go.mod h1:0xz6cgdX55+kmppvPm2IaKzIXOheGJhAufacPJaXZ7c=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.18 h1:D/ALDWqK4JdY3OFgA2thcPO1c9aYTT5STS/CvnkqY1c=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.18/go.mod h1:JuitCWq+F5QGUrmMPsk945rop6bB57jdscu+Glozdnc=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5 h1:dDgptDO9dxeFkXy+tEgVkzSClHZje/6JkPW5aZyEvrQ=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5/go.mod h1:gjvE2KBUgUQhcv89jqxrIxH9GaKs1JbZzWejj/DaHGA=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9 h1:cy8ahBJuhtM8GTTSyOkfy6WVPV1IE+SS5/wfXUYuulw=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9/go.mod h1:CZBXGLaJnEZI6EVNcPd7a6B5IC5cA/GkRWtu9fp3S6Y=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9 h1:A4SYk07ef04+vxZToz9LWvAXl9LW0NClpPpMsi31cz0=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9/go.mod h1:5jJcHuwDagxN+ErjQ3PU3ocf6Ylc/p9x+BLO/+X4iXw=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/config v1.27.21 h1:yPX3pjGCe2hJsetlmGNB4Mngu7UPmvWPzzWCv1+boeM=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/config v1.27.21/go.mod h1:4XtlEU6DzNai8RMbjSF5MgGZtYvrhBP/aKZcRtZAVdM=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.21 h1:pjAqgzfgFhTv5grc7xPHtXCAaMapzmwA7aU+c/SZQGw=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.21/go.mod h1:nhK6PtBlfHTUDVmBLr1dg+WHCOCK+1Fu/WQyVHPsgNQ=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.8 h1:FR+oWPFb/8qMVYMWN98bUZAGqPvLHiyqg1wqQGfUAXY=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.8/go.mod h1:EgSKcHiuuakEIxJcKGzVNWh5srVAQ3jKaSrBGRYvM48=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.12 h1:SJ04WXGTwnHlWIODtC5kJzKbeuHt+OUNOgKg7nfnUGw=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.12/go.mod h1:FkpvXhA92gb3GE9LD6Og0pHHycTxW7xGpnEh5E7Opwo=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.12 h1:hb5KgeYfObi5MHkSSZMEudnIvX30iB+E21evI4r6BnQ=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.12/go.mod h1:CroKe/eWJdyfy9Vx4rljP5wTUjNJfb+fPz1uMYUhEGM=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.9 h1:vHyZxoLVOgrI8GqX7OMHLXp4YYoxeEsrjweXKpye+ds=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.9/go.mod h1:z9VXZsWA2BvZNH1dT0ToUYwMu/CR9Skkj/TBX+mceZw=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.12 h1:DXFWyt7ymx/l1ygdyTTS0X923e+Q2wXIxConJzrgwc0=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.12/go.mod h1:mVOr/LbvaNySK1/BTy4cBOCjhCNY2raWBwK4v+WR5J4=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/ecr v1.28.2 h1:xUpMnRZonKfrHaNLC77IMpWZSUMRRXIi6IU5EhAPsrM=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/ecr v1.28.2/go.mod h1:X52zjAVRaXklEU1TE/wO8kyyJSr9cJx9ZsqliWbyRys=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.11 h1:4vt9Sspk59EZyHCAEMaktHKiq0C09noRTQorXD/qV+s=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.11/go.mod h1:5jHR79Tv+Ccq6rwYh+W7Nptmw++WiFafMfR42XhwNl8=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11 h1:o4T+fKxA3gTMcluBNZZXE9DNaMkJuUL1O3mffCUjoJo=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11/go.mod h1:84oZdJ+VjuJKs9v1UTC9NaodRZRseOXCTgku+vQJWR8=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.9 h1:TE2i0A9ErH1YfRSvXfCr2SQwfnqsoJT9nPQ9kj0lkxM=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.9/go.mod h1:9TzXX3MehQNGPwCZ3ka4CpwQsoAMWSF48/b+De9rfVM=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.55.1 h1:UAxBuh0/8sFJk1qOkvOKewP5sWeWaTPDknbQz0ZkDm0=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.55.1/go.mod h1:hWjsYGjVuqCgfoveVcVFPXIWgz0aByzwaxKlN1StKcM=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.11 h1:gEYM2GSpr4YNWc6hCd5nod4+d4kd9vWIAWrmGuLdlMw=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.11/go.mod h1:gVvwPdPNYehHSP9Rs7q27U1EU+3Or2ZpXvzAYJNh63w=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 h1:iXjh3uaH3vsVcnyZX7MqCoCfcyxIrVE9iOQruRaWPrQ=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5/go.mod h1:5ZXesEuy/QcO0WUnt+4sDkxhdXRHTu2yG0uCSH8B6os=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 h1:M/1u4HBpwLuMtjlxuI2y6HoVLzF5e2mfxHCg7ZVMYmk=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/sts v1.28.12/go.mod h1:kcfd+eTdEi/40FIbLq4Hif3XMXnl5b/+t/KTfLt9xIk=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.14 h1:oWccitSnByVU74rQRHac4gLfDqjB6Z1YQGOY/dXKedI=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.14/go.mod h1:8SaZBlQdCLrc/2U3CEO48rYj9uR8qRsPRkmzwNM52pM=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.14 h1:zSDPny/pVnkqABXYRicYuPf9z2bTqfH13HT3v6UheIk=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.14/go.mod h1:3TTcI5JSzda1nw/pkVC9dhgLre0SNBFj2lYS4GctXKI=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.12 h1:tzha+v1SCEBpXWEuw6B/+jm4h5z8hZbTpXz0zRZqTnw=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.12/go.mod h1:n+nt2qjHGoseWeLHt1vEr6ZRCCxIN2KcNpJxBcYQSwI=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.56.1 h1:wsg9Z/vNnCmxWikfGIoOlnExtEU459cR+2d+iDJ8elo=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.56.1/go.mod h1:8rDw3mVwmvIWWX/+LWY3PPIMZuwnQdJMCt0iVFVT3qw=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/sso v1.21.1 h1:sd0BsnAvLH8gsp2e3cbaIr+9D7T1xugueQ7V/zUAsS4=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/sso v1.21.1/go.mod h1:lcQG/MmxydijbeTOp04hIuJwXGWPZGI3bwdFDGRTv14=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.25.1 h1:1uEFNNskK/I1KoZ9Q8wJxMz5V9jyBlsiaNrM7vA3YUQ=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.25.1/go.mod h1:z0P8K+cBIsFXUr5rzo/psUeJ20XjPN0+Nn8067Nd+E4=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/sts v1.29.1 h1:myX5CxqXE0QMZNja6FA1/FSE3Vu1rVmeUmpJMMzeZg0=
 | 
			
		||||
github.com/aws/aws-sdk-go-v2/service/sts v1.29.1/go.mod h1:N2mQiucsO0VwK9CYuS4/c2n6Smeh1v47Rz3dWCPFLdE=
 | 
			
		||||
github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q=
 | 
			
		||||
github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
 | 
			
		||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 | 
			
		||||
@@ -755,8 +755,8 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY
 | 
			
		||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 | 
			
		||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
 | 
			
		||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
 | 
			
		||||
github.com/hashicorp/go-getter v1.7.4 h1:3yQjWuxICvSpYwqSayAdKRFcvBl1y/vogCxczWSmix0=
 | 
			
		||||
github.com/hashicorp/go-getter v1.7.4/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744=
 | 
			
		||||
github.com/hashicorp/go-getter v1.7.5 h1:dT58k9hQ/vbxNMwoI5+xFYAJuv6152UNvdHokfI5wE4=
 | 
			
		||||
github.com/hashicorp/go-getter v1.7.5/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744=
 | 
			
		||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
 | 
			
		||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
 | 
			
		||||
github.com/hashicorp/go-retryablehttp v0.7.6 h1:TwRYfx2z2C4cLbXmT8I5PgP/xmuqASDyiVuGYfs9GZM=
 | 
			
		||||
@@ -794,10 +794,10 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
 | 
			
		||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
 | 
			
		||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
 | 
			
		||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
 | 
			
		||||
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA=
 | 
			
		||||
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
 | 
			
		||||
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
 | 
			
		||||
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
 | 
			
		||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
 | 
			
		||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
 | 
			
		||||
github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
 | 
			
		||||
github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
 | 
			
		||||
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
 | 
			
		||||
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
 | 
			
		||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
 | 
			
		||||
@@ -1068,8 +1068,8 @@ github.com/rubenv/sql-migrate v1.5.2/go.mod h1:H38GW8Vqf8F0Su5XignRyaRcbXbJunSWx
 | 
			
		||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 | 
			
		||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
 | 
			
		||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 | 
			
		||||
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
 | 
			
		||||
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
 | 
			
		||||
github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk=
 | 
			
		||||
github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0=
 | 
			
		||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
 | 
			
		||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
 | 
			
		||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA=
 | 
			
		||||
@@ -1122,8 +1122,8 @@ github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
 | 
			
		||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
 | 
			
		||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 | 
			
		||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 | 
			
		||||
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
 | 
			
		||||
github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
 | 
			
		||||
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
 | 
			
		||||
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
 | 
			
		||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
			
		||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
			
		||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 | 
			
		||||
@@ -1168,8 +1168,8 @@ github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinC
 | 
			
		||||
github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk=
 | 
			
		||||
github.com/vulsio/go-cti v0.0.5-0.20240318121747-822b3ef289cb h1:aC6CqML20oYEI5Wjx04uwpARsXjdGCrOk4ken+l4dG8=
 | 
			
		||||
github.com/vulsio/go-cti v0.0.5-0.20240318121747-822b3ef289cb/go.mod h1:MHlQMcrMMUGXVc9G1JBZg1J/frsugODntu7CfLInEFs=
 | 
			
		||||
github.com/vulsio/go-cve-dictionary v0.10.2-0.20240319004433-af03be313b77 h1:utQlIgdHOqx+TOHecQm3vk4Bu9QHZcwkKj2DMQ4F3mo=
 | 
			
		||||
github.com/vulsio/go-cve-dictionary v0.10.2-0.20240319004433-af03be313b77/go.mod h1:NYtVYgM43dITGd0wVGTGhBqGHYisdK7k6pLo+71rMzU=
 | 
			
		||||
github.com/vulsio/go-cve-dictionary v0.10.2-0.20240628072614-73f15707be8e h1:z/rVzYJy6LCeSzoLFZuiAFfe45giUYdsyPL+iprlC78=
 | 
			
		||||
github.com/vulsio/go-cve-dictionary v0.10.2-0.20240628072614-73f15707be8e/go.mod h1:Kxpy1CE1D/Wsu7HH+5K1RAQQ6PErMOPHZ2W0+bsxqNc=
 | 
			
		||||
github.com/vulsio/go-exploitdb v0.4.7-0.20240318122115-ccb3abc151a1 h1:rQRTmiO2gYEhyjthvGseV34Qj+nwrVgZEnFvk6Z2AqM=
 | 
			
		||||
github.com/vulsio/go-exploitdb v0.4.7-0.20240318122115-ccb3abc151a1/go.mod h1:ml2oTRyR37hUyyP4kWD9NSlBYIQuJUVNaAfbflSu4i4=
 | 
			
		||||
github.com/vulsio/go-kev v0.1.4-0.20240318121733-b3386e67d3fb h1:j03zKKkR+WWaPoPzMBwNxpDsc1mYDtt9s1VrHaIxmfw=
 | 
			
		||||
@@ -1178,8 +1178,8 @@ github.com/vulsio/go-msfdb v0.2.4-0.20240318121704-8bfc812656dc h1:nf62vF8T3yAmm
 | 
			
		||||
github.com/vulsio/go-msfdb v0.2.4-0.20240318121704-8bfc812656dc/go.mod h1:X7NqckQva6ok3GaWRYFAEvd72xzWFeGKOm9YOCWeIhc=
 | 
			
		||||
github.com/vulsio/gost v0.4.6-0.20240501065222-d47d2e716bfa h1:AmXiFpp2kFuoCgGw/yBl+RGuanSbPg7cV78dvIrbJ/k=
 | 
			
		||||
github.com/vulsio/gost v0.4.6-0.20240501065222-d47d2e716bfa/go.mod h1:fWe/YGX+XpPYIjrIvvl15/x/6GXj+pqbn8BHwnE3X/g=
 | 
			
		||||
github.com/vulsio/goval-dictionary v0.9.5 h1:wchMOOyPAS2IqzAszl/u3apubyZWvmKoM+c5lxK5FHs=
 | 
			
		||||
github.com/vulsio/goval-dictionary v0.9.5/go.mod h1:/LBgb03I5S4HNjXWx6T32CuQzYQgNUSLOKZwiOLR4AM=
 | 
			
		||||
github.com/vulsio/goval-dictionary v0.9.6-0.20240625074017-1da5dfb8b28a h1:8X9wH7AocxgrM52PYtjBZ2Xd/axrzCHonWwhQZSgQaM=
 | 
			
		||||
github.com/vulsio/goval-dictionary v0.9.6-0.20240625074017-1da5dfb8b28a/go.mod h1:Qkcs63pRa/ZuOrQO0xPIhR/M6WVKOQEV60fkRJFkM60=
 | 
			
		||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
 | 
			
		||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
 | 
			
		||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
 | 
			
		||||
@@ -1276,8 +1276,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
 | 
			
		||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
 | 
			
		||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
 | 
			
		||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
 | 
			
		||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
 | 
			
		||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
 | 
			
		||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
 | 
			
		||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
 | 
			
		||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 | 
			
		||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 | 
			
		||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 | 
			
		||||
@@ -1305,8 +1305,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
			
		||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
			
		||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 | 
			
		||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 | 
			
		||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
 | 
			
		||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 | 
			
		||||
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
 | 
			
		||||
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 | 
			
		||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
@@ -1565,8 +1565,8 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 | 
			
		||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 | 
			
		||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 | 
			
		||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 | 
			
		||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
 | 
			
		||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
 | 
			
		||||
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
 | 
			
		||||
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
@@ -1825,10 +1825,10 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
			
		||||
gorm.io/driver/mysql v1.5.6 h1:Ld4mkIickM+EliaQZQx3uOJDJHtrd70MxAUqWqlx3Y8=
 | 
			
		||||
gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
 | 
			
		||||
gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM=
 | 
			
		||||
gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA=
 | 
			
		||||
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
 | 
			
		||||
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
 | 
			
		||||
gorm.io/driver/postgres v1.5.9 h1:DkegyItji119OlcaLjqN11kHoUgZ/j13E0jkJZgD6A8=
 | 
			
		||||
gorm.io/driver/postgres v1.5.9/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
 | 
			
		||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
 | 
			
		||||
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
 | 
			
		||||
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
 | 
			
		||||
@@ -1865,18 +1865,18 @@ k8s.io/kubectl v0.30.0 h1:xbPvzagbJ6RNYVMVuiHArC1grrV5vSmmIcSZuCdzRyk=
 | 
			
		||||
k8s.io/kubectl v0.30.0/go.mod h1:zgolRw2MQXLPwmic2l/+iHs239L49fhSeICuMhQQXTI=
 | 
			
		||||
k8s.io/utils v0.0.0-20231127182322-b307cd553661 h1:FepOBzJ0GXm8t0su67ln2wAZjbQ6RxQGZDnzuLcrUTI=
 | 
			
		||||
k8s.io/utils v0.0.0-20231127182322-b307cd553661/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
 | 
			
		||||
modernc.org/cc/v4 v4.21.0 h1:D/gLKtcztomvWbsbvBKo3leKQv+86f+DdqEZBBXhnag=
 | 
			
		||||
modernc.org/cc/v4 v4.21.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
 | 
			
		||||
modernc.org/ccgo/v4 v4.17.3 h1:t2CQci84jnxKw3GGnHvjGKjiNZeZqyQx/023spkk4hU=
 | 
			
		||||
modernc.org/ccgo/v4 v4.17.3/go.mod h1:1FCbAtWYJoKuc+AviS+dH+vGNtYmFJqBeRWjmnDWsIg=
 | 
			
		||||
modernc.org/cc/v4 v4.21.3 h1:2mhBdWKtivdFlLR1ecKXTljPG1mfvbByX7QKztAIJl8=
 | 
			
		||||
modernc.org/cc/v4 v4.21.3/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
 | 
			
		||||
modernc.org/ccgo/v4 v4.18.2 h1:PUQPShG4HwghpOekNujL0sFavdkRvmxzTbI4rGJ5mg0=
 | 
			
		||||
modernc.org/ccgo/v4 v4.18.2/go.mod h1:ao1fAxf9a2KEOL15WY8+yP3wnpaOpP/QuyFOZ9HJolM=
 | 
			
		||||
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
 | 
			
		||||
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
 | 
			
		||||
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
 | 
			
		||||
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
 | 
			
		||||
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI=
 | 
			
		||||
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
 | 
			
		||||
modernc.org/libc v1.50.5 h1:ZzeUd0dIc/sUtoPTCYIrgypkuzoGzNu6kbEWj2VuEmk=
 | 
			
		||||
modernc.org/libc v1.50.5/go.mod h1:rhzrUx5oePTSTIzBgM0mTftwWHK8tiT9aNFUt1mldl0=
 | 
			
		||||
modernc.org/libc v1.53.4 h1:YAgFS7tGIFBfqje2UOqiXtIwuDUCF8AUonYw0seup34=
 | 
			
		||||
modernc.org/libc v1.53.4/go.mod h1:aGsLofnkcct8lTJnKQnCqJO37ERAXSHamSuWLFoF2Cw=
 | 
			
		||||
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
 | 
			
		||||
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
 | 
			
		||||
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
 | 
			
		||||
@@ -1885,8 +1885,8 @@ modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
 | 
			
		||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
 | 
			
		||||
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
 | 
			
		||||
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
 | 
			
		||||
modernc.org/sqlite v1.29.10 h1:3u93dz83myFnMilBGCOLbr+HjklS6+5rJLx4q86RDAg=
 | 
			
		||||
modernc.org/sqlite v1.29.10/go.mod h1:ItX2a1OVGgNsFh6Dv60JQvGfJfTPHPVpV6DF59akYOA=
 | 
			
		||||
modernc.org/sqlite v1.30.1 h1:YFhPVfu2iIgUf9kuA1CR7iiHdcEEsI2i+yjRYHscyxk=
 | 
			
		||||
modernc.org/sqlite v1.30.1/go.mod h1:DUmsiWQDaAvU4abhc/N+djlom/L2o8f7gZ95RCvyoLU=
 | 
			
		||||
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
 | 
			
		||||
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
 | 
			
		||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,14 @@
 | 
			
		||||
package models
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"sort"
 | 
			
		||||
	"cmp"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"slices"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/exp/maps"
 | 
			
		||||
 | 
			
		||||
	"github.com/future-architect/vuls/constant"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -15,18 +19,14 @@ type CveContents map[CveContentType][]CveContent
 | 
			
		||||
func NewCveContents(conts ...CveContent) CveContents {
 | 
			
		||||
	m := CveContents{}
 | 
			
		||||
	for _, cont := range conts {
 | 
			
		||||
		if cont.Type == Jvn {
 | 
			
		||||
			found := false
 | 
			
		||||
			for _, cveCont := range m[cont.Type] {
 | 
			
		||||
				if cont.SourceLink == cveCont.SourceLink {
 | 
			
		||||
					found = true
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if !found {
 | 
			
		||||
		switch cont.Type {
 | 
			
		||||
		case Jvn:
 | 
			
		||||
			if !slices.ContainsFunc(m[cont.Type], func(e CveContent) bool {
 | 
			
		||||
				return cont.SourceLink == e.SourceLink
 | 
			
		||||
			}) {
 | 
			
		||||
				m[cont.Type] = append(m[cont.Type], cont)
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
		default:
 | 
			
		||||
			m[cont.Type] = []CveContent{cont}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -43,14 +43,7 @@ type CveContentStr struct {
 | 
			
		||||
func (v CveContents) Except(exceptCtypes ...CveContentType) (values CveContents) {
 | 
			
		||||
	values = CveContents{}
 | 
			
		||||
	for ctype, content := range v {
 | 
			
		||||
		found := false
 | 
			
		||||
		for _, exceptCtype := range exceptCtypes {
 | 
			
		||||
			if ctype == exceptCtype {
 | 
			
		||||
				found = true
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if !found {
 | 
			
		||||
		if !slices.Contains(exceptCtypes, ctype) {
 | 
			
		||||
			values[ctype] = content
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -63,43 +56,51 @@ func (v CveContents) PrimarySrcURLs(lang, myFamily, cveID string, confidences Co
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if conts, found := v[Nvd]; found {
 | 
			
		||||
		for _, cont := range conts {
 | 
			
		||||
			for _, r := range cont.References {
 | 
			
		||||
				for _, t := range r.Tags {
 | 
			
		||||
					if t == "Vendor Advisory" {
 | 
			
		||||
						values = append(values, CveContentStr{Nvd, r.Link})
 | 
			
		||||
	for _, ctype := range append(append(CveContentTypes{Mitre, Nvd, Jvn}, GetCveContentTypes(myFamily)...), GitHub) {
 | 
			
		||||
		for _, cont := range v[ctype] {
 | 
			
		||||
			switch ctype {
 | 
			
		||||
			case Nvd:
 | 
			
		||||
				for _, r := range cont.References {
 | 
			
		||||
					if slices.Contains(r.Tags, "Vendor Advisory") {
 | 
			
		||||
						if !slices.ContainsFunc(values, func(e CveContentStr) bool {
 | 
			
		||||
							return e.Type == ctype && e.Value == r.Link
 | 
			
		||||
						}) {
 | 
			
		||||
							values = append(values, CveContentStr{
 | 
			
		||||
								Type:  ctype,
 | 
			
		||||
								Value: r.Link,
 | 
			
		||||
							})
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	order := append(append(CveContentTypes{Nvd}, GetCveContentTypes(myFamily)...), GitHub)
 | 
			
		||||
	for _, ctype := range order {
 | 
			
		||||
		if conts, found := v[ctype]; found {
 | 
			
		||||
			for _, cont := range conts {
 | 
			
		||||
				if cont.SourceLink == "" {
 | 
			
		||||
					continue
 | 
			
		||||
				if cont.SourceLink != "" && !slices.ContainsFunc(values, func(e CveContentStr) bool {
 | 
			
		||||
					return e.Type == ctype && e.Value == cont.SourceLink
 | 
			
		||||
				}) {
 | 
			
		||||
					values = append(values, CveContentStr{
 | 
			
		||||
						Type:  ctype,
 | 
			
		||||
						Value: cont.SourceLink,
 | 
			
		||||
					})
 | 
			
		||||
				}
 | 
			
		||||
				values = append(values, CveContentStr{ctype, cont.SourceLink})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	jvnMatch := false
 | 
			
		||||
	for _, confidence := range confidences {
 | 
			
		||||
		if confidence.DetectionMethod == JvnVendorProductMatchStr {
 | 
			
		||||
			jvnMatch = true
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if lang == "ja" || jvnMatch {
 | 
			
		||||
		if conts, found := v[Jvn]; found {
 | 
			
		||||
			for _, cont := range conts {
 | 
			
		||||
				if 0 < len(cont.SourceLink) {
 | 
			
		||||
					values = append(values, CveContentStr{Jvn, cont.SourceLink})
 | 
			
		||||
			case Jvn:
 | 
			
		||||
				if lang == "ja" || slices.ContainsFunc(confidences, func(e Confidence) bool {
 | 
			
		||||
					return e.DetectionMethod == JvnVendorProductMatchStr
 | 
			
		||||
				}) {
 | 
			
		||||
					if cont.SourceLink != "" && !slices.ContainsFunc(values, func(e CveContentStr) bool {
 | 
			
		||||
						return e.Type == ctype && e.Value == cont.SourceLink
 | 
			
		||||
					}) {
 | 
			
		||||
						values = append(values, CveContentStr{
 | 
			
		||||
							Type:  ctype,
 | 
			
		||||
							Value: cont.SourceLink,
 | 
			
		||||
						})
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default:
 | 
			
		||||
				if cont.SourceLink != "" && !slices.ContainsFunc(values, func(e CveContentStr) bool {
 | 
			
		||||
					return e.Type == ctype && e.Value == cont.SourceLink
 | 
			
		||||
				}) {
 | 
			
		||||
					values = append(values, CveContentStr{
 | 
			
		||||
						Type:  ctype,
 | 
			
		||||
						Value: cont.SourceLink,
 | 
			
		||||
					})
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@@ -108,7 +109,7 @@ func (v CveContents) PrimarySrcURLs(lang, myFamily, cveID string, confidences Co
 | 
			
		||||
	if len(values) == 0 && strings.HasPrefix(cveID, "CVE") {
 | 
			
		||||
		return []CveContentStr{{
 | 
			
		||||
			Type:  Nvd,
 | 
			
		||||
			Value: "https://nvd.nist.gov/vuln/detail/" + cveID,
 | 
			
		||||
			Value: fmt.Sprintf("https://nvd.nist.gov/vuln/detail/%s", cveID),
 | 
			
		||||
		}}
 | 
			
		||||
	}
 | 
			
		||||
	return values
 | 
			
		||||
@@ -116,17 +117,10 @@ func (v CveContents) PrimarySrcURLs(lang, myFamily, cveID string, confidences Co
 | 
			
		||||
 | 
			
		||||
// PatchURLs returns link of patch
 | 
			
		||||
func (v CveContents) PatchURLs() (urls []string) {
 | 
			
		||||
	conts, found := v[Nvd]
 | 
			
		||||
	if !found {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, cont := range conts {
 | 
			
		||||
	for _, cont := range v[Nvd] {
 | 
			
		||||
		for _, r := range cont.References {
 | 
			
		||||
			for _, t := range r.Tags {
 | 
			
		||||
				if t == "Patch" {
 | 
			
		||||
					urls = append(urls, r.Link)
 | 
			
		||||
				}
 | 
			
		||||
			if slices.Contains(r.Tags, "Patch") && !slices.Contains(urls, r.Link) {
 | 
			
		||||
				urls = append(urls, r.Link)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -145,21 +139,24 @@ func (v CveContents) Cpes(myFamily string) (values []CveContentCpes) {
 | 
			
		||||
	order = append(order, AllCveContetTypes.Except(order...)...)
 | 
			
		||||
 | 
			
		||||
	for _, ctype := range order {
 | 
			
		||||
		if conts, found := v[ctype]; found {
 | 
			
		||||
			for _, cont := range conts {
 | 
			
		||||
				if 0 < len(cont.Cpes) {
 | 
			
		||||
					values = append(values, CveContentCpes{
 | 
			
		||||
						Type:  ctype,
 | 
			
		||||
						Value: cont.Cpes,
 | 
			
		||||
					})
 | 
			
		||||
				}
 | 
			
		||||
		for _, cont := range v[ctype] {
 | 
			
		||||
			if len(cont.Cpes) == 0 {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if !slices.ContainsFunc(values, func(e CveContentCpes) bool {
 | 
			
		||||
				return e.Type == ctype && slices.Equal(e.Value, cont.Cpes)
 | 
			
		||||
			}) {
 | 
			
		||||
				values = append(values, CveContentCpes{
 | 
			
		||||
					Type:  ctype,
 | 
			
		||||
					Value: cont.Cpes,
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CveContentRefs has CveContentType and Cpes
 | 
			
		||||
// CveContentRefs has CveContentType and References
 | 
			
		||||
type CveContentRefs struct {
 | 
			
		||||
	Type  CveContentType
 | 
			
		||||
	Value []Reference
 | 
			
		||||
@@ -171,14 +168,19 @@ func (v CveContents) References(myFamily string) (values []CveContentRefs) {
 | 
			
		||||
	order = append(order, AllCveContetTypes.Except(order...)...)
 | 
			
		||||
 | 
			
		||||
	for _, ctype := range order {
 | 
			
		||||
		if conts, found := v[ctype]; found {
 | 
			
		||||
			for _, cont := range conts {
 | 
			
		||||
				if 0 < len(cont.References) {
 | 
			
		||||
					values = append(values, CveContentRefs{
 | 
			
		||||
						Type:  ctype,
 | 
			
		||||
						Value: cont.References,
 | 
			
		||||
					})
 | 
			
		||||
				}
 | 
			
		||||
		for _, cont := range v[ctype] {
 | 
			
		||||
			if len(cont.References) == 0 {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if !slices.ContainsFunc(values, func(e CveContentRefs) bool {
 | 
			
		||||
				return e.Type == ctype && slices.EqualFunc(e.Value, cont.References, func(e1, e2 Reference) bool {
 | 
			
		||||
					return e1.Link == e2.Link && e1.RefID == e2.RefID && e1.Source == e2.Source && slices.Equal(e1.Tags, e2.Tags)
 | 
			
		||||
				})
 | 
			
		||||
			}) {
 | 
			
		||||
				values = append(values, CveContentRefs{
 | 
			
		||||
					Type:  ctype,
 | 
			
		||||
					Value: cont.References,
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -191,20 +193,18 @@ func (v CveContents) CweIDs(myFamily string) (values []CveContentStr) {
 | 
			
		||||
	order := GetCveContentTypes(myFamily)
 | 
			
		||||
	order = append(order, AllCveContetTypes.Except(order...)...)
 | 
			
		||||
	for _, ctype := range order {
 | 
			
		||||
		if conts, found := v[ctype]; found {
 | 
			
		||||
			for _, cont := range conts {
 | 
			
		||||
				if 0 < len(cont.CweIDs) {
 | 
			
		||||
					for _, cweID := range cont.CweIDs {
 | 
			
		||||
						for _, val := range values {
 | 
			
		||||
							if val.Value == cweID {
 | 
			
		||||
								continue
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
						values = append(values, CveContentStr{
 | 
			
		||||
							Type:  ctype,
 | 
			
		||||
							Value: cweID,
 | 
			
		||||
						})
 | 
			
		||||
					}
 | 
			
		||||
		for _, cont := range v[ctype] {
 | 
			
		||||
			if len(cont.CweIDs) == 0 {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			for _, cweID := range cont.CweIDs {
 | 
			
		||||
				if !slices.ContainsFunc(values, func(e CveContentStr) bool {
 | 
			
		||||
					return e.Type == ctype && e.Value == cweID
 | 
			
		||||
				}) {
 | 
			
		||||
					values = append(values, CveContentStr{
 | 
			
		||||
						Type:  ctype,
 | 
			
		||||
						Value: cweID,
 | 
			
		||||
					})
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@@ -213,52 +213,55 @@ func (v CveContents) CweIDs(myFamily string) (values []CveContentStr) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UniqCweIDs returns Uniq CweIDs
 | 
			
		||||
func (v CveContents) UniqCweIDs(myFamily string) (values []CveContentStr) {
 | 
			
		||||
func (v CveContents) UniqCweIDs(myFamily string) []CveContentStr {
 | 
			
		||||
	uniq := map[string]CveContentStr{}
 | 
			
		||||
	for _, cwes := range v.CweIDs(myFamily) {
 | 
			
		||||
		uniq[cwes.Value] = cwes
 | 
			
		||||
	}
 | 
			
		||||
	for _, cwe := range uniq {
 | 
			
		||||
		values = append(values, cwe)
 | 
			
		||||
	return maps.Values(uniq)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CveContentSSVC has CveContentType and SSVC
 | 
			
		||||
type CveContentSSVC struct {
 | 
			
		||||
	Type  CveContentType
 | 
			
		||||
	Value SSVC
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v CveContents) SSVC() (value []CveContentSSVC) {
 | 
			
		||||
	for _, cont := range v[Mitre] {
 | 
			
		||||
		if cont.SSVC == nil {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		t := Mitre
 | 
			
		||||
		if s, ok := cont.Optional["source"]; ok {
 | 
			
		||||
			t = CveContentType(fmt.Sprintf("%s(%s)", Mitre, s))
 | 
			
		||||
		}
 | 
			
		||||
		value = append(value, CveContentSSVC{
 | 
			
		||||
			Type:  t,
 | 
			
		||||
			Value: *cont.SSVC,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	return values
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sort elements for integration-testing
 | 
			
		||||
func (v CveContents) Sort() {
 | 
			
		||||
	for contType, contents := range v {
 | 
			
		||||
		// CVSS3 desc, CVSS2 desc, SourceLink asc
 | 
			
		||||
		sort.Slice(contents, func(i, j int) bool {
 | 
			
		||||
			if contents[i].Cvss3Score > contents[j].Cvss3Score {
 | 
			
		||||
				return true
 | 
			
		||||
			} else if contents[i].Cvss3Score == contents[i].Cvss3Score {
 | 
			
		||||
				if contents[i].Cvss2Score > contents[j].Cvss2Score {
 | 
			
		||||
					return true
 | 
			
		||||
				} else if contents[i].Cvss2Score == contents[i].Cvss2Score {
 | 
			
		||||
					if contents[i].SourceLink < contents[j].SourceLink {
 | 
			
		||||
						return true
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			return false
 | 
			
		||||
		// CVSS40 desc, CVSS3 desc, CVSS2 desc, SourceLink asc
 | 
			
		||||
		slices.SortFunc(contents, func(a, b CveContent) int {
 | 
			
		||||
			return cmp.Or(
 | 
			
		||||
				cmp.Compare(b.Cvss40Score, a.Cvss40Score),
 | 
			
		||||
				cmp.Compare(b.Cvss3Score, a.Cvss3Score),
 | 
			
		||||
				cmp.Compare(b.Cvss2Score, a.Cvss2Score),
 | 
			
		||||
				cmp.Compare(a.SourceLink, b.SourceLink),
 | 
			
		||||
			)
 | 
			
		||||
		})
 | 
			
		||||
		v[contType] = contents
 | 
			
		||||
	}
 | 
			
		||||
	for contType, contents := range v {
 | 
			
		||||
		for cveID, cont := range contents {
 | 
			
		||||
			sort.Slice(cont.References, func(i, j int) bool {
 | 
			
		||||
				return cont.References[i].Link < cont.References[j].Link
 | 
			
		||||
			})
 | 
			
		||||
			sort.Slice(cont.CweIDs, func(i, j int) bool {
 | 
			
		||||
				return cont.CweIDs[i] < cont.CweIDs[j]
 | 
			
		||||
			})
 | 
			
		||||
			for i, ref := range cont.References {
 | 
			
		||||
				// sort v.CveContents[].References[].Tags
 | 
			
		||||
				sort.Slice(ref.Tags, func(j, k int) bool {
 | 
			
		||||
					return ref.Tags[j] < ref.Tags[k]
 | 
			
		||||
				})
 | 
			
		||||
				cont.References[i] = ref
 | 
			
		||||
			slices.SortFunc(cont.References, func(a, b Reference) int { return cmp.Compare(a.Link, b.Link) })
 | 
			
		||||
			for i := range cont.References {
 | 
			
		||||
				slices.Sort(cont.References[i].Tags)
 | 
			
		||||
			}
 | 
			
		||||
			slices.Sort(cont.CweIDs)
 | 
			
		||||
			contents[cveID] = cont
 | 
			
		||||
		}
 | 
			
		||||
		v[contType] = contents
 | 
			
		||||
@@ -267,23 +270,27 @@ func (v CveContents) Sort() {
 | 
			
		||||
 | 
			
		||||
// CveContent has abstraction of various vulnerability information
 | 
			
		||||
type CveContent struct {
 | 
			
		||||
	Type          CveContentType    `json:"type"`
 | 
			
		||||
	CveID         string            `json:"cveID"`
 | 
			
		||||
	Title         string            `json:"title"`
 | 
			
		||||
	Summary       string            `json:"summary"`
 | 
			
		||||
	Cvss2Score    float64           `json:"cvss2Score"`
 | 
			
		||||
	Cvss2Vector   string            `json:"cvss2Vector"`
 | 
			
		||||
	Cvss2Severity string            `json:"cvss2Severity"`
 | 
			
		||||
	Cvss3Score    float64           `json:"cvss3Score"`
 | 
			
		||||
	Cvss3Vector   string            `json:"cvss3Vector"`
 | 
			
		||||
	Cvss3Severity string            `json:"cvss3Severity"`
 | 
			
		||||
	SourceLink    string            `json:"sourceLink"`
 | 
			
		||||
	Cpes          []Cpe             `json:"cpes,omitempty"`
 | 
			
		||||
	References    References        `json:"references,omitempty"`
 | 
			
		||||
	CweIDs        []string          `json:"cweIDs,omitempty"`
 | 
			
		||||
	Published     time.Time         `json:"published"`
 | 
			
		||||
	LastModified  time.Time         `json:"lastModified"`
 | 
			
		||||
	Optional      map[string]string `json:"optional,omitempty"`
 | 
			
		||||
	Type           CveContentType    `json:"type"`
 | 
			
		||||
	CveID          string            `json:"cveID"`
 | 
			
		||||
	Title          string            `json:"title"`
 | 
			
		||||
	Summary        string            `json:"summary"`
 | 
			
		||||
	Cvss2Score     float64           `json:"cvss2Score"`
 | 
			
		||||
	Cvss2Vector    string            `json:"cvss2Vector"`
 | 
			
		||||
	Cvss2Severity  string            `json:"cvss2Severity"`
 | 
			
		||||
	Cvss3Score     float64           `json:"cvss3Score"`
 | 
			
		||||
	Cvss3Vector    string            `json:"cvss3Vector"`
 | 
			
		||||
	Cvss3Severity  string            `json:"cvss3Severity"`
 | 
			
		||||
	Cvss40Score    float64           `json:"cvss40Score"`
 | 
			
		||||
	Cvss40Vector   string            `json:"cvss40Vector"`
 | 
			
		||||
	Cvss40Severity string            `json:"cvss40Severity"`
 | 
			
		||||
	SSVC           *SSVC             `json:"ssvc,omitempty"`
 | 
			
		||||
	SourceLink     string            `json:"sourceLink"`
 | 
			
		||||
	Cpes           []Cpe             `json:"cpes,omitempty"`
 | 
			
		||||
	References     References        `json:"references,omitempty"`
 | 
			
		||||
	CweIDs         []string          `json:"cweIDs,omitempty"`
 | 
			
		||||
	Published      time.Time         `json:"published"`
 | 
			
		||||
	LastModified   time.Time         `json:"lastModified"`
 | 
			
		||||
	Optional       map[string]string `json:"optional,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Empty checks the content is empty
 | 
			
		||||
@@ -297,6 +304,8 @@ type CveContentType string
 | 
			
		||||
// NewCveContentType create CveContentType
 | 
			
		||||
func NewCveContentType(name string) CveContentType {
 | 
			
		||||
	switch name {
 | 
			
		||||
	case "mitre":
 | 
			
		||||
		return Mitre
 | 
			
		||||
	case "nvd":
 | 
			
		||||
		return Nvd
 | 
			
		||||
	case "jvn":
 | 
			
		||||
@@ -415,6 +424,9 @@ func GetCveContentTypes(family string) []CveContentType {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// Mitre is Mitre
 | 
			
		||||
	Mitre CveContentType = "mitre"
 | 
			
		||||
 | 
			
		||||
	// Nvd is Nvd JSON
 | 
			
		||||
	Nvd CveContentType = "nvd"
 | 
			
		||||
 | 
			
		||||
@@ -556,6 +568,7 @@ type CveContentTypes []CveContentType
 | 
			
		||||
 | 
			
		||||
// AllCveContetTypes has all of CveContentTypes
 | 
			
		||||
var AllCveContetTypes = CveContentTypes{
 | 
			
		||||
	Mitre,
 | 
			
		||||
	Nvd,
 | 
			
		||||
	Jvn,
 | 
			
		||||
	Fortinet,
 | 
			
		||||
@@ -603,14 +616,7 @@ var AllCveContetTypes = CveContentTypes{
 | 
			
		||||
// Except returns CveContentTypes except for given args
 | 
			
		||||
func (c CveContentTypes) Except(excepts ...CveContentType) (excepted CveContentTypes) {
 | 
			
		||||
	for _, ctype := range c {
 | 
			
		||||
		found := false
 | 
			
		||||
		for _, except := range excepts {
 | 
			
		||||
			if ctype == except {
 | 
			
		||||
				found = true
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if !found {
 | 
			
		||||
		if !slices.Contains(excepts, ctype) {
 | 
			
		||||
			excepted = append(excepted, ctype)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -633,3 +639,10 @@ type Reference struct {
 | 
			
		||||
	RefID  string   `json:"refID,omitempty"`
 | 
			
		||||
	Tags   []string `json:"tags,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SSVC has SSVC decision points
 | 
			
		||||
type SSVC struct {
 | 
			
		||||
	Exploitation    string `json:"exploitation,omitempty"`
 | 
			
		||||
	Automatable     string `json:"automatable,omitempty"`
 | 
			
		||||
	TechnicalImpact string `json:"technical_impact,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,26 +7,37 @@ import (
 | 
			
		||||
	"github.com/future-architect/vuls/constant"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestExcept(t *testing.T) {
 | 
			
		||||
	var tests = []struct {
 | 
			
		||||
		in  CveContents
 | 
			
		||||
		out CveContents
 | 
			
		||||
	}{{
 | 
			
		||||
		in: CveContents{
 | 
			
		||||
			RedHat: []CveContent{{Type: RedHat}},
 | 
			
		||||
			Ubuntu: []CveContent{{Type: Ubuntu}},
 | 
			
		||||
			Debian: []CveContent{{Type: Debian}},
 | 
			
		||||
func TestCveContents_Except(t *testing.T) {
 | 
			
		||||
	type args struct {
 | 
			
		||||
		exceptCtypes []CveContentType
 | 
			
		||||
	}
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name       string
 | 
			
		||||
		v          CveContents
 | 
			
		||||
		args       args
 | 
			
		||||
		wantValues CveContents
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "happy",
 | 
			
		||||
			v: CveContents{
 | 
			
		||||
				RedHat: []CveContent{{Type: RedHat}},
 | 
			
		||||
				Ubuntu: []CveContent{{Type: Ubuntu}},
 | 
			
		||||
				Debian: []CveContent{{Type: Debian}},
 | 
			
		||||
			},
 | 
			
		||||
			args: args{
 | 
			
		||||
				exceptCtypes: []CveContentType{Ubuntu, Debian},
 | 
			
		||||
			},
 | 
			
		||||
			wantValues: CveContents{
 | 
			
		||||
				RedHat: []CveContent{{Type: RedHat}},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		out: CveContents{
 | 
			
		||||
			RedHat: []CveContent{{Type: RedHat}},
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		actual := tt.in.Except(Ubuntu, Debian)
 | 
			
		||||
		if !reflect.DeepEqual(tt.out, actual) {
 | 
			
		||||
			t.Errorf("\nexpected: %v\n  actual: %v\n", tt.out, actual)
 | 
			
		||||
		}
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			if gotValues := tt.v.Except(tt.args.exceptCtypes...); !reflect.DeepEqual(gotValues, tt.wantValues) {
 | 
			
		||||
				t.Errorf("CveContents.Except() = %v, want %v", gotValues, tt.wantValues)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -84,14 +95,14 @@ func TestSourceLinks(t *testing.T) {
 | 
			
		||||
					Type:  Nvd,
 | 
			
		||||
					Value: "https://nvd.nist.gov/vuln/detail/CVE-2017-6074",
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Type:  RedHat,
 | 
			
		||||
					Value: "https://access.redhat.com/security/cve/CVE-2017-6074",
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Type:  Jvn,
 | 
			
		||||
					Value: "https://jvn.jp/vu/JVNVU93610402/",
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Type:  RedHat,
 | 
			
		||||
					Value: "https://access.redhat.com/security/cve/CVE-2017-6074",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		// lang: en
 | 
			
		||||
@@ -162,6 +173,294 @@ func TestSourceLinks(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestCveContents_PatchURLs(t *testing.T) {
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name     string
 | 
			
		||||
		v        CveContents
 | 
			
		||||
		wantUrls []string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "happy",
 | 
			
		||||
			v: CveContents{
 | 
			
		||||
				Nvd: []CveContent{
 | 
			
		||||
					{
 | 
			
		||||
						References: []Reference{
 | 
			
		||||
							{
 | 
			
		||||
								Link:   "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c52873e5a1ef72f845526d9f6a50704433f9c625",
 | 
			
		||||
								Source: "cve@mitre.org",
 | 
			
		||||
								Tags:   []string{"Patch", "Vendor Advisory"},
 | 
			
		||||
							},
 | 
			
		||||
							{
 | 
			
		||||
								Link:   "https://lists.debian.org/debian-lts-announce/2020/01/msg00013.html",
 | 
			
		||||
								Source: "cve@mitre.org",
 | 
			
		||||
								Tags:   []string{"Mailing List", "Third Party Advisory"},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						References: []Reference{
 | 
			
		||||
							{
 | 
			
		||||
								Link: "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c52873e5a1ef72f845526d9f6a50704433f9c625",
 | 
			
		||||
								Tags: []string{"Patch", "Vendor Advisory"},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			wantUrls: []string{"https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c52873e5a1ef72f845526d9f6a50704433f9c625"},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			if gotUrls := tt.v.PatchURLs(); !reflect.DeepEqual(gotUrls, tt.wantUrls) {
 | 
			
		||||
				t.Errorf("CveContents.PatchURLs() = %v, want %v", gotUrls, tt.wantUrls)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestCveContents_Cpes(t *testing.T) {
 | 
			
		||||
	type args struct {
 | 
			
		||||
		myFamily string
 | 
			
		||||
	}
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name       string
 | 
			
		||||
		v          CveContents
 | 
			
		||||
		args       args
 | 
			
		||||
		wantValues []CveContentCpes
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "happy",
 | 
			
		||||
			v: CveContents{
 | 
			
		||||
				Nvd: []CveContent{{
 | 
			
		||||
					Cpes: []Cpe{{
 | 
			
		||||
						URI:             "cpe:/a:microsoft:internet_explorer:8.0.6001:beta",
 | 
			
		||||
						FormattedString: "cpe:2.3:a:microsoft:internet_explorer:8.0.6001:beta:*:*:*:*:*:*",
 | 
			
		||||
					}},
 | 
			
		||||
				}},
 | 
			
		||||
			},
 | 
			
		||||
			args: args{myFamily: "redhat"},
 | 
			
		||||
			wantValues: []CveContentCpes{{
 | 
			
		||||
				Type: Nvd,
 | 
			
		||||
				Value: []Cpe{{
 | 
			
		||||
					URI:             "cpe:/a:microsoft:internet_explorer:8.0.6001:beta",
 | 
			
		||||
					FormattedString: "cpe:2.3:a:microsoft:internet_explorer:8.0.6001:beta:*:*:*:*:*:*",
 | 
			
		||||
				}},
 | 
			
		||||
			}},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			if gotValues := tt.v.Cpes(tt.args.myFamily); !reflect.DeepEqual(gotValues, tt.wantValues) {
 | 
			
		||||
				t.Errorf("CveContents.Cpes() = %v, want %v", gotValues, tt.wantValues)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func TestCveContents_References(t *testing.T) {
 | 
			
		||||
	type args struct {
 | 
			
		||||
		myFamily string
 | 
			
		||||
	}
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name       string
 | 
			
		||||
		v          CveContents
 | 
			
		||||
		args       args
 | 
			
		||||
		wantValues []CveContentRefs
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "happy",
 | 
			
		||||
			v: CveContents{
 | 
			
		||||
				Mitre: []CveContent{{CveID: "CVE-2024-0001"}},
 | 
			
		||||
				Nvd: []CveContent{
 | 
			
		||||
					{
 | 
			
		||||
						References: []Reference{
 | 
			
		||||
							{
 | 
			
		||||
								Link:   "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c52873e5a1ef72f845526d9f6a50704433f9c625",
 | 
			
		||||
								Source: "cve@mitre.org",
 | 
			
		||||
								Tags:   []string{"Patch", "Vendor Advisory"},
 | 
			
		||||
							},
 | 
			
		||||
							{
 | 
			
		||||
								Link:   "https://lists.debian.org/debian-lts-announce/2020/01/msg00013.html",
 | 
			
		||||
								Source: "cve@mitre.org",
 | 
			
		||||
								Tags:   []string{"Mailing List", "Third Party Advisory"},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						References: []Reference{
 | 
			
		||||
							{
 | 
			
		||||
								Link: "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c52873e5a1ef72f845526d9f6a50704433f9c625",
 | 
			
		||||
								Tags: []string{"Patch", "Vendor Advisory"},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			wantValues: []CveContentRefs{
 | 
			
		||||
				{
 | 
			
		||||
					Type: Nvd,
 | 
			
		||||
					Value: []Reference{
 | 
			
		||||
						{
 | 
			
		||||
							Link:   "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c52873e5a1ef72f845526d9f6a50704433f9c625",
 | 
			
		||||
							Source: "cve@mitre.org",
 | 
			
		||||
							Tags:   []string{"Patch", "Vendor Advisory"},
 | 
			
		||||
						},
 | 
			
		||||
						{
 | 
			
		||||
							Link:   "https://lists.debian.org/debian-lts-announce/2020/01/msg00013.html",
 | 
			
		||||
							Source: "cve@mitre.org",
 | 
			
		||||
							Tags:   []string{"Mailing List", "Third Party Advisory"},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Type: Nvd,
 | 
			
		||||
					Value: []Reference{
 | 
			
		||||
						{
 | 
			
		||||
							Link: "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c52873e5a1ef72f845526d9f6a50704433f9c625",
 | 
			
		||||
							Tags: []string{"Patch", "Vendor Advisory"},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			if gotValues := tt.v.References(tt.args.myFamily); !reflect.DeepEqual(gotValues, tt.wantValues) {
 | 
			
		||||
				t.Errorf("CveContents.References() = %v, want %v", gotValues, tt.wantValues)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestCveContents_CweIDs(t *testing.T) {
 | 
			
		||||
	type args struct {
 | 
			
		||||
		myFamily string
 | 
			
		||||
	}
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name       string
 | 
			
		||||
		v          CveContents
 | 
			
		||||
		args       args
 | 
			
		||||
		wantValues []CveContentStr
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "happy",
 | 
			
		||||
			v: CveContents{
 | 
			
		||||
				Mitre: []CveContent{{CweIDs: []string{"CWE-001"}}},
 | 
			
		||||
				Nvd: []CveContent{
 | 
			
		||||
					{CweIDs: []string{"CWE-001"}},
 | 
			
		||||
					{CweIDs: []string{"CWE-001"}},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			args: args{myFamily: "redhat"},
 | 
			
		||||
			wantValues: []CveContentStr{
 | 
			
		||||
				{
 | 
			
		||||
					Type:  Mitre,
 | 
			
		||||
					Value: "CWE-001",
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Type:  Nvd,
 | 
			
		||||
					Value: "CWE-001",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			if gotValues := tt.v.CweIDs(tt.args.myFamily); !reflect.DeepEqual(gotValues, tt.wantValues) {
 | 
			
		||||
				t.Errorf("CveContents.CweIDs() = %v, want %v", gotValues, tt.wantValues)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestCveContents_UniqCweIDs(t *testing.T) {
 | 
			
		||||
	type args struct {
 | 
			
		||||
		myFamily string
 | 
			
		||||
	}
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name string
 | 
			
		||||
		v    CveContents
 | 
			
		||||
		args args
 | 
			
		||||
		want []CveContentStr
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "happy",
 | 
			
		||||
			v: CveContents{
 | 
			
		||||
				Mitre: []CveContent{{CweIDs: []string{"CWE-001"}}},
 | 
			
		||||
				Nvd: []CveContent{
 | 
			
		||||
					{CweIDs: []string{"CWE-001"}},
 | 
			
		||||
					{CweIDs: []string{"CWE-001"}},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			args: args{myFamily: "redhat"},
 | 
			
		||||
			want: []CveContentStr{
 | 
			
		||||
				{
 | 
			
		||||
					Type:  Nvd,
 | 
			
		||||
					Value: "CWE-001",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			if got := tt.v.UniqCweIDs(tt.args.myFamily); !reflect.DeepEqual(got, tt.want) {
 | 
			
		||||
				t.Errorf("CveContents.UniqCweIDs() = %v, want %v", got, tt.want)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestCveContents_SSVC(t *testing.T) {
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name string
 | 
			
		||||
		v    CveContents
 | 
			
		||||
		want []CveContentSSVC
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "happy",
 | 
			
		||||
			v: CveContents{
 | 
			
		||||
				Mitre: []CveContent{
 | 
			
		||||
					{
 | 
			
		||||
						Type:     Mitre,
 | 
			
		||||
						CveID:    "CVE-2024-5732",
 | 
			
		||||
						Title:    "Clash Proxy Port improper authentication",
 | 
			
		||||
						Optional: map[string]string{"source": "CNA"},
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						Type:  Mitre,
 | 
			
		||||
						CveID: "CVE-2024-5732",
 | 
			
		||||
						Title: "CISA ADP Vulnrichment",
 | 
			
		||||
						SSVC: &SSVC{
 | 
			
		||||
							Exploitation:    "none",
 | 
			
		||||
							Automatable:     "no",
 | 
			
		||||
							TechnicalImpact: "partial",
 | 
			
		||||
						},
 | 
			
		||||
						Optional: map[string]string{"source": "ADP:CISA-ADP"},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			want: []CveContentSSVC{
 | 
			
		||||
				{
 | 
			
		||||
					Type: "mitre(ADP:CISA-ADP)",
 | 
			
		||||
					Value: SSVC{
 | 
			
		||||
						Exploitation:    "none",
 | 
			
		||||
						Automatable:     "no",
 | 
			
		||||
						TechnicalImpact: "partial",
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			if got := tt.v.SSVC(); !reflect.DeepEqual(got, tt.want) {
 | 
			
		||||
				t.Errorf("CveContents.SSVC() = %v, want %v", got, tt.want)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestCveContents_Sort(t *testing.T) {
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name string
 | 
			
		||||
@@ -241,6 +540,48 @@ func TestCveContents_Sort(t *testing.T) {
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "sort CVSS v4.0",
 | 
			
		||||
			v: CveContents{
 | 
			
		||||
				Mitre: []CveContent{
 | 
			
		||||
					{Cvss40Score: 0},
 | 
			
		||||
					{Cvss40Score: 6.9},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			want: CveContents{
 | 
			
		||||
				Mitre: []CveContent{
 | 
			
		||||
					{Cvss40Score: 6.9},
 | 
			
		||||
					{Cvss40Score: 0},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "sort CVSS v4.0 and CVSS v3",
 | 
			
		||||
			v: CveContents{
 | 
			
		||||
				Mitre: []CveContent{
 | 
			
		||||
					{
 | 
			
		||||
						Cvss40Score: 0,
 | 
			
		||||
						Cvss3Score:  7.3,
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						Cvss40Score: 0,
 | 
			
		||||
						Cvss3Score:  9.8,
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			want: CveContents{
 | 
			
		||||
				Mitre: []CveContent{
 | 
			
		||||
					{
 | 
			
		||||
						Cvss40Score: 0,
 | 
			
		||||
						Cvss3Score:  9.8,
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						Cvss40Score: 0,
 | 
			
		||||
						Cvss3Score:  7.3,
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
@@ -252,6 +593,47 @@ func TestCveContents_Sort(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestCveContent_Empty(t *testing.T) {
 | 
			
		||||
	type fields struct {
 | 
			
		||||
		Type    CveContentType
 | 
			
		||||
		CveID   string
 | 
			
		||||
		Title   string
 | 
			
		||||
		Summary string
 | 
			
		||||
	}
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name   string
 | 
			
		||||
		fields fields
 | 
			
		||||
		want   bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "empty",
 | 
			
		||||
			fields: fields{
 | 
			
		||||
				Summary: "",
 | 
			
		||||
			},
 | 
			
		||||
			want: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "not empty",
 | 
			
		||||
			fields: fields{
 | 
			
		||||
				Summary: "summary",
 | 
			
		||||
			},
 | 
			
		||||
			want: false,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			if got := (CveContent{
 | 
			
		||||
				Type:    tt.fields.Type,
 | 
			
		||||
				CveID:   tt.fields.CveID,
 | 
			
		||||
				Title:   tt.fields.Title,
 | 
			
		||||
				Summary: tt.fields.Summary,
 | 
			
		||||
			}).Empty(); got != tt.want {
 | 
			
		||||
				t.Errorf("CveContent.Empty() = %v, want %v", got, tt.want)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestNewCveContentType(t *testing.T) {
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name string
 | 
			
		||||
@@ -309,3 +691,31 @@ func TestGetCveContentTypes(t *testing.T) {
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestCveContentTypes_Except(t *testing.T) {
 | 
			
		||||
	type args struct {
 | 
			
		||||
		excepts []CveContentType
 | 
			
		||||
	}
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name         string
 | 
			
		||||
		c            CveContentTypes
 | 
			
		||||
		args         args
 | 
			
		||||
		wantExcepted CveContentTypes
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "happy",
 | 
			
		||||
			c:    CveContentTypes{Ubuntu, UbuntuAPI},
 | 
			
		||||
			args: args{
 | 
			
		||||
				excepts: []CveContentType{Ubuntu},
 | 
			
		||||
			},
 | 
			
		||||
			wantExcepted: CveContentTypes{UbuntuAPI},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			if gotExcepted := tt.c.Except(tt.args.excepts...); !reflect.DeepEqual(gotExcepted, tt.wantExcepted) {
 | 
			
		||||
				t.Errorf("CveContentTypes.Except() = %v, want %v", gotExcepted, tt.wantExcepted)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										120
									
								
								models/utils.go
									
									
									
									
									
								
							
							
						
						
									
										120
									
								
								models/utils.go
									
									
									
									
									
								
							@@ -6,6 +6,7 @@ package models
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	cvedict "github.com/vulsio/go-cve-dictionary/models"
 | 
			
		||||
)
 | 
			
		||||
@@ -178,3 +179,122 @@ func ConvertFortinetToModel(cveID string, fortinets []cvedict.Fortinet) []CveCon
 | 
			
		||||
	}
 | 
			
		||||
	return cves
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ConvertMitreToModel convert Mitre to CveContent
 | 
			
		||||
func ConvertMitreToModel(cveID string, mitres []cvedict.Mitre) []CveContent {
 | 
			
		||||
	var cves []CveContent
 | 
			
		||||
	for _, mitre := range mitres {
 | 
			
		||||
		for _, c := range mitre.Containers {
 | 
			
		||||
			cve := CveContent{
 | 
			
		||||
				Type:  Mitre,
 | 
			
		||||
				CveID: cveID,
 | 
			
		||||
				Title: func() string {
 | 
			
		||||
					if c.Title != nil {
 | 
			
		||||
						return *c.Title
 | 
			
		||||
					}
 | 
			
		||||
					return ""
 | 
			
		||||
				}(),
 | 
			
		||||
				Summary: func() string {
 | 
			
		||||
					for _, d := range c.Descriptions {
 | 
			
		||||
						if d.Lang == "en" {
 | 
			
		||||
							return d.Value
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					return ""
 | 
			
		||||
				}(),
 | 
			
		||||
				SourceLink: fmt.Sprintf("https://www.cve.org/CVERecord?id=%s", cveID),
 | 
			
		||||
				Published: func() time.Time {
 | 
			
		||||
					if mitre.CVEMetadata.DatePublished != nil {
 | 
			
		||||
						return *mitre.CVEMetadata.DatePublished
 | 
			
		||||
					}
 | 
			
		||||
					return time.Time{}
 | 
			
		||||
				}(),
 | 
			
		||||
				LastModified: func() time.Time {
 | 
			
		||||
					if mitre.CVEMetadata.DateUpdated != nil {
 | 
			
		||||
						return *mitre.CVEMetadata.DateUpdated
 | 
			
		||||
					}
 | 
			
		||||
					if mitre.CVEMetadata.DatePublished != nil {
 | 
			
		||||
						return *mitre.CVEMetadata.DatePublished
 | 
			
		||||
					}
 | 
			
		||||
					return time.Time{}
 | 
			
		||||
				}(),
 | 
			
		||||
				Optional: map[string]string{"source": func() string {
 | 
			
		||||
					if c.ProviderMetadata.ShortName != nil {
 | 
			
		||||
						return fmt.Sprintf("%s:%s", c.ContainerType, *c.ProviderMetadata.ShortName)
 | 
			
		||||
					}
 | 
			
		||||
					return fmt.Sprintf("%s:%s", c.ContainerType, c.ProviderMetadata.OrgID)
 | 
			
		||||
				}()},
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for _, m := range c.Metrics {
 | 
			
		||||
				if m.CVSSv2 != nil {
 | 
			
		||||
					cve.Cvss2Score = m.CVSSv2.BaseScore
 | 
			
		||||
					cve.Cvss2Vector = m.CVSSv2.VectorString
 | 
			
		||||
				}
 | 
			
		||||
				if m.CVSSv30 != nil {
 | 
			
		||||
					if cve.Cvss3Vector == "" {
 | 
			
		||||
						cve.Cvss3Score = m.CVSSv30.BaseScore
 | 
			
		||||
						cve.Cvss3Vector = m.CVSSv30.VectorString
 | 
			
		||||
						cve.Cvss3Severity = m.CVSSv30.BaseSeverity
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				if m.CVSSv31 != nil {
 | 
			
		||||
					cve.Cvss3Score = m.CVSSv31.BaseScore
 | 
			
		||||
					cve.Cvss3Vector = m.CVSSv31.VectorString
 | 
			
		||||
					cve.Cvss3Severity = m.CVSSv31.BaseSeverity
 | 
			
		||||
				}
 | 
			
		||||
				if m.CVSSv40 != nil {
 | 
			
		||||
					cve.Cvss40Score = m.CVSSv40.BaseScore
 | 
			
		||||
					cve.Cvss40Vector = m.CVSSv40.VectorString
 | 
			
		||||
					cve.Cvss40Severity = m.CVSSv40.BaseSeverity
 | 
			
		||||
				}
 | 
			
		||||
				if m.SSVC != nil {
 | 
			
		||||
					cve.SSVC = &SSVC{
 | 
			
		||||
						Exploitation: func() string {
 | 
			
		||||
							if m.SSVC.Exploitation != nil {
 | 
			
		||||
								return *m.SSVC.Exploitation
 | 
			
		||||
							}
 | 
			
		||||
							return ""
 | 
			
		||||
						}(),
 | 
			
		||||
						Automatable: func() string {
 | 
			
		||||
							if m.SSVC.Automatable != nil {
 | 
			
		||||
								return *m.SSVC.Automatable
 | 
			
		||||
							}
 | 
			
		||||
							return ""
 | 
			
		||||
						}(),
 | 
			
		||||
						TechnicalImpact: func() string {
 | 
			
		||||
							if m.SSVC.TechnicalImpact != nil {
 | 
			
		||||
								return *m.SSVC.TechnicalImpact
 | 
			
		||||
							}
 | 
			
		||||
							return ""
 | 
			
		||||
						}(),
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for _, r := range c.References {
 | 
			
		||||
				cve.References = append(cve.References, Reference{
 | 
			
		||||
					Link:   r.Link,
 | 
			
		||||
					Source: r.Source,
 | 
			
		||||
					Tags: func() []string {
 | 
			
		||||
						if len(r.Tags) > 0 {
 | 
			
		||||
							return strings.Split(r.Tags, ",")
 | 
			
		||||
						}
 | 
			
		||||
						return nil
 | 
			
		||||
					}(),
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for _, p := range c.ProblemTypes {
 | 
			
		||||
				for _, d := range p.Descriptions {
 | 
			
		||||
					if d.CweID != nil {
 | 
			
		||||
						cve.CweIDs = append(cve.CweIDs, *d.CweID)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			cves = append(cves, cve)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return cves
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -123,8 +123,7 @@ func (v VulnInfos) FilterIgnorePkgs(ignorePkgsRegexps []string) (_ VulnInfos, nF
 | 
			
		||||
// FindScoredVulns return scored vulnerabilities
 | 
			
		||||
func (v VulnInfos) FindScoredVulns() (_ VulnInfos, nFiltered int) {
 | 
			
		||||
	return v.Find(func(vv VulnInfo) bool {
 | 
			
		||||
		if 0 < vv.MaxCvss2Score().Value.Score ||
 | 
			
		||||
			0 < vv.MaxCvss3Score().Value.Score {
 | 
			
		||||
		if 0 < vv.MaxCvss2Score().Value.Score || 0 < vv.MaxCvss3Score().Value.Score || 0 < vv.MaxCvss40Score().Value.Score {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
		nFiltered++
 | 
			
		||||
@@ -152,7 +151,10 @@ func (v VulnInfos) ToSortedSlice() (sorted []VulnInfo) {
 | 
			
		||||
func (v VulnInfos) CountGroupBySeverity() map[string]int {
 | 
			
		||||
	m := map[string]int{}
 | 
			
		||||
	for _, vInfo := range v {
 | 
			
		||||
		score := vInfo.MaxCvss3Score().Value.Score
 | 
			
		||||
		score := vInfo.MaxCvss40Score().Value.Score
 | 
			
		||||
		if score < 0.1 {
 | 
			
		||||
			score = vInfo.MaxCvss3Score().Value.Score
 | 
			
		||||
		}
 | 
			
		||||
		if score < 0.1 {
 | 
			
		||||
			score = vInfo.MaxCvss2Score().Value.Score
 | 
			
		||||
		}
 | 
			
		||||
@@ -417,7 +419,7 @@ func (v VulnInfo) Titles(lang, myFamily string) (values []CveContentStr) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	order := append(GetCveContentTypes(string(Trivy)), append(CveContentTypes{Fortinet, Nvd}, GetCveContentTypes(myFamily)...)...)
 | 
			
		||||
	order := append(GetCveContentTypes(string(Trivy)), append(CveContentTypes{Fortinet, Nvd, Mitre}, GetCveContentTypes(myFamily)...)...)
 | 
			
		||||
	order = append(order, AllCveContetTypes.Except(append(order, Jvn)...)...)
 | 
			
		||||
	for _, ctype := range order {
 | 
			
		||||
		if conts, found := v.CveContents[ctype]; found {
 | 
			
		||||
@@ -464,7 +466,7 @@ func (v VulnInfo) Summaries(lang, myFamily string) (values []CveContentStr) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	order := append(append(GetCveContentTypes(string(Trivy)), GetCveContentTypes(myFamily)...), Fortinet, Nvd, GitHub)
 | 
			
		||||
	order := append(append(GetCveContentTypes(string(Trivy)), GetCveContentTypes(myFamily)...), Fortinet, Nvd, Mitre, GitHub)
 | 
			
		||||
	order = append(order, AllCveContetTypes.Except(append(order, Jvn)...)...)
 | 
			
		||||
	for _, ctype := range order {
 | 
			
		||||
		if conts, found := v.CveContents[ctype]; found {
 | 
			
		||||
@@ -510,7 +512,7 @@ func (v VulnInfo) Summaries(lang, myFamily string) (values []CveContentStr) {
 | 
			
		||||
 | 
			
		||||
// Cvss2Scores returns CVSS V2 Scores
 | 
			
		||||
func (v VulnInfo) Cvss2Scores() (values []CveContentCvss) {
 | 
			
		||||
	order := append([]CveContentType{RedHatAPI, RedHat, Nvd, Jvn}, GetCveContentTypes(string(Trivy))...)
 | 
			
		||||
	order := append([]CveContentType{RedHatAPI, RedHat, Nvd, Mitre, Jvn}, GetCveContentTypes(string(Trivy))...)
 | 
			
		||||
	for _, ctype := range order {
 | 
			
		||||
		if conts, found := v.CveContents[ctype]; found {
 | 
			
		||||
			for _, cont := range conts {
 | 
			
		||||
@@ -535,7 +537,7 @@ func (v VulnInfo) Cvss2Scores() (values []CveContentCvss) {
 | 
			
		||||
 | 
			
		||||
// Cvss3Scores returns CVSS V3 Score
 | 
			
		||||
func (v VulnInfo) Cvss3Scores() (values []CveContentCvss) {
 | 
			
		||||
	order := append([]CveContentType{RedHatAPI, RedHat, SUSE, Microsoft, Fortinet, Nvd, Jvn}, GetCveContentTypes(string(Trivy))...)
 | 
			
		||||
	order := append([]CveContentType{RedHatAPI, RedHat, SUSE, Microsoft, Fortinet, Nvd, Mitre, Jvn}, GetCveContentTypes(string(Trivy))...)
 | 
			
		||||
	for _, ctype := range order {
 | 
			
		||||
		if conts, found := v.CveContents[ctype]; found {
 | 
			
		||||
			for _, cont := range conts {
 | 
			
		||||
@@ -606,9 +608,37 @@ func (v VulnInfo) Cvss3Scores() (values []CveContentCvss) {
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Cvss40Scores returns CVSS V4 Score
 | 
			
		||||
func (v VulnInfo) Cvss40Scores() (values []CveContentCvss) {
 | 
			
		||||
	for _, ctype := range []CveContentType{Mitre} {
 | 
			
		||||
		if conts, found := v.CveContents[ctype]; found {
 | 
			
		||||
			for _, cont := range conts {
 | 
			
		||||
				if cont.Cvss40Score == 0 && cont.Cvss40Severity == "" {
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
				// https://nvd.nist.gov/vuln-metrics/cvss
 | 
			
		||||
				values = append(values, CveContentCvss{
 | 
			
		||||
					Type: ctype,
 | 
			
		||||
					Value: Cvss{
 | 
			
		||||
						Type:     CVSS40,
 | 
			
		||||
						Score:    cont.Cvss40Score,
 | 
			
		||||
						Vector:   cont.Cvss40Vector,
 | 
			
		||||
						Severity: strings.ToUpper(cont.Cvss40Severity),
 | 
			
		||||
					},
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MaxCvssScore returns max CVSS Score
 | 
			
		||||
// If there is no CVSS Score, return Severity as a numerical value.
 | 
			
		||||
func (v VulnInfo) MaxCvssScore() CveContentCvss {
 | 
			
		||||
	v40Max := v.MaxCvss40Score()
 | 
			
		||||
	if v40Max.Type != Unknown {
 | 
			
		||||
		return v40Max
 | 
			
		||||
	}
 | 
			
		||||
	v3Max := v.MaxCvss3Score()
 | 
			
		||||
	if v3Max.Type != Unknown {
 | 
			
		||||
		return v3Max
 | 
			
		||||
@@ -616,6 +646,20 @@ func (v VulnInfo) MaxCvssScore() CveContentCvss {
 | 
			
		||||
	return v.MaxCvss2Score()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MaxCvss40Score returns Max CVSS V4.0 Score
 | 
			
		||||
func (v VulnInfo) MaxCvss40Score() CveContentCvss {
 | 
			
		||||
	max := CveContentCvss{
 | 
			
		||||
		Type:  Unknown,
 | 
			
		||||
		Value: Cvss{Type: CVSS40},
 | 
			
		||||
	}
 | 
			
		||||
	for _, cvss := range v.Cvss40Scores() {
 | 
			
		||||
		if max.Value.Score < cvss.Value.Score {
 | 
			
		||||
			max = cvss
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return max
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MaxCvss3Score returns Max CVSS V3 Score
 | 
			
		||||
func (v VulnInfo) MaxCvss3Score() CveContentCvss {
 | 
			
		||||
	max := CveContentCvss{
 | 
			
		||||
@@ -648,17 +692,14 @@ func (v VulnInfo) MaxCvss2Score() CveContentCvss {
 | 
			
		||||
func (v VulnInfo) AttackVector() string {
 | 
			
		||||
	for _, conts := range v.CveContents {
 | 
			
		||||
		for _, cont := range conts {
 | 
			
		||||
			if strings.HasPrefix(cont.Cvss2Vector, "AV:N") ||
 | 
			
		||||
				strings.Contains(cont.Cvss3Vector, "AV:N") {
 | 
			
		||||
			switch {
 | 
			
		||||
			case strings.HasPrefix(cont.Cvss2Vector, "AV:N") || strings.Contains(cont.Cvss3Vector, "AV:N") || strings.Contains(cont.Cvss40Vector, "AV:N"):
 | 
			
		||||
				return "AV:N"
 | 
			
		||||
			} else if strings.HasPrefix(cont.Cvss2Vector, "AV:A") ||
 | 
			
		||||
				strings.Contains(cont.Cvss3Vector, "AV:A") {
 | 
			
		||||
			case strings.HasPrefix(cont.Cvss2Vector, "AV:A") || strings.Contains(cont.Cvss3Vector, "AV:A") || strings.Contains(cont.Cvss40Vector, "AV:A"):
 | 
			
		||||
				return "AV:A"
 | 
			
		||||
			} else if strings.HasPrefix(cont.Cvss2Vector, "AV:L") ||
 | 
			
		||||
				strings.Contains(cont.Cvss3Vector, "AV:L") {
 | 
			
		||||
			case strings.HasPrefix(cont.Cvss2Vector, "AV:L") || strings.Contains(cont.Cvss3Vector, "AV:L") || strings.Contains(cont.Cvss40Vector, "AV:L"):
 | 
			
		||||
				return "AV:L"
 | 
			
		||||
			} else if strings.Contains(cont.Cvss3Vector, "AV:P") {
 | 
			
		||||
				// no AV:P in CVSS v2
 | 
			
		||||
			case strings.Contains(cont.Cvss3Vector, "AV:P") || strings.Contains(cont.Cvss40Vector, "AV:P"): // no AV:P in CVSS v2
 | 
			
		||||
				return "AV:P"
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@@ -724,6 +765,9 @@ const (
 | 
			
		||||
 | 
			
		||||
	// CVSS3 means CVSS version3
 | 
			
		||||
	CVSS3 CvssType = "3"
 | 
			
		||||
 | 
			
		||||
	// CVSS40 means CVSS version4.0
 | 
			
		||||
	CVSS40 CvssType = "4.0"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Cvss has CVSS Score
 | 
			
		||||
 
 | 
			
		||||
@@ -917,6 +917,50 @@ func TestMaxCvssScores(t *testing.T) {
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		// 6 : CVSSv4.0 and CVSSv3.1
 | 
			
		||||
		{
 | 
			
		||||
			in: VulnInfo{
 | 
			
		||||
				CveContents: CveContents{
 | 
			
		||||
					Mitre: []CveContent{
 | 
			
		||||
						{
 | 
			
		||||
							Type:           Mitre,
 | 
			
		||||
							Cvss40Score:    6.9,
 | 
			
		||||
							Cvss40Vector:   "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N",
 | 
			
		||||
							Cvss40Severity: "MEDIUM",
 | 
			
		||||
							Cvss3Score:     7.3,
 | 
			
		||||
							Cvss3Vector:    "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L",
 | 
			
		||||
							Cvss3Severity:  "HIGH",
 | 
			
		||||
							Optional:       map[string]string{"source": "CNA"},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					Nvd: []CveContent{
 | 
			
		||||
						{
 | 
			
		||||
							Type:          Nvd,
 | 
			
		||||
							Cvss3Score:    9.8,
 | 
			
		||||
							Cvss3Vector:   "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
 | 
			
		||||
							Cvss3Severity: "CRITICAL",
 | 
			
		||||
							Optional:      map[string]string{"source": "nvd@nist.gov"},
 | 
			
		||||
						},
 | 
			
		||||
						{
 | 
			
		||||
							Type:          Nvd,
 | 
			
		||||
							Cvss3Score:    7.3,
 | 
			
		||||
							Cvss3Vector:   "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L",
 | 
			
		||||
							Cvss3Severity: "HIGH",
 | 
			
		||||
							Optional:      map[string]string{"source": "cna@vuldb.com"},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			out: CveContentCvss{
 | 
			
		||||
				Type: Mitre,
 | 
			
		||||
				Value: Cvss{
 | 
			
		||||
					Type:     CVSS40,
 | 
			
		||||
					Score:    6.9,
 | 
			
		||||
					Severity: "MEDIUM",
 | 
			
		||||
					Vector:   "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		// Empty
 | 
			
		||||
		{
 | 
			
		||||
			in: VulnInfo{},
 | 
			
		||||
@@ -1859,3 +1903,109 @@ func TestVulnInfo_PatchStatus(t *testing.T) {
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestVulnInfo_Cvss40Scores(t *testing.T) {
 | 
			
		||||
	type fields struct {
 | 
			
		||||
		CveID       string
 | 
			
		||||
		CveContents CveContents
 | 
			
		||||
	}
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name   string
 | 
			
		||||
		fields fields
 | 
			
		||||
		want   []CveContentCvss
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "happy",
 | 
			
		||||
			fields: fields{
 | 
			
		||||
				CveID: "CVE-2024-5732",
 | 
			
		||||
				CveContents: CveContents{
 | 
			
		||||
					Mitre: []CveContent{
 | 
			
		||||
						{
 | 
			
		||||
							Type:           Mitre,
 | 
			
		||||
							Cvss40Score:    6.9,
 | 
			
		||||
							Cvss40Vector:   "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N",
 | 
			
		||||
							Cvss40Severity: "MEDIUM",
 | 
			
		||||
							Cvss3Score:     7.3,
 | 
			
		||||
							Cvss3Vector:    "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L",
 | 
			
		||||
							Cvss3Severity:  "HIGH",
 | 
			
		||||
							Optional:       map[string]string{"source": "CNA"},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			want: []CveContentCvss{
 | 
			
		||||
				{
 | 
			
		||||
					Type: Mitre,
 | 
			
		||||
					Value: Cvss{
 | 
			
		||||
						Type:     CVSS40,
 | 
			
		||||
						Score:    6.9,
 | 
			
		||||
						Severity: "MEDIUM",
 | 
			
		||||
						Vector:   "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N",
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			if got := (VulnInfo{
 | 
			
		||||
				CveID:       tt.fields.CveID,
 | 
			
		||||
				CveContents: tt.fields.CveContents,
 | 
			
		||||
			}).Cvss40Scores(); !reflect.DeepEqual(got, tt.want) {
 | 
			
		||||
				t.Errorf("VulnInfo.Cvss40Scores() = %v, want %v", got, tt.want)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestVulnInfo_MaxCvss40Score(t *testing.T) {
 | 
			
		||||
	type fields struct {
 | 
			
		||||
		CveID       string
 | 
			
		||||
		CveContents CveContents
 | 
			
		||||
	}
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name   string
 | 
			
		||||
		fields fields
 | 
			
		||||
		want   CveContentCvss
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "happy",
 | 
			
		||||
			fields: fields{
 | 
			
		||||
				CveID: "CVE-2024-5732",
 | 
			
		||||
				CveContents: CveContents{
 | 
			
		||||
					Mitre: []CveContent{
 | 
			
		||||
						{
 | 
			
		||||
							Type:           Mitre,
 | 
			
		||||
							Cvss40Score:    6.9,
 | 
			
		||||
							Cvss40Vector:   "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N",
 | 
			
		||||
							Cvss40Severity: "MEDIUM",
 | 
			
		||||
							Cvss3Score:     7.3,
 | 
			
		||||
							Cvss3Vector:    "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L",
 | 
			
		||||
							Cvss3Severity:  "HIGH",
 | 
			
		||||
							Optional:       map[string]string{"source": "CNA"},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			want: CveContentCvss{
 | 
			
		||||
				Type: Mitre,
 | 
			
		||||
				Value: Cvss{
 | 
			
		||||
					Type:     CVSS40,
 | 
			
		||||
					Score:    6.9,
 | 
			
		||||
					Severity: "MEDIUM",
 | 
			
		||||
					Vector:   "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			if got := (VulnInfo{
 | 
			
		||||
				CveID:       tt.fields.CveID,
 | 
			
		||||
				CveContents: tt.fields.CveContents,
 | 
			
		||||
			}).MaxCvss40Score(); !reflect.DeepEqual(got, tt.want) {
 | 
			
		||||
				t.Errorf("VulnInfo.MaxsCvss40Score() = %v, want %v", got, tt.want)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -424,6 +424,9 @@ func cdxRatings(cveContents models.CveContents) *[]cdx.VulnerabilityRating {
 | 
			
		||||
			if content.Cvss3Score != 0 || content.Cvss3Vector != "" || content.Cvss3Severity != "" {
 | 
			
		||||
				ratings = append(ratings, cdxCVSS3Rating(string(content.Type), content.Cvss3Vector, content.Cvss3Score, content.Cvss3Severity))
 | 
			
		||||
			}
 | 
			
		||||
			if content.Cvss40Score != 0 || content.Cvss40Vector != "" || content.Cvss40Severity != "" {
 | 
			
		||||
				ratings = append(ratings, cdxCVSS40Rating(string(content.Type), content.Cvss40Vector, content.Cvss40Score, content.Cvss40Severity))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return &ratings
 | 
			
		||||
@@ -480,6 +483,32 @@ func cdxCVSS3Rating(source, vector string, score float64, severity string) cdx.V
 | 
			
		||||
	return r
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func cdxCVSS40Rating(source, vector string, score float64, severity string) cdx.VulnerabilityRating {
 | 
			
		||||
	r := cdx.VulnerabilityRating{
 | 
			
		||||
		Source: &cdx.Source{Name: source},
 | 
			
		||||
		Method: cdx.ScoringMethodCVSSv4,
 | 
			
		||||
		Vector: vector,
 | 
			
		||||
	}
 | 
			
		||||
	if score != 0 {
 | 
			
		||||
		r.Score = &score
 | 
			
		||||
	}
 | 
			
		||||
	switch strings.ToLower(severity) {
 | 
			
		||||
	case "critical":
 | 
			
		||||
		r.Severity = cdx.SeverityCritical
 | 
			
		||||
	case "high":
 | 
			
		||||
		r.Severity = cdx.SeverityHigh
 | 
			
		||||
	case "medium":
 | 
			
		||||
		r.Severity = cdx.SeverityMedium
 | 
			
		||||
	case "low":
 | 
			
		||||
		r.Severity = cdx.SeverityLow
 | 
			
		||||
	case "none":
 | 
			
		||||
		r.Severity = cdx.SeverityNone
 | 
			
		||||
	default:
 | 
			
		||||
		r.Severity = cdx.SeverityUnknown
 | 
			
		||||
	}
 | 
			
		||||
	return r
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func cdxAffects(cve models.VulnInfo, ospkgToPURL map[string]string, libpkgToPURL, ghpkgToPURL map[string]map[string]string, wppkgToPURL map[string]string) *[]cdx.Affects {
 | 
			
		||||
	affects := make([]cdx.Affects, 0, len(cve.AffectedPackages)+len(cve.CpeURIs)+len(cve.LibraryFixedIns)+len(cve.WpPackageFixStats))
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -253,7 +253,7 @@ func (w SlackWriter) attachmentText(vinfo models.VulnInfo, cweDict map[string]mo
 | 
			
		||||
	maxCvss := vinfo.MaxCvssScore()
 | 
			
		||||
	vectors := []string{}
 | 
			
		||||
 | 
			
		||||
	scores := append(vinfo.Cvss3Scores(), vinfo.Cvss2Scores()...)
 | 
			
		||||
	scores := append(vinfo.Cvss40Scores(), append(vinfo.Cvss3Scores(), vinfo.Cvss2Scores()...)...)
 | 
			
		||||
	for _, cvss := range scores {
 | 
			
		||||
		if cvss.Value.Severity == "" {
 | 
			
		||||
			continue
 | 
			
		||||
@@ -268,6 +268,8 @@ func (w SlackWriter) attachmentText(vinfo models.VulnInfo, cweDict map[string]mo
 | 
			
		||||
			calcURL = fmt.Sprintf(
 | 
			
		||||
				"https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?name=%s",
 | 
			
		||||
				vinfo.CveID)
 | 
			
		||||
		case models.CVSS40:
 | 
			
		||||
			calcURL = fmt.Sprintf("https://www.first.org/cvss/calculator/4.0#%s", cvss.Value.Vector)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if conts, ok := vinfo.CveContents[cvss.Type]; ok {
 | 
			
		||||
 
 | 
			
		||||
@@ -73,6 +73,11 @@ func (w SyslogWriter) encodeSyslog(result models.ScanResult) (messages []string)
 | 
			
		||||
			kvPairs = append(kvPairs, fmt.Sprintf(`cvss_vector_%s_v3="%s"`, cvss.Type, cvss.Value.Vector))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, cvss := range vinfo.Cvss40Scores() {
 | 
			
		||||
			kvPairs = append(kvPairs, fmt.Sprintf(`cvss_score_%s_v40="%.2f"`, cvss.Type, cvss.Value.Score))
 | 
			
		||||
			kvPairs = append(kvPairs, fmt.Sprintf(`cvss_vector_%s_v40="%s"`, cvss.Type, cvss.Value.Vector))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if conts, ok := vinfo.CveContents[models.Nvd]; ok {
 | 
			
		||||
			for _, cont := range conts {
 | 
			
		||||
				cwes := strings.Join(cont.CweIDs, ",")
 | 
			
		||||
 
 | 
			
		||||
@@ -337,18 +337,26 @@ No CVE-IDs are found in updatable packages.
 | 
			
		||||
	for _, vuln := range r.ScannedCves.ToSortedSlice() {
 | 
			
		||||
		data := [][]string{}
 | 
			
		||||
		data = append(data, []string{"Max Score", vuln.FormatMaxCvssScore()})
 | 
			
		||||
		for _, cvss := range vuln.Cvss40Scores() {
 | 
			
		||||
			if cvssstr := cvss.Value.Format(); cvssstr != "" {
 | 
			
		||||
				data = append(data, []string{string(cvss.Type), cvssstr})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		for _, cvss := range vuln.Cvss3Scores() {
 | 
			
		||||
			if cvssstr := cvss.Value.Format(); cvssstr != "" {
 | 
			
		||||
				data = append(data, []string{string(cvss.Type), cvssstr})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, cvss := range vuln.Cvss2Scores() {
 | 
			
		||||
			if cvssstr := cvss.Value.Format(); cvssstr != "" {
 | 
			
		||||
				data = append(data, []string{string(cvss.Type), cvssstr})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, ssvc := range vuln.CveContents.SSVC() {
 | 
			
		||||
			data = append(data, []string{fmt.Sprintf("SSVC[%s]", ssvc.Type), fmt.Sprintf("Exploitation    : %s\nAutomatable     : %s\nTechnicalImpact : %s", ssvc.Value.Exploitation, ssvc.Value.Automatable, ssvc.Value.TechnicalImpact)})
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		data = append(data, []string{"Summary", vuln.Summaries(
 | 
			
		||||
			r.Lang, r.Family)[0].Value})
 | 
			
		||||
 | 
			
		||||
@@ -770,7 +778,7 @@ func getMinusDiffCves(previous, current models.ScanResult) models.VulnInfos {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isCveInfoUpdated(cveID string, previous, current models.ScanResult) bool {
 | 
			
		||||
	cTypes := append([]models.CveContentType{models.Nvd, models.Jvn}, models.GetCveContentTypes(current.Family)...)
 | 
			
		||||
	cTypes := append([]models.CveContentType{models.Mitre, models.Nvd, models.Jvn}, models.GetCveContentTypes(current.Family)...)
 | 
			
		||||
 | 
			
		||||
	prevLastModifieds := map[models.CveContentType][]time.Time{}
 | 
			
		||||
	preVinfo, ok := previous.ScannedCves[cveID]
 | 
			
		||||
 
 | 
			
		||||
@@ -76,7 +76,7 @@ func (h VulsHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	logging.Log.Infof("Fill CVE detailed with CVE-DB")
 | 
			
		||||
	if err := detector.FillCvesWithNvdJvnFortinet(&r, config.Conf.CveDict, config.Conf.LogOpts); err != nil {
 | 
			
		||||
	if err := detector.FillCvesWithGoCVEDictionary(&r, config.Conf.CveDict, config.Conf.LogOpts); err != nil {
 | 
			
		||||
		logging.Log.Errorf("Failed to fill with CVE: %+v", err)
 | 
			
		||||
		http.Error(w, err.Error(), http.StatusServiceUnavailable)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								tui/tui.go
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								tui/tui.go
									
									
									
									
									
								
							@@ -899,6 +899,7 @@ func setChangelogLayout(g *gocui.Gui) error {
 | 
			
		||||
type dataForTmpl struct {
 | 
			
		||||
	CveID            string
 | 
			
		||||
	Cvsses           string
 | 
			
		||||
	SSVC             []models.CveContentSSVC
 | 
			
		||||
	Exploits         []models.Exploit
 | 
			
		||||
	Metasploits      []models.Metasploit
 | 
			
		||||
	Summary          string
 | 
			
		||||
@@ -979,7 +980,7 @@ func detailLines() (string, error) {
 | 
			
		||||
	table := uitable.New()
 | 
			
		||||
	table.MaxColWidth = 100
 | 
			
		||||
	table.Wrap = true
 | 
			
		||||
	scores := append(vinfo.Cvss3Scores(), vinfo.Cvss2Scores()...)
 | 
			
		||||
	scores := append(vinfo.Cvss40Scores(), append(vinfo.Cvss3Scores(), vinfo.Cvss2Scores()...)...)
 | 
			
		||||
	var cols []interface{}
 | 
			
		||||
	for _, score := range scores {
 | 
			
		||||
		cols = []interface{}{
 | 
			
		||||
@@ -1002,6 +1003,7 @@ func detailLines() (string, error) {
 | 
			
		||||
	data := dataForTmpl{
 | 
			
		||||
		CveID:       vinfo.CveID,
 | 
			
		||||
		Cvsses:      fmt.Sprintf("%s\n", table),
 | 
			
		||||
		SSVC:        vinfo.CveContents.SSVC(),
 | 
			
		||||
		Summary:     fmt.Sprintf("%s (%s)", summary.Value, summary.Type),
 | 
			
		||||
		Mitigation:  strings.Join(mitigations, "\n"),
 | 
			
		||||
		PatchURLs:   vinfo.CveContents.PatchURLs(),
 | 
			
		||||
@@ -1027,6 +1029,17 @@ CVSS Scores
 | 
			
		||||
-----------
 | 
			
		||||
{{.Cvsses }}
 | 
			
		||||
 | 
			
		||||
{{if .SSVC}}
 | 
			
		||||
SSVC
 | 
			
		||||
-----------
 | 
			
		||||
{{range $ssvc := .SSVC -}}
 | 
			
		||||
* {{$ssvc.Type}}
 | 
			
		||||
  Exploitation    : {{$ssvc.Value.Exploitation}}
 | 
			
		||||
  Automatable     : {{$ssvc.Value.Automatable}}
 | 
			
		||||
  TechnicalImpact : {{$ssvc.Value.TechnicalImpact}}
 | 
			
		||||
{{end}}
 | 
			
		||||
{{end}}
 | 
			
		||||
 | 
			
		||||
Summary
 | 
			
		||||
-----------
 | 
			
		||||
 {{.Summary }}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user