Change models structure
This commit is contained in:
		
							
								
								
									
										28
									
								
								Gopkg.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										28
									
								
								Gopkg.lock
									
									
									
										generated
									
									
									
								
							@@ -4,13 +4,13 @@ memo = "bd95ed8c2b0aa32327ae55d88bff888b8198d238f7a71eee0f8663494664a0ac"
 | 
			
		||||
  branch = "master"
 | 
			
		||||
  name = "github.com/Azure/azure-storage-go"
 | 
			
		||||
  packages = ["."]
 | 
			
		||||
  revision = "12ccaadb081cdd217702067d28da9a7ff4305239"
 | 
			
		||||
  revision = "4fe73b0b4f68bf8a7cad2920ef563fe4c40ac5c0"
 | 
			
		||||
 | 
			
		||||
[[projects]]
 | 
			
		||||
  name = "github.com/Azure/go-autorest"
 | 
			
		||||
  packages = ["autorest","autorest/azure","autorest/date"]
 | 
			
		||||
  revision = "a2fdd780c9a50455cecd249b00bdc3eb73a78e31"
 | 
			
		||||
  version = "v7.3.1"
 | 
			
		||||
  packages = ["autorest","autorest/adal","autorest/azure","autorest/date"]
 | 
			
		||||
  revision = "58f6f26e200fa5dfb40c9cd1c83f3e2c860d779d"
 | 
			
		||||
  version = "v8.0.0"
 | 
			
		||||
 | 
			
		||||
[[projects]]
 | 
			
		||||
  name = "github.com/BurntSushi/toml"
 | 
			
		||||
@@ -22,7 +22,7 @@ memo = "bd95ed8c2b0aa32327ae55d88bff888b8198d238f7a71eee0f8663494664a0ac"
 | 
			
		||||
  branch = "master"
 | 
			
		||||
  name = "github.com/Sirupsen/logrus"
 | 
			
		||||
  packages = ["."]
 | 
			
		||||
  revision = "10f801ebc38b33738c9d17d50860f484a0988ff5"
 | 
			
		||||
  revision = "508f304878257fb578be3e863e3990ed9ec3aa2e"
 | 
			
		||||
 | 
			
		||||
[[projects]]
 | 
			
		||||
  name = "github.com/asaskevich/govalidator"
 | 
			
		||||
@@ -141,7 +141,7 @@ memo = "bd95ed8c2b0aa32327ae55d88bff888b8198d238f7a71eee0f8663494664a0ac"
 | 
			
		||||
  branch = "master"
 | 
			
		||||
  name = "github.com/kotakanbe/goval-dictionary"
 | 
			
		||||
  packages = ["config","db","log","models"]
 | 
			
		||||
  revision = "5470d7565a9de51593f53327ce14c97d466b05ab"
 | 
			
		||||
  revision = "545199055508ae62a6d3bd34ef83034fbfc04d7f"
 | 
			
		||||
 | 
			
		||||
[[projects]]
 | 
			
		||||
  branch = "master"
 | 
			
		||||
@@ -221,6 +221,12 @@ memo = "bd95ed8c2b0aa32327ae55d88bff888b8198d238f7a71eee0f8663494664a0ac"
 | 
			
		||||
  revision = "2adb3e0c4ddd8778c4adde609d2dfd4fbe6096ea"
 | 
			
		||||
  version = "1.6"
 | 
			
		||||
 | 
			
		||||
[[projects]]
 | 
			
		||||
  name = "github.com/satori/uuid"
 | 
			
		||||
  packages = ["."]
 | 
			
		||||
  revision = "879c5887cd475cd7864858769793b2ceb0d44feb"
 | 
			
		||||
  version = "v1.1.0"
 | 
			
		||||
 | 
			
		||||
[[projects]]
 | 
			
		||||
  branch = "master"
 | 
			
		||||
  name = "github.com/valyala/bytebufferpool"
 | 
			
		||||
@@ -237,28 +243,28 @@ memo = "bd95ed8c2b0aa32327ae55d88bff888b8198d238f7a71eee0f8663494664a0ac"
 | 
			
		||||
  branch = "master"
 | 
			
		||||
  name = "github.com/ymomoi/goval-parser"
 | 
			
		||||
  packages = ["oval"]
 | 
			
		||||
  revision = "4ddf6fc4f1a1af026f7cae41f76979c7ff2b2e2f"
 | 
			
		||||
  revision = "003ac9af5fffac6c97ab1def025d2cb73e88469a"
 | 
			
		||||
 | 
			
		||||
[[projects]]
 | 
			
		||||
  branch = "master"
 | 
			
		||||
  name = "golang.org/x/crypto"
 | 
			
		||||
  packages = ["curve25519","ed25519","ed25519/internal/edwards25519","ssh","ssh/agent","ssh/terminal"]
 | 
			
		||||
  revision = "c7af5bf2638a1164f2eb5467c39c6cffbd13a02e"
 | 
			
		||||
  revision = "04eae0b62feaaf659a0ce2c4e8dc70b6ae2fff67"
 | 
			
		||||
 | 
			
		||||
[[projects]]
 | 
			
		||||
  branch = "master"
 | 
			
		||||
  name = "golang.org/x/net"
 | 
			
		||||
  packages = ["context","idna","publicsuffix"]
 | 
			
		||||
  revision = "da118f7b8e5954f39d0d2130ab35d4bf0e3cb344"
 | 
			
		||||
  revision = "feeb485667d1fdabe727840fe00adc22431bc86e"
 | 
			
		||||
 | 
			
		||||
[[projects]]
 | 
			
		||||
  branch = "master"
 | 
			
		||||
  name = "golang.org/x/sys"
 | 
			
		||||
  packages = ["unix"]
 | 
			
		||||
  revision = "9f30dcbe5be197894515a338a9bda9253567ea8f"
 | 
			
		||||
  revision = "9ccfe848b9db8435a24c424abbc07a921adf1df5"
 | 
			
		||||
 | 
			
		||||
[[projects]]
 | 
			
		||||
  branch = "master"
 | 
			
		||||
  name = "golang.org/x/text"
 | 
			
		||||
  packages = ["internal/gen","internal/triegen","internal/ucd","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"]
 | 
			
		||||
  revision = "a9a820217f98f7c8a207ec1e45a874e1fe12c478"
 | 
			
		||||
  revision = "470f45bf29f4147d6fbd7dfd0a02a848e49f5bf4"
 | 
			
		||||
 
 | 
			
		||||
@@ -422,7 +422,6 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
 | 
			
		||||
				util.Log.Errorf("Failed to fill OVAL information: %s", err)
 | 
			
		||||
				return subcommands.ExitFailure
 | 
			
		||||
			}
 | 
			
		||||
			pp.Println(filled)
 | 
			
		||||
 | 
			
		||||
			filled, err = fillCveInfoFromCveDB(*filled)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
@@ -463,6 +462,13 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
 | 
			
		||||
 | 
			
		||||
	var res models.ScanResults
 | 
			
		||||
	for _, r := range results {
 | 
			
		||||
		//TODO remove
 | 
			
		||||
		for _, vuln := range r.ScannedCves {
 | 
			
		||||
			if _, ok := vuln.CveContents.Get(models.CveContentType(r.Family)); !ok {
 | 
			
		||||
				fmt.Println("not in oval")
 | 
			
		||||
				pp.Println(vuln)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		res = append(res, r.FilterByCvssOver())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -231,8 +231,9 @@ func diff(current, previous models.ScanResults) (diff models.ScanResults, err er
 | 
			
		||||
		if found {
 | 
			
		||||
			currentResult.ScannedCves = getNewCves(previousResult, currentResult)
 | 
			
		||||
 | 
			
		||||
			currentResult.KnownCves = []models.CveInfo{}
 | 
			
		||||
			currentResult.UnknownCves = []models.CveInfo{}
 | 
			
		||||
			//TODO
 | 
			
		||||
			//  currentResult.KnownCves = []models.CveInfo{}
 | 
			
		||||
			//  currentResult.UnknownCves = []models.CveInfo{}
 | 
			
		||||
 | 
			
		||||
			currentResult.Packages = models.PackageInfoList{}
 | 
			
		||||
			for _, s := range currentResult.ScannedCves {
 | 
			
		||||
@@ -270,27 +271,28 @@ func isCveInfoUpdated(current, previous models.ScanResult, CveID string) bool {
 | 
			
		||||
		Jvn time.Time
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//TODO
 | 
			
		||||
	previousModifies := lastModified{}
 | 
			
		||||
	for _, c := range previous.KnownCves {
 | 
			
		||||
	for _, c := range previous.ScannedCves {
 | 
			
		||||
		if CveID == c.CveID {
 | 
			
		||||
			//TODO
 | 
			
		||||
			if nvd, found := c.Get(models.NVD); found {
 | 
			
		||||
			if nvd, found := c.CveContents.Get(models.NVD); found {
 | 
			
		||||
				previousModifies.Nvd = nvd.LastModified
 | 
			
		||||
			}
 | 
			
		||||
			if jvn, found := c.Get(models.JVN); found {
 | 
			
		||||
			if jvn, found := c.CveContents.Get(models.JVN); found {
 | 
			
		||||
				previousModifies.Jvn = jvn.LastModified
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	currentModifies := lastModified{}
 | 
			
		||||
	for _, c := range current.KnownCves {
 | 
			
		||||
		if CveID == c.VulnInfo.CveID {
 | 
			
		||||
	for _, c := range current.ScannedCves {
 | 
			
		||||
		if CveID == c.CveID {
 | 
			
		||||
			//TODO
 | 
			
		||||
			if nvd, found := c.Get(models.NVD); found {
 | 
			
		||||
			if nvd, found := c.CveContents.Get(models.NVD); found {
 | 
			
		||||
				previousModifies.Nvd = nvd.LastModified
 | 
			
		||||
			}
 | 
			
		||||
			if jvn, found := c.Get(models.JVN); found {
 | 
			
		||||
			if jvn, found := c.CveContents.Get(models.JVN); found {
 | 
			
		||||
				previousModifies.Jvn = jvn.LastModified
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@@ -352,7 +354,14 @@ func scanVulnByCpeNames(cpeNames []string, scannedVulns []models.VulnInfo) ([]mo
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func needToRefreshCve(r models.ScanResult) bool {
 | 
			
		||||
	return r.Lang != c.Conf.Lang || len(r.KnownCves) == 0 &&
 | 
			
		||||
		len(r.UnknownCves) == 0 &&
 | 
			
		||||
		len(r.IgnoredCves) == 0
 | 
			
		||||
	if r.Lang != c.Conf.Lang {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, cve := range r.ScannedCves {
 | 
			
		||||
		if 0 < len(cve.CveContents) {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -69,6 +69,7 @@ type response struct {
 | 
			
		||||
	CveDetail cve.CveDetail
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//TODO rename to FetchCveDictionary
 | 
			
		||||
func (api cvedictClient) FetchCveDetails(cveIDs []string) (cveDetails cve.CveDetails, err error) {
 | 
			
		||||
	switch config.Conf.CveDBType {
 | 
			
		||||
	case "sqlite3", "mysql", "postgres":
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										515
									
								
								models/models.go
									
									
									
									
									
								
							
							
						
						
									
										515
									
								
								models/models.go
									
									
									
									
									
								
							@@ -60,25 +60,19 @@ type ScanResult struct {
 | 
			
		||||
	Container  Container
 | 
			
		||||
	Platform   Platform
 | 
			
		||||
 | 
			
		||||
	// Scanned Vulns via SSH + CPE Vulns
 | 
			
		||||
	ScannedCves []VulnInfo
 | 
			
		||||
 | 
			
		||||
	KnownCves   CveInfos
 | 
			
		||||
	UnknownCves CveInfos
 | 
			
		||||
	IgnoredCves CveInfos
 | 
			
		||||
	// Scanned Vulns by SSH scan + CPE + OVAL
 | 
			
		||||
	ScannedCves VulnInfos
 | 
			
		||||
 | 
			
		||||
	Packages PackageInfoList
 | 
			
		||||
 | 
			
		||||
	Errors   []string
 | 
			
		||||
	Optional [][]interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FillCveDetail fetches NVD, JVN from CVE Database, and then set to fields.
 | 
			
		||||
//TODO rename to FillCveDictionary
 | 
			
		||||
func (r ScanResult) FillCveDetail() (*ScanResult, error) {
 | 
			
		||||
	set := map[string]VulnInfo{}
 | 
			
		||||
	var cveIDs []string
 | 
			
		||||
	for _, v := range r.ScannedCves {
 | 
			
		||||
		set[v.CveID] = v
 | 
			
		||||
		cveIDs = append(cveIDs, v.CveID)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -86,64 +80,24 @@ func (r ScanResult) FillCveDetail() (*ScanResult, error) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r.IgnoredCves = CveInfos{}
 | 
			
		||||
	for _, d := range ds {
 | 
			
		||||
		nvd := *r.convertNvdToModel(d.CveID, d.Nvd)
 | 
			
		||||
		jvn := *r.convertJvnToModel(d.CveID, d.Jvn)
 | 
			
		||||
		cinfo := CveInfo{
 | 
			
		||||
			CveContents: []CveContent{nvd, jvn},
 | 
			
		||||
			VulnInfo:    set[d.CveID],
 | 
			
		||||
		}
 | 
			
		||||
		cinfo.NilSliceToEmpty()
 | 
			
		||||
 | 
			
		||||
		// ignored
 | 
			
		||||
		ignore := false
 | 
			
		||||
		for _, icve := range config.Conf.Servers[r.ServerName].IgnoreCves {
 | 
			
		||||
			if icve == d.CveID {
 | 
			
		||||
				r.IgnoredCves.Insert(cinfo)
 | 
			
		||||
				ignore = true
 | 
			
		||||
		for i, sc := range r.ScannedCves {
 | 
			
		||||
			if sc.CveID == d.CveID {
 | 
			
		||||
				for _, con := range []CveContent{nvd, jvn} {
 | 
			
		||||
					if !con.Empty() {
 | 
			
		||||
						r.ScannedCves[i].CveContents.Upsert(con)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if ignore {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Update known if KnownCves already have cinfo
 | 
			
		||||
		if c, ok := r.KnownCves.Get(cinfo.CveID); ok {
 | 
			
		||||
			for _, con := range []CveContent{nvd, jvn} {
 | 
			
		||||
				if !c.Update(con) {
 | 
			
		||||
					c.Insert(con)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			r.KnownCves.Update(c)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Update unknown if UnknownCves already have cinfo
 | 
			
		||||
		if c, ok := r.UnknownCves.Get(cinfo.CveID); ok {
 | 
			
		||||
			for _, con := range []CveContent{nvd, jvn} {
 | 
			
		||||
				if !c.Update(con) {
 | 
			
		||||
					c.Insert(con)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			r.UnknownCves.Update(c)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// unknown
 | 
			
		||||
		if d.CvssScore(config.Conf.Lang) <= 0 {
 | 
			
		||||
			r.UnknownCves.Insert(cinfo)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// known
 | 
			
		||||
		r.KnownCves.Insert(cinfo)
 | 
			
		||||
	}
 | 
			
		||||
	sort.Sort(r.KnownCves)
 | 
			
		||||
	sort.Sort(r.UnknownCves)
 | 
			
		||||
	sort.Sort(r.IgnoredCves)
 | 
			
		||||
	//TODO sort
 | 
			
		||||
	//  sort.Sort(r.KnownCves)
 | 
			
		||||
	//  sort.Sort(r.UnknownCves)
 | 
			
		||||
	//  sort.Sort(r.IgnoredCves)
 | 
			
		||||
	return &r, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -236,19 +190,21 @@ func (r ScanResult) convertJvnToModel(cveID string, jvn cvedict.Jvn) *CveContent
 | 
			
		||||
 | 
			
		||||
// FilterByCvssOver is filter function.
 | 
			
		||||
func (r ScanResult) FilterByCvssOver() ScanResult {
 | 
			
		||||
	cveInfos := []CveInfo{}
 | 
			
		||||
	// TODO: Set correct default value
 | 
			
		||||
	if config.Conf.CvssScoreOver == 0 {
 | 
			
		||||
		config.Conf.CvssScoreOver = -1.1
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, cveInfo := range r.KnownCves {
 | 
			
		||||
		if config.Conf.CvssScoreOver <= cveInfo.CvssV2Score() {
 | 
			
		||||
			cveInfos = append(cveInfos, cveInfo)
 | 
			
		||||
	// TODO: Filter by ignore cves???
 | 
			
		||||
	filtered := VulnInfos{}
 | 
			
		||||
	for _, sc := range r.ScannedCves {
 | 
			
		||||
		if config.Conf.CvssScoreOver <= sc.CveContents.CvssV2Score() {
 | 
			
		||||
			filtered = append(filtered, sc)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	r.KnownCves = cveInfos
 | 
			
		||||
	return r
 | 
			
		||||
	copiedScanResult := r
 | 
			
		||||
	copiedScanResult.ScannedCves = filtered
 | 
			
		||||
	return copiedScanResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReportFileName returns the filename on localhost without extention
 | 
			
		||||
@@ -311,9 +267,8 @@ func (r ScanResult) FormatServerName() string {
 | 
			
		||||
// CveSummary summarize the number of CVEs group by CVSSv2 Severity
 | 
			
		||||
func (r ScanResult) CveSummary() string {
 | 
			
		||||
	var high, medium, low, unknown int
 | 
			
		||||
	cves := append(r.KnownCves, r.UnknownCves...)
 | 
			
		||||
	for _, cveInfo := range cves {
 | 
			
		||||
		score := cveInfo.CvssV2Score()
 | 
			
		||||
	for _, vInfo := range r.ScannedCves {
 | 
			
		||||
		score := vInfo.CveContents.CvssV2Score()
 | 
			
		||||
		switch {
 | 
			
		||||
		case 7.0 <= score:
 | 
			
		||||
			high++
 | 
			
		||||
@@ -334,18 +289,14 @@ func (r ScanResult) CveSummary() string {
 | 
			
		||||
		high+medium+low+unknown, high, medium, low, unknown)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AllCves returns Known and Unknown CVEs
 | 
			
		||||
func (r ScanResult) AllCves() []CveInfo {
 | 
			
		||||
	return append(r.KnownCves, r.UnknownCves...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NWLink has network link information.
 | 
			
		||||
type NWLink struct {
 | 
			
		||||
	IPAddress string
 | 
			
		||||
	Netmask   string
 | 
			
		||||
	DevName   string
 | 
			
		||||
	LinkState string
 | 
			
		||||
}
 | 
			
		||||
//TODO remove
 | 
			
		||||
//  type NWLink struct {
 | 
			
		||||
//      IPAddress string
 | 
			
		||||
//      Netmask   string
 | 
			
		||||
//      DevName   string
 | 
			
		||||
//      LinkState string
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
// Confidence is a ranking how confident the CVE-ID was deteted correctly
 | 
			
		||||
// Score: 0 - 100
 | 
			
		||||
@@ -405,6 +356,89 @@ var ChangelogLenientMatch = Confidence{50, ChangelogLenientMatchStr}
 | 
			
		||||
// VulnInfos is VulnInfo list, getter/setter, sortable methods.
 | 
			
		||||
type VulnInfos []VulnInfo
 | 
			
		||||
 | 
			
		||||
// FindByCveID find by CVEID
 | 
			
		||||
// TODO remove
 | 
			
		||||
//  func (v *VulnInfos) FindByCveID(cveID string) (VulnInfo, bool) {
 | 
			
		||||
//      for _, p := range s {
 | 
			
		||||
//          if cveID == p.CveID {
 | 
			
		||||
//              return p, true
 | 
			
		||||
//          }
 | 
			
		||||
//      }
 | 
			
		||||
//      return VulnInfo{CveID: cveID}, false
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
// Get VulnInfo by cveID
 | 
			
		||||
func (v *VulnInfos) Get(cveID string) (VulnInfo, bool) {
 | 
			
		||||
	for _, vv := range *v {
 | 
			
		||||
		if vv.CveID == cveID {
 | 
			
		||||
			return vv, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return VulnInfo{}, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete by cveID
 | 
			
		||||
func (v *VulnInfos) Delete(cveID string) {
 | 
			
		||||
	vInfos := *v
 | 
			
		||||
	for i, vv := range vInfos {
 | 
			
		||||
		if vv.CveID == cveID {
 | 
			
		||||
			*v = append(vInfos[:i], vInfos[i+1:]...)
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Insert VulnInfo
 | 
			
		||||
func (v *VulnInfos) Insert(vinfo VulnInfo) {
 | 
			
		||||
	*v = append(*v, vinfo)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update VulnInfo
 | 
			
		||||
func (v *VulnInfos) Update(vInfo VulnInfo) (ok bool) {
 | 
			
		||||
	for i, vv := range *v {
 | 
			
		||||
		if vv.CveID == vInfo.CveID {
 | 
			
		||||
			(*v)[i] = vInfo
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Upsert cveInfo
 | 
			
		||||
func (v *VulnInfos) Upsert(vInfo VulnInfo) {
 | 
			
		||||
	ok := v.Update(vInfo)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		v.Insert(vInfo)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// immutable
 | 
			
		||||
//  func (v *VulnInfos) set(cveID string, v VulnInfo) VulnInfos {
 | 
			
		||||
//      for i, p := range s {
 | 
			
		||||
//          if cveID == p.CveID {
 | 
			
		||||
//              s[i] = v
 | 
			
		||||
//              return s
 | 
			
		||||
//          }
 | 
			
		||||
//      }
 | 
			
		||||
//      return append(s, v)
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
//TODO GO 1.8
 | 
			
		||||
// Len implement Sort Interface
 | 
			
		||||
//  func (s VulnInfos) Len() int {
 | 
			
		||||
//      return len(s)
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
//  // Swap implement Sort Interface
 | 
			
		||||
//  func (s VulnInfos) Swap(i, j int) {
 | 
			
		||||
//      s[i], s[j] = s[j], s[i]
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
//  // Less implement Sort Interface
 | 
			
		||||
//  func (s VulnInfos) Less(i, j int) bool {
 | 
			
		||||
//      return s[i].CveID < s[j].CveID
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
// VulnInfo holds a vulnerability information and unsecure packages
 | 
			
		||||
type VulnInfo struct {
 | 
			
		||||
	CveID            string
 | 
			
		||||
@@ -412,6 +446,7 @@ type VulnInfo struct {
 | 
			
		||||
	Packages         PackageInfoList
 | 
			
		||||
	DistroAdvisories []DistroAdvisory // for Aamazon, RHEL, FreeBSD
 | 
			
		||||
	CpeNames         []string
 | 
			
		||||
	CveContents      CveContents
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NilSliceToEmpty set nil slice fields to empty slice to avoid null in JSON
 | 
			
		||||
@@ -427,167 +462,132 @@ func (v *VulnInfo) NilSliceToEmpty() {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FindByCveID find by CVEID
 | 
			
		||||
func (s VulnInfos) FindByCveID(cveID string) (VulnInfo, bool) {
 | 
			
		||||
	for _, p := range s {
 | 
			
		||||
		if cveID == p.CveID {
 | 
			
		||||
			return p, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return VulnInfo{CveID: cveID}, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// immutable
 | 
			
		||||
func (s VulnInfos) set(cveID string, v VulnInfo) VulnInfos {
 | 
			
		||||
	for i, p := range s {
 | 
			
		||||
		if cveID == p.CveID {
 | 
			
		||||
			s[i] = v
 | 
			
		||||
			return s
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return append(s, v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Len implement Sort Interface
 | 
			
		||||
func (s VulnInfos) Len() int {
 | 
			
		||||
	return len(s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Swap implement Sort Interface
 | 
			
		||||
func (s VulnInfos) Swap(i, j int) {
 | 
			
		||||
	s[i], s[j] = s[j], s[i]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Less implement Sort Interface
 | 
			
		||||
func (s VulnInfos) Less(i, j int) bool {
 | 
			
		||||
	return s[i].CveID < s[j].CveID
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CveInfos is for sorting
 | 
			
		||||
type CveInfos []CveInfo
 | 
			
		||||
//  type CveInfos []CveInfo
 | 
			
		||||
 | 
			
		||||
func (c CveInfos) Len() int {
 | 
			
		||||
	return len(c)
 | 
			
		||||
}
 | 
			
		||||
//  func (c CveInfos) Len() int {
 | 
			
		||||
//      return len(c)
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
func (c CveInfos) Swap(i, j int) {
 | 
			
		||||
	c[i], c[j] = c[j], c[i]
 | 
			
		||||
}
 | 
			
		||||
//  func (c CveInfos) Swap(i, j int) {
 | 
			
		||||
//      c[i], c[j] = c[j], c[i]
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
func (c CveInfos) Less(i, j int) bool {
 | 
			
		||||
	if c[i].CvssV2Score() == c[j].CvssV2Score() {
 | 
			
		||||
		return c[i].CveID < c[j].CveID
 | 
			
		||||
	}
 | 
			
		||||
	return c[j].CvssV2Score() < c[i].CvssV2Score()
 | 
			
		||||
}
 | 
			
		||||
//  func (c CveInfos) Less(i, j int) bool {
 | 
			
		||||
//      if c[i].CvssV2Score() == c[j].CvssV2Score() {
 | 
			
		||||
//          return c[i].CveID < c[j].CveID
 | 
			
		||||
//      }
 | 
			
		||||
//      return c[j].CvssV2Score() < c[i].CvssV2Score()
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
// Get cveInfo by cveID
 | 
			
		||||
func (c CveInfos) Get(cveID string) (CveInfo, bool) {
 | 
			
		||||
	for _, cve := range c {
 | 
			
		||||
		if cve.VulnInfo.CveID == cveID {
 | 
			
		||||
			return cve, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return CveInfo{}, false
 | 
			
		||||
}
 | 
			
		||||
//  // Get cveInfo by cveID
 | 
			
		||||
//  func (c CveInfos) Get(cveID string) (CveInfo, bool) {
 | 
			
		||||
//      for _, cve := range c {
 | 
			
		||||
//          if cve.VulnInfo.CveID == cveID {
 | 
			
		||||
//              return cve, true
 | 
			
		||||
//          }
 | 
			
		||||
//      }
 | 
			
		||||
//      return CveInfo{}, false
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
// Delete by cveID
 | 
			
		||||
func (c *CveInfos) Delete(cveID string) {
 | 
			
		||||
	cveInfos := *c
 | 
			
		||||
	for i, cve := range cveInfos {
 | 
			
		||||
		if cve.VulnInfo.CveID == cveID {
 | 
			
		||||
			*c = append(cveInfos[:i], cveInfos[i+1:]...)
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
//  // Delete by cveID
 | 
			
		||||
//  func (c *CveInfos) Delete(cveID string) {
 | 
			
		||||
//      cveInfos := *c
 | 
			
		||||
//      for i, cve := range cveInfos {
 | 
			
		||||
//          if cve.VulnInfo.CveID == cveID {
 | 
			
		||||
//              *c = append(cveInfos[:i], cveInfos[i+1:]...)
 | 
			
		||||
//              break
 | 
			
		||||
//          }
 | 
			
		||||
//      }
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
// Insert cveInfo
 | 
			
		||||
func (c *CveInfos) Insert(cveInfo CveInfo) {
 | 
			
		||||
	*c = append(*c, cveInfo)
 | 
			
		||||
}
 | 
			
		||||
//  // Insert cveInfo
 | 
			
		||||
//  func (c *CveInfos) Insert(cveInfo CveInfo) {
 | 
			
		||||
//      *c = append(*c, cveInfo)
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
// Update cveInfo
 | 
			
		||||
func (c CveInfos) Update(cveInfo CveInfo) (ok bool) {
 | 
			
		||||
	for i, cve := range c {
 | 
			
		||||
		if cve.VulnInfo.CveID == cveInfo.VulnInfo.CveID {
 | 
			
		||||
			c[i] = cveInfo
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
//  // Update cveInfo
 | 
			
		||||
//  func (c CveInfos) Update(cveInfo CveInfo) (ok bool) {
 | 
			
		||||
//      for i, cve := range c {
 | 
			
		||||
//          if cve.VulnInfo.CveID == cveInfo.VulnInfo.CveID {
 | 
			
		||||
//              c[i] = cveInfo
 | 
			
		||||
//              return true
 | 
			
		||||
//          }
 | 
			
		||||
//      }
 | 
			
		||||
//      return false
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
// Upsert cveInfo
 | 
			
		||||
func (c *CveInfos) Upsert(cveInfo CveInfo) {
 | 
			
		||||
	ok := c.Update(cveInfo)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		c.Insert(cveInfo)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
//  // Upsert cveInfo
 | 
			
		||||
//  func (c *CveInfos) Upsert(cveInfo CveInfo) {
 | 
			
		||||
//      ok := c.Update(cveInfo)
 | 
			
		||||
//      if !ok {
 | 
			
		||||
//          c.Insert(cveInfo)
 | 
			
		||||
//      }
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
//TODO
 | 
			
		||||
// CveInfo has CVE detailed Information.
 | 
			
		||||
type CveInfo struct {
 | 
			
		||||
	VulnInfo
 | 
			
		||||
	CveContents []CveContent
 | 
			
		||||
}
 | 
			
		||||
//  type CveInfo struct {
 | 
			
		||||
//      VulnInfo
 | 
			
		||||
//      CveContents []CveContent
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
// Get a CveContent specified by arg
 | 
			
		||||
func (c *CveInfo) Get(typestr CveContentType) (*CveContent, bool) {
 | 
			
		||||
	for _, cont := range c.CveContents {
 | 
			
		||||
		if cont.Type == typestr {
 | 
			
		||||
			return &cont, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return &CveContent{}, false
 | 
			
		||||
}
 | 
			
		||||
//  func (c *CveInfo) Get(typestr CveContentType) (*CveContent, bool) {
 | 
			
		||||
//      for _, cont := range c.CveContents {
 | 
			
		||||
//          if cont.Type == typestr {
 | 
			
		||||
//              return &cont, true
 | 
			
		||||
//          }
 | 
			
		||||
//      }
 | 
			
		||||
//      return &CveContent{}, false
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
// Insert a CveContent to specified by arg
 | 
			
		||||
func (c *CveInfo) Insert(con CveContent) {
 | 
			
		||||
	c.CveContents = append(c.CveContents, con)
 | 
			
		||||
}
 | 
			
		||||
//  // Insert a CveContent to specified by arg
 | 
			
		||||
//  func (c *CveInfo) Insert(con CveContent) {
 | 
			
		||||
//      c.CveContents = append(c.CveContents, con)
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
// Update a CveContent to specified by arg
 | 
			
		||||
func (c *CveInfo) Update(to CveContent) bool {
 | 
			
		||||
	for i, cont := range c.CveContents {
 | 
			
		||||
		if cont.Type == to.Type {
 | 
			
		||||
			c.CveContents[i] = to
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
//  // Update a CveContent to specified by arg
 | 
			
		||||
//  func (c *CveInfo) Update(to CveContent) bool {
 | 
			
		||||
//      for i, cont := range c.CveContents {
 | 
			
		||||
//          if cont.Type == to.Type {
 | 
			
		||||
//              c.CveContents[i] = to
 | 
			
		||||
//              return true
 | 
			
		||||
//          }
 | 
			
		||||
//      }
 | 
			
		||||
//      return false
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
// CvssV2Score returns CVSS V2 Score
 | 
			
		||||
func (c *CveInfo) CvssV2Score() float64 {
 | 
			
		||||
	//TODO
 | 
			
		||||
	if cont, found := c.Get(NVD); found {
 | 
			
		||||
		return cont.Cvss2Score
 | 
			
		||||
	} else if cont, found := c.Get(JVN); found {
 | 
			
		||||
		return cont.Cvss2Score
 | 
			
		||||
	} else if cont, found := c.Get(RedHat); found {
 | 
			
		||||
		return cont.Cvss2Score
 | 
			
		||||
	}
 | 
			
		||||
	return -1
 | 
			
		||||
}
 | 
			
		||||
//  // CvssV2Score returns CVSS V2 Score
 | 
			
		||||
//  func (c *CveInfo) CvssV2Score() float64 {
 | 
			
		||||
//      //TODO
 | 
			
		||||
//      if cont, found := c.Get(NVD); found {
 | 
			
		||||
//          return cont.Cvss2Score
 | 
			
		||||
//      } else if cont, found := c.Get(JVN); found {
 | 
			
		||||
//          return cont.Cvss2Score
 | 
			
		||||
//      } else if cont, found := c.Get(RedHat); found {
 | 
			
		||||
//          return cont.Cvss2Score
 | 
			
		||||
//      }
 | 
			
		||||
//      return -1
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
// NilSliceToEmpty set nil slice fields to empty slice to avoid null in JSON
 | 
			
		||||
func (c *CveInfo) NilSliceToEmpty() {
 | 
			
		||||
	return
 | 
			
		||||
	// TODO
 | 
			
		||||
	//  if c.CveDetail.Nvd.Cpes == nil {
 | 
			
		||||
	//      c.CveDetail.Nvd.Cpes = []cve.Cpe{}
 | 
			
		||||
	//  }
 | 
			
		||||
	//  if c.CveDetail.Jvn.Cpes == nil {
 | 
			
		||||
	//      c.CveDetail.Jvn.Cpes = []cve.Cpe{}
 | 
			
		||||
	//  }
 | 
			
		||||
	//  if c.CveDetail.Nvd.References == nil {
 | 
			
		||||
	//      c.CveDetail.Nvd.References = []cve.Reference{}
 | 
			
		||||
	//  }
 | 
			
		||||
	//  if c.CveDetail.Jvn.References == nil {
 | 
			
		||||
	//      c.CveDetail.Jvn.References = []cve.Reference{}
 | 
			
		||||
	//  }
 | 
			
		||||
}
 | 
			
		||||
//  // NilSliceToEmpty set nil slice fields to empty slice to avoid null in JSON
 | 
			
		||||
//  func (c *CveInfo) NilSliceToEmpty() {
 | 
			
		||||
//      return
 | 
			
		||||
//      // TODO
 | 
			
		||||
//      //  if c.CveDetail.Nvd.Cpes == nil {
 | 
			
		||||
//      //      c.CveDetail.Nvd.Cpes = []cve.Cpe{}
 | 
			
		||||
//      //  }
 | 
			
		||||
//      //  if c.CveDetail.Jvn.Cpes == nil {
 | 
			
		||||
//      //      c.CveDetail.Jvn.Cpes = []cve.Cpe{}
 | 
			
		||||
//      //  }
 | 
			
		||||
//      //  if c.CveDetail.Nvd.References == nil {
 | 
			
		||||
//      //      c.CveDetail.Nvd.References = []cve.Reference{}
 | 
			
		||||
//      //  }
 | 
			
		||||
//      //  if c.CveDetail.Jvn.References == nil {
 | 
			
		||||
//      //      c.CveDetail.Jvn.References = []cve.Reference{}
 | 
			
		||||
//      //  }
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
// CveContentType is a source of CVE information
 | 
			
		||||
type CveContentType string
 | 
			
		||||
@@ -612,6 +612,68 @@ const (
 | 
			
		||||
	Ubuntu CveContentType = "ubuntu"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CveContents has slice of CveContent
 | 
			
		||||
type CveContents []CveContent
 | 
			
		||||
 | 
			
		||||
// Get CveContent by cveID
 | 
			
		||||
// TODO Pointer
 | 
			
		||||
func (v *CveContents) Get(typestr CveContentType) (CveContent, bool) {
 | 
			
		||||
	for _, vv := range *v {
 | 
			
		||||
		if vv.Type == typestr {
 | 
			
		||||
			return vv, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return CveContent{}, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete by cveID
 | 
			
		||||
func (v *CveContents) Delete(typestr CveContentType) {
 | 
			
		||||
	cveContents := *v
 | 
			
		||||
	for i, cc := range cveContents {
 | 
			
		||||
		if cc.Type == typestr {
 | 
			
		||||
			*v = append(cveContents[:i], cveContents[i+1:]...)
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Insert CveContent
 | 
			
		||||
func (v *CveContents) Insert(cont CveContent) {
 | 
			
		||||
	*v = append(*v, cont)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update VulnInfo
 | 
			
		||||
func (v *CveContents) Update(cont CveContent) (ok bool) {
 | 
			
		||||
	for i, vv := range *v {
 | 
			
		||||
		if vv.Type == cont.Type {
 | 
			
		||||
			(*v)[i] = cont
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Upsert CveContent
 | 
			
		||||
func (v *CveContents) Upsert(cont CveContent) {
 | 
			
		||||
	ok := v.Update(cont)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		v.Insert(cont)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CvssV2Score returns CVSS V2 Score
 | 
			
		||||
func (v *CveContents) CvssV2Score() float64 {
 | 
			
		||||
	//TODO
 | 
			
		||||
	if cont, found := v.Get(NVD); found {
 | 
			
		||||
		return cont.Cvss2Score
 | 
			
		||||
	} else if cont, found := v.Get(JVN); found {
 | 
			
		||||
		return cont.Cvss2Score
 | 
			
		||||
	} else if cont, found := v.Get(RedHat); found {
 | 
			
		||||
		return cont.Cvss2Score
 | 
			
		||||
	}
 | 
			
		||||
	return -1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CveContent has abstraction of various vulnerability information
 | 
			
		||||
type CveContent struct {
 | 
			
		||||
	Type         CveContentType
 | 
			
		||||
@@ -630,6 +692,11 @@ type CveContent struct {
 | 
			
		||||
	LastModified time.Time
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Empty checks the content is empty
 | 
			
		||||
func (c CveContent) Empty() bool {
 | 
			
		||||
	return c.Summary == ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Cpe is Common Platform Enumeration
 | 
			
		||||
type Cpe struct {
 | 
			
		||||
	CpeName string
 | 
			
		||||
 
 | 
			
		||||
@@ -59,64 +59,30 @@ func (o Debian) FillCveInfoFromOvalDB(r *models.ScanResult) (*models.ScanResult,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o Debian) fillOvalInfo(r *models.ScanResult, definition *ovalmodels.Definition) *models.ScanResult {
 | 
			
		||||
	// Update ScannedCves by OVAL info
 | 
			
		||||
	found := false
 | 
			
		||||
	updatedCves := []models.VulnInfo{}
 | 
			
		||||
 | 
			
		||||
	// Update scanned confidence to ovalmatch
 | 
			
		||||
	for _, scanned := range r.ScannedCves {
 | 
			
		||||
		if scanned.CveID == definition.Debian.CveID {
 | 
			
		||||
			found = true
 | 
			
		||||
			if scanned.Confidence.Score < models.OvalMatch.Score {
 | 
			
		||||
				scanned.Confidence = models.OvalMatch
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		updatedCves = append(updatedCves, scanned)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vuln := models.VulnInfo{
 | 
			
		||||
		CveID:      definition.Debian.CveID,
 | 
			
		||||
		Confidence: models.OvalMatch,
 | 
			
		||||
		Packages:   getPackageInfoList(r, definition),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !found {
 | 
			
		||||
		util.Log.Debugf("%s is newly detected by OVAL", vuln.CveID)
 | 
			
		||||
		updatedCves = append(updatedCves, vuln)
 | 
			
		||||
	}
 | 
			
		||||
	r.ScannedCves = updatedCves
 | 
			
		||||
 | 
			
		||||
	// Update KnownCves by OVAL info
 | 
			
		||||
	ovalContent := *o.convertToModel(definition)
 | 
			
		||||
	ovalContent.Type = models.CveContentType(r.Family)
 | 
			
		||||
	cInfo, ok := r.KnownCves.Get(definition.Debian.CveID)
 | 
			
		||||
	vinfo, ok := r.ScannedCves.Get(definition.Debian.CveID)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		cInfo.VulnInfo = vuln
 | 
			
		||||
		cInfo.CveContents = []models.CveContent{ovalContent}
 | 
			
		||||
	}
 | 
			
		||||
	if !cInfo.Update(ovalContent) {
 | 
			
		||||
		cInfo.Insert(ovalContent)
 | 
			
		||||
	}
 | 
			
		||||
	if cInfo.VulnInfo.Confidence.Score < models.OvalMatch.Score {
 | 
			
		||||
		cInfo.Confidence = models.OvalMatch
 | 
			
		||||
	}
 | 
			
		||||
	r.KnownCves.Upsert(cInfo)
 | 
			
		||||
 | 
			
		||||
	// Update UnknownCves by OVAL info
 | 
			
		||||
	cInfo, ok = r.UnknownCves.Get(definition.Debian.CveID)
 | 
			
		||||
	if ok {
 | 
			
		||||
		r.UnknownCves.Delete(definition.Debian.CveID)
 | 
			
		||||
 | 
			
		||||
		// Insert new CveInfo
 | 
			
		||||
		if !cInfo.Update(ovalContent) {
 | 
			
		||||
			cInfo.Insert(ovalContent)
 | 
			
		||||
		util.Log.Infof("%s is newly detected by OVAL",
 | 
			
		||||
			definition.Debian.CveID)
 | 
			
		||||
		vinfo = models.VulnInfo{
 | 
			
		||||
			CveID:       definition.Debian.CveID,
 | 
			
		||||
			Confidence:  models.OvalMatch,
 | 
			
		||||
			Packages:    getPackageInfoList(r, definition),
 | 
			
		||||
			CveContents: []models.CveContent{ovalContent},
 | 
			
		||||
		}
 | 
			
		||||
		if cInfo.VulnInfo.Confidence.Score < models.OvalMatch.Score {
 | 
			
		||||
			cInfo.Confidence = models.OvalMatch
 | 
			
		||||
	} else {
 | 
			
		||||
		if _, ok := vinfo.CveContents.Get(models.CveContentType(r.Family)); !ok {
 | 
			
		||||
			util.Log.Infof("%s is also detected by OVAL", definition.Debian.CveID)
 | 
			
		||||
		} else {
 | 
			
		||||
			util.Log.Infof("%s will be updated by OVAL", definition.Debian.CveID)
 | 
			
		||||
		}
 | 
			
		||||
		r.KnownCves.Upsert(cInfo)
 | 
			
		||||
		if vinfo.Confidence.Score < models.OvalMatch.Score {
 | 
			
		||||
			vinfo.Confidence = models.OvalMatch
 | 
			
		||||
		}
 | 
			
		||||
		vinfo.CveContents.Upsert(ovalContent)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r.ScannedCves.Upsert(vinfo)
 | 
			
		||||
	return r
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -133,6 +99,7 @@ func (o Debian) convertToModel(def *ovalmodels.Definition) *models.CveContent {
 | 
			
		||||
		CveID:      def.Debian.CveID,
 | 
			
		||||
		Title:      def.Title,
 | 
			
		||||
		Summary:    def.Description,
 | 
			
		||||
		Severity:   def.Advisory.Severity,
 | 
			
		||||
		References: refs,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										135
									
								
								oval/redhat.go
									
									
									
									
									
								
							
							
						
						
									
										135
									
								
								oval/redhat.go
									
									
									
									
									
								
							@@ -2,6 +2,8 @@ package oval
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/future-architect/vuls/config"
 | 
			
		||||
	"github.com/future-architect/vuls/models"
 | 
			
		||||
@@ -55,76 +57,26 @@ func (o Redhat) FillCveInfoFromOvalDB(r *models.ScanResult) (*models.ScanResult,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o Redhat) fillOvalInfo(r *models.ScanResult, definition *ovalmodels.Definition) *models.ScanResult {
 | 
			
		||||
	cveIDSet := make(map[string]bool)
 | 
			
		||||
	cveID2VulnInfo := make(map[string]models.VulnInfo)
 | 
			
		||||
	for _, cve := range definition.Advisory.Cves {
 | 
			
		||||
		cveIDSet[cve.CveID] = false
 | 
			
		||||
		cveID2VulnInfo[cve.CveID] = models.VulnInfo{
 | 
			
		||||
			CveID:      cve.CveID,
 | 
			
		||||
			Confidence: models.OvalMatch,
 | 
			
		||||
			Packages:   getPackageInfoList(r, definition),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Update ScannedCves by OVAL info
 | 
			
		||||
	updatedCves := []models.VulnInfo{}
 | 
			
		||||
	for _, scanned := range r.ScannedCves {
 | 
			
		||||
		// Update scanned confidence to ovalmatch
 | 
			
		||||
		for _, c := range definition.Advisory.Cves {
 | 
			
		||||
			if scanned.CveID == c.CveID {
 | 
			
		||||
				cveIDSet[c.CveID] = true
 | 
			
		||||
				if scanned.Confidence.Score < models.OvalMatch.Score {
 | 
			
		||||
					scanned.Confidence = models.OvalMatch
 | 
			
		||||
				}
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		updatedCves = append(updatedCves, scanned)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for cveID, found := range cveIDSet {
 | 
			
		||||
		if !found {
 | 
			
		||||
			util.Log.Debugf("%s is newly detected by OVAL", cveID)
 | 
			
		||||
			updatedCves = append(updatedCves, cveID2VulnInfo[cveID])
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	r.ScannedCves = updatedCves
 | 
			
		||||
 | 
			
		||||
	// Update KnownCves by OVAL info
 | 
			
		||||
	for _, c := range definition.Advisory.Cves {
 | 
			
		||||
		ovalContent := *o.convertToModel(c.CveID, definition)
 | 
			
		||||
		cInfo, ok := r.KnownCves.Get(c.CveID)
 | 
			
		||||
		ovalContent := *o.convertToModel(cve.CveID, definition)
 | 
			
		||||
		vinfo, ok := r.ScannedCves.Get(cve.CveID)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			cInfo.VulnInfo = cveID2VulnInfo[c.CveID]
 | 
			
		||||
			cInfo.CveContents = []models.CveContent{ovalContent}
 | 
			
		||||
		}
 | 
			
		||||
		if !cInfo.Update(ovalContent) {
 | 
			
		||||
			cInfo.Insert(ovalContent)
 | 
			
		||||
		}
 | 
			
		||||
		if cInfo.VulnInfo.Confidence.Score < models.OvalMatch.Score {
 | 
			
		||||
			cInfo.Confidence = models.OvalMatch
 | 
			
		||||
		}
 | 
			
		||||
		r.KnownCves.Upsert(cInfo)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Update UnknownCves by OVAL info
 | 
			
		||||
	for _, c := range definition.Advisory.Cves {
 | 
			
		||||
		cInfo, ok := r.UnknownCves.Get(c.CveID)
 | 
			
		||||
		if ok {
 | 
			
		||||
			r.UnknownCves.Delete(c.CveID)
 | 
			
		||||
 | 
			
		||||
			// Insert new CveInfo
 | 
			
		||||
			ovalContent := *o.convertToModel(c.CveID, definition)
 | 
			
		||||
			if !cInfo.Update(ovalContent) {
 | 
			
		||||
				cInfo.Insert(ovalContent)
 | 
			
		||||
			util.Log.Infof("%s is newly detected by OVAL",
 | 
			
		||||
				definition.Debian.CveID)
 | 
			
		||||
			vinfo = models.VulnInfo{
 | 
			
		||||
				CveID:       cve.CveID,
 | 
			
		||||
				Confidence:  models.OvalMatch,
 | 
			
		||||
				Packages:    getPackageInfoList(r, definition),
 | 
			
		||||
				CveContents: []models.CveContent{ovalContent},
 | 
			
		||||
			}
 | 
			
		||||
			if cInfo.VulnInfo.Confidence.Score < models.OvalMatch.Score {
 | 
			
		||||
				cInfo.Confidence = models.OvalMatch
 | 
			
		||||
		} else {
 | 
			
		||||
			if vinfo.Confidence.Score < models.OvalMatch.Score {
 | 
			
		||||
				vinfo.Confidence = models.OvalMatch
 | 
			
		||||
			}
 | 
			
		||||
			r.KnownCves.Upsert(cInfo)
 | 
			
		||||
			vinfo.CveContents.Upsert(ovalContent)
 | 
			
		||||
		}
 | 
			
		||||
		r.ScannedCves.Upsert(vinfo)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return r
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -134,7 +86,6 @@ func (o Redhat) convertToModel(cveID string, def *ovalmodels.Definition) *models
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		var refs []models.Reference
 | 
			
		||||
		//TODO RHSAのリンクを入れる
 | 
			
		||||
		for _, r := range def.References {
 | 
			
		||||
			refs = append(refs, models.Reference{
 | 
			
		||||
				Link:   r.RefURL,
 | 
			
		||||
@@ -143,20 +94,52 @@ func (o Redhat) convertToModel(cveID string, def *ovalmodels.Definition) *models
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//  util.ParseCvss2()
 | 
			
		||||
		score2, vec2 := o.parseCvss2(cve.Cvss2)
 | 
			
		||||
		score3, vec3 := o.parseCvss3(cve.Cvss3)
 | 
			
		||||
 | 
			
		||||
		return &models.CveContent{
 | 
			
		||||
			Type:     models.RedHat,
 | 
			
		||||
			CveID:    cve.CveID,
 | 
			
		||||
			Title:    def.Title,
 | 
			
		||||
			Summary:  def.Description,
 | 
			
		||||
			Severity: def.Advisory.Severity,
 | 
			
		||||
			//  V2Score:    v2Score,   // TODO divide into score and vector
 | 
			
		||||
			Cvss2Vector: cve.Cvss2, // TODO divide into score and vector
 | 
			
		||||
			Cvss3Vector: cve.Cvss3, // TODO divide into score and vector
 | 
			
		||||
			References:  refs,
 | 
			
		||||
			CweID:       cve.Cwe,
 | 
			
		||||
			Type:         models.RedHat,
 | 
			
		||||
			CveID:        cve.CveID,
 | 
			
		||||
			Title:        def.Title,
 | 
			
		||||
			Summary:      def.Description,
 | 
			
		||||
			Severity:     def.Advisory.Severity,
 | 
			
		||||
			Cvss2Score:   score2,
 | 
			
		||||
			Cvss2Vector:  vec2,
 | 
			
		||||
			Cvss3Score:   score3,
 | 
			
		||||
			Cvss3Vector:  vec3,
 | 
			
		||||
			References:   refs,
 | 
			
		||||
			CweID:        cve.Cwe,
 | 
			
		||||
			Published:    def.Advisory.Issued,
 | 
			
		||||
			LastModified: def.Advisory.Updated,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseCvss2 divide CVSSv2 string into score and vector
 | 
			
		||||
// 5/AV:N/AC:L/Au:N/C:N/I:N/A:P
 | 
			
		||||
func (o Redhat) parseCvss2(scoreVector string) (score float64, vector string) {
 | 
			
		||||
	var err error
 | 
			
		||||
	ss := strings.Split(scoreVector, "/")
 | 
			
		||||
	if 1 < len(ss) {
 | 
			
		||||
		if score, err = strconv.ParseFloat(ss[0], 64); err != nil {
 | 
			
		||||
			return 0, ""
 | 
			
		||||
		}
 | 
			
		||||
		return score, strings.Join(ss[1:len(ss)], "/")
 | 
			
		||||
	}
 | 
			
		||||
	return 0, ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseCvss3 divide CVSSv3 string into score and vector
 | 
			
		||||
// 5.6/CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L
 | 
			
		||||
func (o Redhat) parseCvss3(scoreVector string) (score float64, vector string) {
 | 
			
		||||
	var err error
 | 
			
		||||
	ss := strings.Split(scoreVector, "/CVSS:3.0/")
 | 
			
		||||
	if 1 < len(ss) {
 | 
			
		||||
		if score, err = strconv.ParseFloat(ss[0], 64); err != nil {
 | 
			
		||||
			return 0, ""
 | 
			
		||||
		}
 | 
			
		||||
		return score, strings.Join(ss[1:len(ss)], "/")
 | 
			
		||||
	}
 | 
			
		||||
	return 0, ""
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										69
									
								
								oval/redhat_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								oval/redhat_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
			
		||||
package oval
 | 
			
		||||
 | 
			
		||||
import "testing"
 | 
			
		||||
 | 
			
		||||
func TestParseCvss2(t *testing.T) {
 | 
			
		||||
	type out struct {
 | 
			
		||||
		score  float64
 | 
			
		||||
		vector string
 | 
			
		||||
	}
 | 
			
		||||
	var tests = []struct {
 | 
			
		||||
		in  string
 | 
			
		||||
		out out
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			in: "5/AV:N/AC:L/Au:N/C:N/I:N/A:P",
 | 
			
		||||
			out: out{
 | 
			
		||||
				score:  5.0,
 | 
			
		||||
				vector: "AV:N/AC:L/Au:N/C:N/I:N/A:P",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			in: "",
 | 
			
		||||
			out: out{
 | 
			
		||||
				score:  0,
 | 
			
		||||
				vector: "",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		s, v := Redhat{}.parseCvss2(tt.in)
 | 
			
		||||
		if s != tt.out.score || v != tt.out.vector {
 | 
			
		||||
			t.Errorf("\nexpected: %f, %s\n  actual: %f, %s",
 | 
			
		||||
				tt.out.score, tt.out.vector, s, v)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestParseCvss3(t *testing.T) {
 | 
			
		||||
	type out struct {
 | 
			
		||||
		score  float64
 | 
			
		||||
		vector string
 | 
			
		||||
	}
 | 
			
		||||
	var tests = []struct {
 | 
			
		||||
		in  string
 | 
			
		||||
		out out
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			in: "5.6/CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L",
 | 
			
		||||
			out: out{
 | 
			
		||||
				score:  5.6,
 | 
			
		||||
				vector: "AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			in: "",
 | 
			
		||||
			out: out{
 | 
			
		||||
				score:  0,
 | 
			
		||||
				vector: "",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		s, v := Redhat{}.parseCvss3(tt.in)
 | 
			
		||||
		if s != tt.out.score || v != tt.out.vector {
 | 
			
		||||
			t.Errorf("\nexpected: %f, %s\n  actual: %f, %s",
 | 
			
		||||
				tt.out.score, tt.out.vector, s, v)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -139,13 +139,9 @@ func createBlockBlob(cli storage.BlobStorageClient, k string, b []byte) error {
 | 
			
		||||
		k = k + ".gz"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := cli.CreateBlockBlobFromReader(
 | 
			
		||||
		c.Conf.AzureContainer,
 | 
			
		||||
		k,
 | 
			
		||||
		uint64(len(b)),
 | 
			
		||||
		bytes.NewReader(b),
 | 
			
		||||
		map[string]string{},
 | 
			
		||||
	); err != nil {
 | 
			
		||||
	ref := cli.GetContainerReference(c.Conf.AzureContainer)
 | 
			
		||||
	blob := ref.GetBlobReference(k)
 | 
			
		||||
	if err := blob.CreateBlockBlobFromReader(bytes.NewReader(b), nil); err != nil {
 | 
			
		||||
		return fmt.Errorf("Failed to upload data to %s/%s, %s",
 | 
			
		||||
			c.Conf.AzureContainer, k, err)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -41,8 +41,8 @@ func (w EMailWriter) Write(rs ...models.ScanResult) (err error) {
 | 
			
		||||
	for _, r := range rs {
 | 
			
		||||
		if conf.FormatOneEMail {
 | 
			
		||||
			message += formatFullPlainText(r) + "\r\n\r\n"
 | 
			
		||||
			totalResult.KnownCves = append(totalResult.KnownCves, r.KnownCves...)
 | 
			
		||||
			totalResult.UnknownCves = append(totalResult.UnknownCves, r.UnknownCves...)
 | 
			
		||||
			//  totalResult.KnownCves = append(totalResult.KnownCves, r.KnownCves...)
 | 
			
		||||
			//  totalResult.UnknownCves = append(totalResult.UnknownCves, r.UnknownCves...)
 | 
			
		||||
		} else {
 | 
			
		||||
			var subject string
 | 
			
		||||
			if len(r.Errors) != 0 {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										236
									
								
								report/slack.go
									
									
									
									
									
								
							
							
						
						
									
										236
									
								
								report/slack.go
									
									
									
									
									
								
							@@ -21,7 +21,6 @@ import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	log "github.com/Sirupsen/logrus"
 | 
			
		||||
@@ -67,11 +66,12 @@ func (w SlackWriter) Write(rs ...models.ScanResult) error {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if 0 < len(r.Errors) {
 | 
			
		||||
			serverInfo := fmt.Sprintf("*%s*", r.ServerInfo())
 | 
			
		||||
			notifyUsers := getNotifyUsers(config.Conf.Slack.NotifyUsers)
 | 
			
		||||
			txt := fmt.Sprintf("%s\n%s\nError: %s", notifyUsers, serverInfo, r.Errors)
 | 
			
		||||
			//TODO
 | 
			
		||||
			//  serverInfo := fmt.Sprintf("*%s*", r.ServerInfo())
 | 
			
		||||
			//  notifyUsers := getNotifyUsers(config.Conf.Slack.NotifyUsers)
 | 
			
		||||
			//  txt := fmt.Sprintf("%s\n%s\nError: %s", notifyUsers, serverInfo, r.Errors)
 | 
			
		||||
			msg := message{
 | 
			
		||||
				Text:      txt,
 | 
			
		||||
				//  Text:      txt,
 | 
			
		||||
				Username:  conf.AuthUser,
 | 
			
		||||
				IconEmoji: conf.IconEmoji,
 | 
			
		||||
				Channel:   channel,
 | 
			
		||||
@@ -152,57 +152,57 @@ func send(msg message) error {
 | 
			
		||||
 | 
			
		||||
func msgText(r models.ScanResult) string {
 | 
			
		||||
	notifyUsers := ""
 | 
			
		||||
	if 0 < len(r.KnownCves) || 0 < len(r.UnknownCves) {
 | 
			
		||||
		notifyUsers = getNotifyUsers(config.Conf.Slack.NotifyUsers)
 | 
			
		||||
	}
 | 
			
		||||
	//  if 0 < len(r.KnownCves) || 0 < len(r.UnknownCves) {
 | 
			
		||||
	//      notifyUsers = getNotifyUsers(config.Conf.Slack.NotifyUsers)
 | 
			
		||||
	//  }
 | 
			
		||||
	serverInfo := fmt.Sprintf("*%s*", r.ServerInfo())
 | 
			
		||||
	return fmt.Sprintf("%s\n%s\n>%s", notifyUsers, serverInfo, r.CveSummary())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func toSlackAttachments(scanResult models.ScanResult) (attaches []*attachment) {
 | 
			
		||||
	cves := scanResult.KnownCves
 | 
			
		||||
	if !config.Conf.IgnoreUnscoredCves {
 | 
			
		||||
		cves = append(cves, scanResult.UnknownCves...)
 | 
			
		||||
	}
 | 
			
		||||
	//  cves := scanResult.KnownCves
 | 
			
		||||
	//  if !config.Conf.IgnoreUnscoredCves {
 | 
			
		||||
	//      cves = append(cves, scanResult.UnknownCves...)
 | 
			
		||||
	//  }
 | 
			
		||||
 | 
			
		||||
	for _, cveInfo := range cves {
 | 
			
		||||
		cveID := cveInfo.VulnInfo.CveID
 | 
			
		||||
	//  for _, cveInfo := range cves {
 | 
			
		||||
	//      cveID := cveInfo.VulnInfo.CveID
 | 
			
		||||
 | 
			
		||||
		curentPackages := []string{}
 | 
			
		||||
		for _, p := range cveInfo.Packages {
 | 
			
		||||
			curentPackages = append(curentPackages, p.FormatCurrentVer())
 | 
			
		||||
		}
 | 
			
		||||
		for _, n := range cveInfo.CpeNames {
 | 
			
		||||
			curentPackages = append(curentPackages, n)
 | 
			
		||||
		}
 | 
			
		||||
	//      curentPackages := []string{}
 | 
			
		||||
	//      for _, p := range cveInfo.Packages {
 | 
			
		||||
	//          curentPackages = append(curentPackages, p.FormatCurrentVer())
 | 
			
		||||
	//      }
 | 
			
		||||
	//      for _, n := range cveInfo.CpeNames {
 | 
			
		||||
	//          curentPackages = append(curentPackages, n)
 | 
			
		||||
	//      }
 | 
			
		||||
 | 
			
		||||
		newPackages := []string{}
 | 
			
		||||
		for _, p := range cveInfo.Packages {
 | 
			
		||||
			newPackages = append(newPackages, p.FormatNewVer())
 | 
			
		||||
		}
 | 
			
		||||
	//      newPackages := []string{}
 | 
			
		||||
	//      for _, p := range cveInfo.Packages {
 | 
			
		||||
	//          newPackages = append(newPackages, p.FormatNewVer())
 | 
			
		||||
	//      }
 | 
			
		||||
 | 
			
		||||
		a := attachment{
 | 
			
		||||
			Title:     cveID,
 | 
			
		||||
			TitleLink: fmt.Sprintf("%s/%s", nvdBaseURL, cveID),
 | 
			
		||||
			Text:      attachmentText(cveInfo, scanResult.Family),
 | 
			
		||||
			MrkdwnIn:  []string{"text", "pretext"},
 | 
			
		||||
			Fields: []*field{
 | 
			
		||||
				{
 | 
			
		||||
					//  Title: "Current Package/CPE",
 | 
			
		||||
					Title: "Installed",
 | 
			
		||||
					Value: strings.Join(curentPackages, "\n"),
 | 
			
		||||
					Short: true,
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Title: "Candidate",
 | 
			
		||||
					Value: strings.Join(newPackages, "\n"),
 | 
			
		||||
					Short: true,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Color: color(cveInfo.CvssV2Score()),
 | 
			
		||||
		}
 | 
			
		||||
		attaches = append(attaches, &a)
 | 
			
		||||
	}
 | 
			
		||||
	//      a := attachment{
 | 
			
		||||
	//          Title:     cveID,
 | 
			
		||||
	//          TitleLink: fmt.Sprintf("%s/%s", nvdBaseURL, cveID),
 | 
			
		||||
	//          Text:      attachmentText(cveInfo, scanResult.Family),
 | 
			
		||||
	//          MrkdwnIn:  []string{"text", "pretext"},
 | 
			
		||||
	//          Fields: []*field{
 | 
			
		||||
	//              {
 | 
			
		||||
	//                  //  Title: "Current Package/CPE",
 | 
			
		||||
	//                  Title: "Installed",
 | 
			
		||||
	//                  Value: strings.Join(curentPackages, "\n"),
 | 
			
		||||
	//                  Short: true,
 | 
			
		||||
	//              },
 | 
			
		||||
	//              {
 | 
			
		||||
	//                  Title: "Candidate",
 | 
			
		||||
	//                  Value: strings.Join(newPackages, "\n"),
 | 
			
		||||
	//                  Short: true,
 | 
			
		||||
	//              },
 | 
			
		||||
	//          },
 | 
			
		||||
	//          Color: color(cveInfo.CvssV2Score()),
 | 
			
		||||
	//      }
 | 
			
		||||
	//      attaches = append(attaches, &a)
 | 
			
		||||
	//  }
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -220,80 +220,80 @@ func color(cvssScore float64) string {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func attachmentText(cveInfo models.CveInfo, osFamily string) string {
 | 
			
		||||
	//  linkText := links(cveInfo, osFamily)
 | 
			
		||||
	//TODO
 | 
			
		||||
	return ""
 | 
			
		||||
	//  switch {
 | 
			
		||||
	//  case config.Conf.Lang == "ja" &&
 | 
			
		||||
	//      0 < cveInfo.CveDetail.Jvn.CvssScore():
 | 
			
		||||
//  func attachmentText(cveInfo models.CveInfo, osFamily string) string {
 | 
			
		||||
//  linkText := links(cveInfo, osFamily)
 | 
			
		||||
//TODO
 | 
			
		||||
//  return ""
 | 
			
		||||
//  switch {
 | 
			
		||||
//  case config.Conf.Lang == "ja" &&
 | 
			
		||||
//      0 < cveInfo.CveDetail.Jvn.CvssScore():
 | 
			
		||||
 | 
			
		||||
	//      jvn := cveInfo.CveDetail.Jvn
 | 
			
		||||
	//      return fmt.Sprintf("*%4.1f (%s)* <%s|%s>\n%s\n%s\n*Confidence:* %v",
 | 
			
		||||
	//          cveInfo.CveDetail.CvssScore(config.Conf.Lang),
 | 
			
		||||
	//          jvn.CvssSeverity(),
 | 
			
		||||
	//          fmt.Sprintf(cvssV2CalcBaseURL, cveInfo.CveDetail.CveID),
 | 
			
		||||
	//          jvn.CvssVector(),
 | 
			
		||||
	//          jvn.CveTitle(),
 | 
			
		||||
	//          linkText,
 | 
			
		||||
	//          cveInfo.VulnInfo.Confidence,
 | 
			
		||||
	//      )
 | 
			
		||||
	//  case 0 < cveInfo.CveDetail.CvssScore("en"):
 | 
			
		||||
	//      nvd := cveInfo.CveDetail.Nvd
 | 
			
		||||
	//      return fmt.Sprintf("*%4.1f (%s)* <%s|%s>\n%s\n%s\n*Confidence:* %v",
 | 
			
		||||
	//          cveInfo.CveDetail.CvssScore(config.Conf.Lang),
 | 
			
		||||
	//          nvd.CvssSeverity(),
 | 
			
		||||
	//          fmt.Sprintf(cvssV2CalcBaseURL, cveInfo.CveDetail.CveID),
 | 
			
		||||
	//          nvd.CvssVector(),
 | 
			
		||||
	//          nvd.CveSummary(),
 | 
			
		||||
	//          linkText,
 | 
			
		||||
	//          cveInfo.VulnInfo.Confidence,
 | 
			
		||||
	//      )
 | 
			
		||||
	//  default:
 | 
			
		||||
	//      nvd := cveInfo.CveDetail.Nvd
 | 
			
		||||
	//      return fmt.Sprintf("?\n%s\n%s\n*Confidence:* %v",
 | 
			
		||||
	//          nvd.CveSummary(), linkText, cveInfo.VulnInfo.Confidence)
 | 
			
		||||
	//  }
 | 
			
		||||
}
 | 
			
		||||
//      jvn := cveInfo.CveDetail.Jvn
 | 
			
		||||
//      return fmt.Sprintf("*%4.1f (%s)* <%s|%s>\n%s\n%s\n*Confidence:* %v",
 | 
			
		||||
//          cveInfo.CveDetail.CvssScore(config.Conf.Lang),
 | 
			
		||||
//          jvn.CvssSeverity(),
 | 
			
		||||
//          fmt.Sprintf(cvssV2CalcBaseURL, cveInfo.CveDetail.CveID),
 | 
			
		||||
//          jvn.CvssVector(),
 | 
			
		||||
//          jvn.CveTitle(),
 | 
			
		||||
//          linkText,
 | 
			
		||||
//          cveInfo.VulnInfo.Confidence,
 | 
			
		||||
//      )
 | 
			
		||||
//  case 0 < cveInfo.CveDetail.CvssScore("en"):
 | 
			
		||||
//      nvd := cveInfo.CveDetail.Nvd
 | 
			
		||||
//      return fmt.Sprintf("*%4.1f (%s)* <%s|%s>\n%s\n%s\n*Confidence:* %v",
 | 
			
		||||
//          cveInfo.CveDetail.CvssScore(config.Conf.Lang),
 | 
			
		||||
//          nvd.CvssSeverity(),
 | 
			
		||||
//          fmt.Sprintf(cvssV2CalcBaseURL, cveInfo.CveDetail.CveID),
 | 
			
		||||
//          nvd.CvssVector(),
 | 
			
		||||
//          nvd.CveSummary(),
 | 
			
		||||
//          linkText,
 | 
			
		||||
//          cveInfo.VulnInfo.Confidence,
 | 
			
		||||
//      )
 | 
			
		||||
//  default:
 | 
			
		||||
//      nvd := cveInfo.CveDetail.Nvd
 | 
			
		||||
//      return fmt.Sprintf("?\n%s\n%s\n*Confidence:* %v",
 | 
			
		||||
//          nvd.CveSummary(), linkText, cveInfo.VulnInfo.Confidence)
 | 
			
		||||
//  }
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
func links(cveInfo models.CveInfo, osFamily string) string {
 | 
			
		||||
	links := []string{}
 | 
			
		||||
//  func links(cveInfo models.CveInfo, osFamily string) string {
 | 
			
		||||
//      links := []string{}
 | 
			
		||||
 | 
			
		||||
	//TODO
 | 
			
		||||
	//  cweID := cveInfo.CveDetail.CweID()
 | 
			
		||||
	//  if 0 < len(cweID) {
 | 
			
		||||
	//      links = append(links, fmt.Sprintf("<%s|%s>",
 | 
			
		||||
	//          cweURL(cweID), cweID))
 | 
			
		||||
	//      if config.Conf.Lang == "ja" {
 | 
			
		||||
	//          links = append(links, fmt.Sprintf("<%s|%s(JVN)>",
 | 
			
		||||
	//              cweJvnURL(cweID), cweID))
 | 
			
		||||
	//      }
 | 
			
		||||
	//  }
 | 
			
		||||
//      //TODO
 | 
			
		||||
//      //  cweID := cveInfo.CveDetail.CweID()
 | 
			
		||||
//      //  if 0 < len(cweID) {
 | 
			
		||||
//      //      links = append(links, fmt.Sprintf("<%s|%s>",
 | 
			
		||||
//      //          cweURL(cweID), cweID))
 | 
			
		||||
//      //      if config.Conf.Lang == "ja" {
 | 
			
		||||
//      //          links = append(links, fmt.Sprintf("<%s|%s(JVN)>",
 | 
			
		||||
//      //              cweJvnURL(cweID), cweID))
 | 
			
		||||
//      //      }
 | 
			
		||||
//      //  }
 | 
			
		||||
 | 
			
		||||
	cveID := cveInfo.VulnInfo.CveID
 | 
			
		||||
	//TODO
 | 
			
		||||
	//  if config.Conf.Lang == "ja" && 0 < len(cveInfo.CveDetail.Jvn.Link()) {
 | 
			
		||||
	//      jvn := fmt.Sprintf("<%s|JVN>", cveInfo.CveDetail.Jvn.Link())
 | 
			
		||||
	//      links = append(links, jvn)
 | 
			
		||||
	//  }
 | 
			
		||||
	dlinks := distroLinks(cveInfo, osFamily)
 | 
			
		||||
	for _, link := range dlinks {
 | 
			
		||||
		links = append(links,
 | 
			
		||||
			fmt.Sprintf("<%s|%s>", link.url, link.title))
 | 
			
		||||
	}
 | 
			
		||||
	links = append(links, fmt.Sprintf("<%s|MITRE>",
 | 
			
		||||
		fmt.Sprintf("%s%s", mitreBaseURL, cveID)))
 | 
			
		||||
	links = append(links, fmt.Sprintf("<%s|CVEDetails>",
 | 
			
		||||
		fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID)))
 | 
			
		||||
//      cveID := cveInfo.VulnInfo.CveID
 | 
			
		||||
//      //TODO
 | 
			
		||||
//      //  if config.Conf.Lang == "ja" && 0 < len(cveInfo.CveDetail.Jvn.Link()) {
 | 
			
		||||
//      //      jvn := fmt.Sprintf("<%s|JVN>", cveInfo.CveDetail.Jvn.Link())
 | 
			
		||||
//      //      links = append(links, jvn)
 | 
			
		||||
//      //  }
 | 
			
		||||
//      dlinks := distroLinks(cveInfo, osFamily)
 | 
			
		||||
//      for _, link := range dlinks {
 | 
			
		||||
//          links = append(links,
 | 
			
		||||
//              fmt.Sprintf("<%s|%s>", link.url, link.title))
 | 
			
		||||
//      }
 | 
			
		||||
//      links = append(links, fmt.Sprintf("<%s|MITRE>",
 | 
			
		||||
//          fmt.Sprintf("%s%s", mitreBaseURL, cveID)))
 | 
			
		||||
//      links = append(links, fmt.Sprintf("<%s|CVEDetails>",
 | 
			
		||||
//          fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID)))
 | 
			
		||||
 | 
			
		||||
	return strings.Join(links, " / ")
 | 
			
		||||
}
 | 
			
		||||
//      return strings.Join(links, " / ")
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
// See testcase
 | 
			
		||||
func getNotifyUsers(notifyUsers []string) string {
 | 
			
		||||
	slackStyleTexts := []string{}
 | 
			
		||||
	for _, username := range notifyUsers {
 | 
			
		||||
		slackStyleTexts = append(slackStyleTexts, fmt.Sprintf("<%s>", username))
 | 
			
		||||
	}
 | 
			
		||||
	return strings.Join(slackStyleTexts, " ")
 | 
			
		||||
}
 | 
			
		||||
//  // See testcase
 | 
			
		||||
//  func getNotifyUsers(notifyUsers []string) string {
 | 
			
		||||
//      slackStyleTexts := []string{}
 | 
			
		||||
//      for _, username := range notifyUsers {
 | 
			
		||||
//          slackStyleTexts = append(slackStyleTexts, fmt.Sprintf("<%s>", username))
 | 
			
		||||
//      }
 | 
			
		||||
//      return strings.Join(slackStyleTexts, " ")
 | 
			
		||||
//  }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										271
									
								
								report/tui.go
									
									
									
									
									
								
							
							
						
						
									
										271
									
								
								report/tui.go
									
									
									
									
									
								
							@@ -22,7 +22,6 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"text/template"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	log "github.com/Sirupsen/logrus"
 | 
			
		||||
@@ -221,7 +220,8 @@ func movable(v *gocui.View, nextY int) (ok bool, yLimit int) {
 | 
			
		||||
		}
 | 
			
		||||
		return true, yLimit
 | 
			
		||||
	case "summary":
 | 
			
		||||
		yLimit = len(currentScanResult.AllCves()) - 1
 | 
			
		||||
		//TODO
 | 
			
		||||
		//  yLimit = len(currentScanResult.AllCves()) - 1
 | 
			
		||||
		if yLimit < nextY {
 | 
			
		||||
			return false, yLimit
 | 
			
		||||
		}
 | 
			
		||||
@@ -601,71 +601,72 @@ func summaryLines() string {
 | 
			
		||||
		return "Error: Scan with --debug to view the details"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	indexFormat := ""
 | 
			
		||||
	if len(currentScanResult.AllCves()) < 10 {
 | 
			
		||||
		indexFormat = "[%1d]"
 | 
			
		||||
	} else if len(currentScanResult.AllCves()) < 100 {
 | 
			
		||||
		indexFormat = "[%2d]"
 | 
			
		||||
	} else {
 | 
			
		||||
		indexFormat = "[%3d]"
 | 
			
		||||
	}
 | 
			
		||||
	//TODO
 | 
			
		||||
	//  indexFormat := ""
 | 
			
		||||
	//  if len(currentScanResult.AllCves()) < 10 {
 | 
			
		||||
	//      indexFormat = "[%1d]"
 | 
			
		||||
	//  } else if len(currentScanResult.AllCves()) < 100 {
 | 
			
		||||
	//      indexFormat = "[%2d]"
 | 
			
		||||
	//  } else {
 | 
			
		||||
	//      indexFormat = "[%3d]"
 | 
			
		||||
	//  }
 | 
			
		||||
 | 
			
		||||
	for i, d := range currentScanResult.AllCves() {
 | 
			
		||||
		var cols []string
 | 
			
		||||
		//TODO
 | 
			
		||||
		var summary string
 | 
			
		||||
		if cont, found := d.Get(models.NVD); found {
 | 
			
		||||
			summary = cont.Summary
 | 
			
		||||
		}
 | 
			
		||||
		var cvssScore string
 | 
			
		||||
		if d.CvssV2Score() <= 0 {
 | 
			
		||||
			cvssScore = "|   ?"
 | 
			
		||||
		} else {
 | 
			
		||||
			cvssScore = fmt.Sprintf("| %4.1f", d.CvssV2Score())
 | 
			
		||||
		}
 | 
			
		||||
		cols = []string{
 | 
			
		||||
			fmt.Sprintf(indexFormat, i+1),
 | 
			
		||||
			d.VulnInfo.CveID,
 | 
			
		||||
			cvssScore,
 | 
			
		||||
			fmt.Sprintf("| %3d |", d.VulnInfo.Confidence.Score),
 | 
			
		||||
			summary,
 | 
			
		||||
		}
 | 
			
		||||
		//  if config.Conf.Lang == "ja" && 0 < d.CveDetail.Jvn.CvssScore() {
 | 
			
		||||
		//      summary := d.CveDetail.Jvn.CveTitle()
 | 
			
		||||
		//      cols = []string{
 | 
			
		||||
		//          fmt.Sprintf(indexFormat, i+1),
 | 
			
		||||
		//          d.CveDetail.CveID,
 | 
			
		||||
		//          fmt.Sprintf("| %4.1f",
 | 
			
		||||
		//              d.CveDetail.CvssScore(config.Conf.Lang)),
 | 
			
		||||
		//          fmt.Sprintf("| %3d |", d.VulnInfo.Confidence.Score),
 | 
			
		||||
		//          summary,
 | 
			
		||||
		//      }
 | 
			
		||||
		//  } else {
 | 
			
		||||
		//      summary := d.CveDetail.Nvd.CveSummary()
 | 
			
		||||
	//  for i, d := range currentScanResult.AllCves() {
 | 
			
		||||
	//      var cols []string
 | 
			
		||||
	//      //TODO
 | 
			
		||||
	//      var summary string
 | 
			
		||||
	//      if cont, found := d.Get(models.NVD); found {
 | 
			
		||||
	//          summary = cont.Summary
 | 
			
		||||
	//      }
 | 
			
		||||
	//      var cvssScore string
 | 
			
		||||
	//      if d.CvssV2Score() <= 0 {
 | 
			
		||||
	//          cvssScore = "|   ?"
 | 
			
		||||
	//      } else {
 | 
			
		||||
	//          cvssScore = fmt.Sprintf("| %4.1f", d.CvssV2Score())
 | 
			
		||||
	//      }
 | 
			
		||||
	//      cols = []string{
 | 
			
		||||
	//          fmt.Sprintf(indexFormat, i+1),
 | 
			
		||||
	//          d.VulnInfo.CveID,
 | 
			
		||||
	//          cvssScore,
 | 
			
		||||
	//          fmt.Sprintf("| %3d |", d.VulnInfo.Confidence.Score),
 | 
			
		||||
	//          summary,
 | 
			
		||||
	//      }
 | 
			
		||||
	//      //  if config.Conf.Lang == "ja" && 0 < d.CveDetail.Jvn.CvssScore() {
 | 
			
		||||
	//      //      summary := d.CveDetail.Jvn.CveTitle()
 | 
			
		||||
	//      //      cols = []string{
 | 
			
		||||
	//      //          fmt.Sprintf(indexFormat, i+1),
 | 
			
		||||
	//      //          d.CveDetail.CveID,
 | 
			
		||||
	//      //          fmt.Sprintf("| %4.1f",
 | 
			
		||||
	//      //              d.CveDetail.CvssScore(config.Conf.Lang)),
 | 
			
		||||
	//      //          fmt.Sprintf("| %3d |", d.VulnInfo.Confidence.Score),
 | 
			
		||||
	//      //          summary,
 | 
			
		||||
	//      //      }
 | 
			
		||||
	//      //  } else {
 | 
			
		||||
	//      //      summary := d.CveDetail.Nvd.CveSummary()
 | 
			
		||||
 | 
			
		||||
		//      var cvssScore string
 | 
			
		||||
		//      if d.CveDetail.CvssScore("en") <= 0 {
 | 
			
		||||
		//          cvssScore = "|   ?"
 | 
			
		||||
		//      } else {
 | 
			
		||||
		//          cvssScore = fmt.Sprintf("| %4.1f",
 | 
			
		||||
		//              d.CveDetail.CvssScore(config.Conf.Lang))
 | 
			
		||||
		//      }
 | 
			
		||||
	//      //      var cvssScore string
 | 
			
		||||
	//      //      if d.CveDetail.CvssScore("en") <= 0 {
 | 
			
		||||
	//      //          cvssScore = "|   ?"
 | 
			
		||||
	//      //      } else {
 | 
			
		||||
	//      //          cvssScore = fmt.Sprintf("| %4.1f",
 | 
			
		||||
	//      //              d.CveDetail.CvssScore(config.Conf.Lang))
 | 
			
		||||
	//      //      }
 | 
			
		||||
 | 
			
		||||
		//      cols = []string{
 | 
			
		||||
		//          fmt.Sprintf(indexFormat, i+1),
 | 
			
		||||
		//          d.CveDetail.CveID,
 | 
			
		||||
		//          cvssScore,
 | 
			
		||||
		//          fmt.Sprintf("| %3d |", d.VulnInfo.Confidence.Score),
 | 
			
		||||
		//          summary,
 | 
			
		||||
		//      }
 | 
			
		||||
		//  }
 | 
			
		||||
	//      //      cols = []string{
 | 
			
		||||
	//      //          fmt.Sprintf(indexFormat, i+1),
 | 
			
		||||
	//      //          d.CveDetail.CveID,
 | 
			
		||||
	//      //          cvssScore,
 | 
			
		||||
	//      //          fmt.Sprintf("| %3d |", d.VulnInfo.Confidence.Score),
 | 
			
		||||
	//      //          summary,
 | 
			
		||||
	//      //      }
 | 
			
		||||
	//      //  }
 | 
			
		||||
 | 
			
		||||
		icols := make([]interface{}, len(cols))
 | 
			
		||||
		for j := range cols {
 | 
			
		||||
			icols[j] = cols[j]
 | 
			
		||||
		}
 | 
			
		||||
		stable.AddRow(icols...)
 | 
			
		||||
	}
 | 
			
		||||
	//      icols := make([]interface{}, len(cols))
 | 
			
		||||
	//      for j := range cols {
 | 
			
		||||
	//          icols[j] = cols[j]
 | 
			
		||||
	//      }
 | 
			
		||||
	//      stable.AddRow(icols...)
 | 
			
		||||
	//  }
 | 
			
		||||
	return fmt.Sprintf("%s", stable)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -712,19 +713,21 @@ func setChangelogLayout(g *gocui.Gui) error {
 | 
			
		||||
		if err != gocui.ErrUnknownView {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if len(currentScanResult.Errors) != 0 || len(currentScanResult.AllCves()) == 0 {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		//TODO
 | 
			
		||||
		//  if len(currentScanResult.Errors) != 0 || len(currentScanResult.AllCves()) == 0 {
 | 
			
		||||
		//      return nil
 | 
			
		||||
		//  }
 | 
			
		||||
 | 
			
		||||
		lines := []string{}
 | 
			
		||||
		cveInfo := currentScanResult.AllCves()[currentCveInfo]
 | 
			
		||||
		for _, pack := range cveInfo.Packages {
 | 
			
		||||
			for _, p := range currentScanResult.Packages {
 | 
			
		||||
				if pack.Name == p.Name {
 | 
			
		||||
					lines = append(lines, formatOneChangelog(p), "\n")
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		//TODO
 | 
			
		||||
		//  cveInfo := currentScanResult.AllCves()[currentCveInfo]
 | 
			
		||||
		//  for _, pack := range cveInfo.Packages {
 | 
			
		||||
		//      for _, p := range currentScanResult.Packages {
 | 
			
		||||
		//          if pack.Name == p.Name {
 | 
			
		||||
		//              lines = append(lines, formatOneChangelog(p), "\n")
 | 
			
		||||
		//          }
 | 
			
		||||
		//      }
 | 
			
		||||
		//  }
 | 
			
		||||
		text := strings.Join(lines, "\n")
 | 
			
		||||
		fmt.Fprint(v, text)
 | 
			
		||||
		v.Editable = false
 | 
			
		||||
@@ -756,20 +759,20 @@ func detailLines() (string, error) {
 | 
			
		||||
		return "", nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(currentScanResult.AllCves()) == 0 {
 | 
			
		||||
		return "No vulnerable packages", nil
 | 
			
		||||
	}
 | 
			
		||||
	//TODO
 | 
			
		||||
	//  if len(currentScanResult.AllCves()) == 0 {
 | 
			
		||||
	//      return "No vulnerable packages", nil
 | 
			
		||||
	//  }
 | 
			
		||||
	//  cveInfo := currentScanResult.AllCves()[currentCveInfo]
 | 
			
		||||
	//  cveID := cveInfo.VulnInfo.CveID
 | 
			
		||||
 | 
			
		||||
	cveInfo := currentScanResult.AllCves()[currentCveInfo]
 | 
			
		||||
	cveID := cveInfo.VulnInfo.CveID
 | 
			
		||||
	//  tmpl, err := template.New("detail").Parse(detailTemplate())
 | 
			
		||||
	//  if err != nil {
 | 
			
		||||
	//      return "", err
 | 
			
		||||
	//  }
 | 
			
		||||
 | 
			
		||||
	tmpl, err := template.New("detail").Parse(detailTemplate())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var cvssSeverity, cvssVector, summary string
 | 
			
		||||
	var refs []cve.Reference
 | 
			
		||||
	//  var cvssSeverity, cvssVector, summary string
 | 
			
		||||
	//  var refs []cve.Reference
 | 
			
		||||
	switch {
 | 
			
		||||
	//TODO
 | 
			
		||||
	//  case config.Conf.Lang == "ja" &&
 | 
			
		||||
@@ -780,67 +783,67 @@ func detailLines() (string, error) {
 | 
			
		||||
	//      summary = fmt.Sprintf("%s\n%s", jvn.CveTitle(), jvn.CveSummary())
 | 
			
		||||
	//      refs = jvn.VulnSiteReferences()
 | 
			
		||||
	default:
 | 
			
		||||
		var nvd *models.CveContent
 | 
			
		||||
		if cont, found := cveInfo.Get(models.NVD); found {
 | 
			
		||||
			nvd = cont
 | 
			
		||||
		}
 | 
			
		||||
		//  var nvd *models.CveContent
 | 
			
		||||
		//TODO
 | 
			
		||||
		//  if cont, found := cveInfo.Get(models.NVD); found {
 | 
			
		||||
		//      nvd = cont
 | 
			
		||||
		//  }
 | 
			
		||||
		//  cvssSeverity = nvd.CvssSeverity()
 | 
			
		||||
		//  cvssVector = nvd.CvssVector()
 | 
			
		||||
		summary = nvd.Summary
 | 
			
		||||
		//  summary = nvd.Summary
 | 
			
		||||
		//  refs = nvd.VulnSiteReferences()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//TODO
 | 
			
		||||
	//  cweURL := cweURL(cveInfo.CveDetail.CweID())
 | 
			
		||||
 | 
			
		||||
	links := []string{
 | 
			
		||||
		fmt.Sprintf("[NVD]( %s )", fmt.Sprintf("%s/%s", nvdBaseURL, cveID)),
 | 
			
		||||
		fmt.Sprintf("[MITRE]( %s )", fmt.Sprintf("%s%s", mitreBaseURL, cveID)),
 | 
			
		||||
		fmt.Sprintf("[CveDetais]( %s )", fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID)),
 | 
			
		||||
		fmt.Sprintf("[CVSSv2 Calc]( %s )", fmt.Sprintf(cvssV2CalcBaseURL, cveID)),
 | 
			
		||||
		fmt.Sprintf("[CVSSv3 Calc]( %s )", fmt.Sprintf(cvssV3CalcBaseURL, cveID)),
 | 
			
		||||
	}
 | 
			
		||||
	dlinks := distroLinks(cveInfo, currentScanResult.Family)
 | 
			
		||||
	for _, link := range dlinks {
 | 
			
		||||
		links = append(links, fmt.Sprintf("[%s]( %s )", link.title, link.url))
 | 
			
		||||
	}
 | 
			
		||||
	//  links := []string{
 | 
			
		||||
	//      fmt.Sprintf("[NVD]( %s )", fmt.Sprintf("%s/%s", nvdBaseURL, cveID)),
 | 
			
		||||
	//      fmt.Sprintf("[MITRE]( %s )", fmt.Sprintf("%s%s", mitreBaseURL, cveID)),
 | 
			
		||||
	//      fmt.Sprintf("[CveDetais]( %s )", fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID)),
 | 
			
		||||
	//      fmt.Sprintf("[CVSSv2 Calc]( %s )", fmt.Sprintf(cvssV2CalcBaseURL, cveID)),
 | 
			
		||||
	//      fmt.Sprintf("[CVSSv3 Calc]( %s )", fmt.Sprintf(cvssV3CalcBaseURL, cveID)),
 | 
			
		||||
	//  }
 | 
			
		||||
	//  dlinks := distroLinks(cveInfo, currentScanResult.Family)
 | 
			
		||||
	//  for _, link := range dlinks {
 | 
			
		||||
	//      links = append(links, fmt.Sprintf("[%s]( %s )", link.title, link.url))
 | 
			
		||||
	//  }
 | 
			
		||||
 | 
			
		||||
	//TODO
 | 
			
		||||
	var cvssScore string
 | 
			
		||||
	if cveInfo.CvssV2Score() == -1 {
 | 
			
		||||
		cvssScore = "?"
 | 
			
		||||
		//  } else {
 | 
			
		||||
		//      cvssScore = fmt.Sprintf("%4.1f", cveInfo.CveDetail.CvssScore(config.Conf.Lang))
 | 
			
		||||
	}
 | 
			
		||||
	//  var cvssScore string
 | 
			
		||||
	//  if cveInfo.CvssV2Score() == -1 {
 | 
			
		||||
	//      cvssScore = "?"
 | 
			
		||||
	//      //  } else {
 | 
			
		||||
	//      //      cvssScore = fmt.Sprintf("%4.1f", cveInfo.CveDetail.CvssScore(config.Conf.Lang))
 | 
			
		||||
	//  }
 | 
			
		||||
 | 
			
		||||
	packages := []string{}
 | 
			
		||||
	for _, pack := range cveInfo.Packages {
 | 
			
		||||
		packages = append(packages,
 | 
			
		||||
			fmt.Sprintf(
 | 
			
		||||
				"%s -> %s",
 | 
			
		||||
				pack.FormatCurrentVer(),
 | 
			
		||||
				pack.FormatNewVer()))
 | 
			
		||||
	}
 | 
			
		||||
	//  packages := []string{}
 | 
			
		||||
	//  for _, pack := range cveInfo.Packages {
 | 
			
		||||
	//      packages = append(packages,
 | 
			
		||||
	//          fmt.Sprintf(
 | 
			
		||||
	//              "%s -> %s",
 | 
			
		||||
	//              pack.FormatCurrentVer(),
 | 
			
		||||
	//              pack.FormatNewVer()))
 | 
			
		||||
	//  }
 | 
			
		||||
 | 
			
		||||
	data := dataForTmpl{
 | 
			
		||||
		CveID:        cveID,
 | 
			
		||||
		CvssScore:    cvssScore,
 | 
			
		||||
		CvssSeverity: cvssSeverity,
 | 
			
		||||
		CvssVector:   cvssVector,
 | 
			
		||||
		Summary:      summary,
 | 
			
		||||
		Confidence:   cveInfo.VulnInfo.Confidence,
 | 
			
		||||
		//TODO
 | 
			
		||||
		//  CweURL:        cweURL,
 | 
			
		||||
		VulnSiteLinks: links,
 | 
			
		||||
		References:    refs,
 | 
			
		||||
		Packages:      packages,
 | 
			
		||||
		CpeNames:      cveInfo.CpeNames,
 | 
			
		||||
	}
 | 
			
		||||
	//  data := dataForTmpl{
 | 
			
		||||
	//      CveID:        cveID,
 | 
			
		||||
	//      CvssScore:    cvssScore,
 | 
			
		||||
	//      CvssSeverity: cvssSeverity,
 | 
			
		||||
	//      CvssVector:   cvssVector,
 | 
			
		||||
	//      Summary:      summary,
 | 
			
		||||
	//      Confidence:   cveInfo.VulnInfo.Confidence,
 | 
			
		||||
	//      //TODO
 | 
			
		||||
	//      //  CweURL:        cweURL,
 | 
			
		||||
	//      VulnSiteLinks: links,
 | 
			
		||||
	//      References:    refs,
 | 
			
		||||
	//      Packages:      packages,
 | 
			
		||||
	//      CpeNames:      cveInfo.CpeNames,
 | 
			
		||||
	//  }
 | 
			
		||||
 | 
			
		||||
	buf := bytes.NewBuffer(nil) // create empty buffer
 | 
			
		||||
	if err := tmpl.Execute(buf, data); err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	//  if err := tmpl.Execute(buf, data); err != nil {
 | 
			
		||||
	//      return "", err
 | 
			
		||||
	//  }
 | 
			
		||||
 | 
			
		||||
	return string(buf.Bytes()), nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										547
									
								
								report/util.go
									
									
									
									
									
								
							
							
						
						
									
										547
									
								
								report/util.go
									
									
									
									
									
								
							@@ -22,7 +22,6 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/future-architect/vuls/config"
 | 
			
		||||
	"github.com/future-architect/vuls/models"
 | 
			
		||||
	"github.com/gosuri/uitable"
 | 
			
		||||
)
 | 
			
		||||
@@ -84,10 +83,11 @@ func formatShortPlainText(r models.ScanResult) string {
 | 
			
		||||
	stable.MaxColWidth = maxColWidth
 | 
			
		||||
	stable.Wrap = true
 | 
			
		||||
 | 
			
		||||
	cves := r.KnownCves
 | 
			
		||||
	if !config.Conf.IgnoreUnscoredCves {
 | 
			
		||||
		cves = append(cves, r.UnknownCves...)
 | 
			
		||||
	}
 | 
			
		||||
	//TODO
 | 
			
		||||
	//  cves := r.KnownCves
 | 
			
		||||
	//  if !config.Conf.IgnoreUnscoredCves {
 | 
			
		||||
	//      cves = append(cves, r.UnknownCves...)
 | 
			
		||||
	//  }
 | 
			
		||||
 | 
			
		||||
	var buf bytes.Buffer
 | 
			
		||||
	for i := 0; i < len(r.ServerInfo()); i++ {
 | 
			
		||||
@@ -106,83 +106,84 @@ func formatShortPlainText(r models.ScanResult) string {
 | 
			
		||||
			header, r.Errors)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(cves) == 0 {
 | 
			
		||||
		return fmt.Sprintf(`
 | 
			
		||||
%s
 | 
			
		||||
No CVE-IDs are found in updatable packages.
 | 
			
		||||
%s
 | 
			
		||||
`, header, r.Packages.FormatUpdatablePacksSummary())
 | 
			
		||||
	}
 | 
			
		||||
	//TODO
 | 
			
		||||
	//      if len(cves) == 0 {
 | 
			
		||||
	//          return fmt.Sprintf(`
 | 
			
		||||
	//  %s
 | 
			
		||||
	//  No CVE-IDs are found in updatable packages.
 | 
			
		||||
	//  %s
 | 
			
		||||
	//  `, header, r.Packages.FormatUpdatablePacksSummary())
 | 
			
		||||
	//      }
 | 
			
		||||
 | 
			
		||||
	for _, d := range cves {
 | 
			
		||||
		var packsVer string
 | 
			
		||||
		for _, p := range d.Packages {
 | 
			
		||||
			packsVer += fmt.Sprintf(
 | 
			
		||||
				"%s -> %s\n", p.FormatCurrentVer(), p.FormatNewVer())
 | 
			
		||||
		}
 | 
			
		||||
		for _, n := range d.CpeNames {
 | 
			
		||||
			packsVer += n
 | 
			
		||||
		}
 | 
			
		||||
	//      for _, d := range cves {
 | 
			
		||||
	//          var packsVer string
 | 
			
		||||
	//          for _, p := range d.Packages {
 | 
			
		||||
	//              packsVer += fmt.Sprintf(
 | 
			
		||||
	//                  "%s -> %s\n", p.FormatCurrentVer(), p.FormatNewVer())
 | 
			
		||||
	//          }
 | 
			
		||||
	//          for _, n := range d.CpeNames {
 | 
			
		||||
	//              packsVer += n
 | 
			
		||||
	//          }
 | 
			
		||||
 | 
			
		||||
		var scols []string
 | 
			
		||||
		switch {
 | 
			
		||||
		//  case config.Conf.Lang == "ja" &&
 | 
			
		||||
		//TODO
 | 
			
		||||
		//  0 < d.CveDetail.Jvn.CvssScore():
 | 
			
		||||
		//  summary := fmt.Sprintf("%s\n%s\n%s\n%sConfidence: %v",
 | 
			
		||||
		//      d.CveDetail.Jvn.CveTitle(),
 | 
			
		||||
		//      d.CveDetail.Jvn.Link(),
 | 
			
		||||
		//      distroLinks(d, r.Family)[0].url,
 | 
			
		||||
		//      packsVer,
 | 
			
		||||
		//      d.VulnInfo.Confidence,
 | 
			
		||||
		//  )
 | 
			
		||||
		//  scols = []string{
 | 
			
		||||
		//      d.CveDetail.CveID,
 | 
			
		||||
		//      fmt.Sprintf("%-4.1f (%s)",
 | 
			
		||||
		//          d.CveDetail.CvssScore(config.Conf.Lang),
 | 
			
		||||
		//          d.CveDetail.Jvn.CvssSeverity(),
 | 
			
		||||
		//      ),
 | 
			
		||||
		//      summary,
 | 
			
		||||
		//  }
 | 
			
		||||
	//          var scols []string
 | 
			
		||||
	//          switch {
 | 
			
		||||
	//          //  case config.Conf.Lang == "ja" &&
 | 
			
		||||
	//          //TODO
 | 
			
		||||
	//          //  0 < d.CveDetail.Jvn.CvssScore():
 | 
			
		||||
	//          //  summary := fmt.Sprintf("%s\n%s\n%s\n%sConfidence: %v",
 | 
			
		||||
	//          //      d.CveDetail.Jvn.CveTitle(),
 | 
			
		||||
	//          //      d.CveDetail.Jvn.Link(),
 | 
			
		||||
	//          //      distroLinks(d, r.Family)[0].url,
 | 
			
		||||
	//          //      packsVer,
 | 
			
		||||
	//          //      d.VulnInfo.Confidence,
 | 
			
		||||
	//          //  )
 | 
			
		||||
	//          //  scols = []string{
 | 
			
		||||
	//          //      d.CveDetail.CveID,
 | 
			
		||||
	//          //      fmt.Sprintf("%-4.1f (%s)",
 | 
			
		||||
	//          //          d.CveDetail.CvssScore(config.Conf.Lang),
 | 
			
		||||
	//          //          d.CveDetail.Jvn.CvssSeverity(),
 | 
			
		||||
	//          //      ),
 | 
			
		||||
	//          //      summary,
 | 
			
		||||
	//          //  }
 | 
			
		||||
 | 
			
		||||
		case 0 < d.CvssV2Score():
 | 
			
		||||
			var nvd *models.CveContent
 | 
			
		||||
			if cont, found := d.Get(models.NVD); found {
 | 
			
		||||
				nvd = cont
 | 
			
		||||
			}
 | 
			
		||||
			summary := fmt.Sprintf("%s\n%s/%s\n%s\n%sConfidence: %v",
 | 
			
		||||
				nvd.Summary,
 | 
			
		||||
				cveDetailsBaseURL,
 | 
			
		||||
				d.VulnInfo.CveID,
 | 
			
		||||
				distroLinks(d, r.Family)[0].url,
 | 
			
		||||
				packsVer,
 | 
			
		||||
				d.VulnInfo.Confidence,
 | 
			
		||||
			)
 | 
			
		||||
			scols = []string{
 | 
			
		||||
				d.VulnInfo.CveID,
 | 
			
		||||
				fmt.Sprintf("%-4.1f (%s)",
 | 
			
		||||
					d.CvssV2Score(),
 | 
			
		||||
					"TODO",
 | 
			
		||||
				),
 | 
			
		||||
				summary,
 | 
			
		||||
			}
 | 
			
		||||
		default:
 | 
			
		||||
			summary := fmt.Sprintf("%s\n%sConfidence: %v",
 | 
			
		||||
				distroLinks(d, r.Family)[0].url, packsVer, d.VulnInfo.Confidence)
 | 
			
		||||
			scols = []string{
 | 
			
		||||
				d.VulnInfo.CveID,
 | 
			
		||||
				"?",
 | 
			
		||||
				summary,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	//          case 0 < d.CvssV2Score():
 | 
			
		||||
	//              var nvd *models.CveContent
 | 
			
		||||
	//              if cont, found := d.Get(models.NVD); found {
 | 
			
		||||
	//                  nvd = cont
 | 
			
		||||
	//              }
 | 
			
		||||
	//              summary := fmt.Sprintf("%s\n%s/%s\n%s\n%sConfidence: %v",
 | 
			
		||||
	//                  nvd.Summary,
 | 
			
		||||
	//                  cveDetailsBaseURL,
 | 
			
		||||
	//                  d.VulnInfo.CveID,
 | 
			
		||||
	//                  distroLinks(d, r.Family)[0].url,
 | 
			
		||||
	//                  packsVer,
 | 
			
		||||
	//                  d.VulnInfo.Confidence,
 | 
			
		||||
	//              )
 | 
			
		||||
	//              scols = []string{
 | 
			
		||||
	//                  d.VulnInfo.CveID,
 | 
			
		||||
	//                  fmt.Sprintf("%-4.1f (%s)",
 | 
			
		||||
	//                      d.CvssV2Score(),
 | 
			
		||||
	//                      "TODO",
 | 
			
		||||
	//                  ),
 | 
			
		||||
	//                  summary,
 | 
			
		||||
	//              }
 | 
			
		||||
	//          default:
 | 
			
		||||
	//              summary := fmt.Sprintf("%s\n%sConfidence: %v",
 | 
			
		||||
	//                  distroLinks(d, r.Family)[0].url, packsVer, d.VulnInfo.Confidence)
 | 
			
		||||
	//              scols = []string{
 | 
			
		||||
	//                  d.VulnInfo.CveID,
 | 
			
		||||
	//                  "?",
 | 
			
		||||
	//                  summary,
 | 
			
		||||
	//              }
 | 
			
		||||
	//          }
 | 
			
		||||
 | 
			
		||||
		cols := make([]interface{}, len(scols))
 | 
			
		||||
		for i := range cols {
 | 
			
		||||
			cols[i] = scols[i]
 | 
			
		||||
		}
 | 
			
		||||
		stable.AddRow(cols...)
 | 
			
		||||
		stable.AddRow("")
 | 
			
		||||
	}
 | 
			
		||||
	//          cols := make([]interface{}, len(scols))
 | 
			
		||||
	//          for i := range cols {
 | 
			
		||||
	//              cols[i] = scols[i]
 | 
			
		||||
	//          }
 | 
			
		||||
	//          stable.AddRow(cols...)
 | 
			
		||||
	//          stable.AddRow("")
 | 
			
		||||
	//      }
 | 
			
		||||
	return fmt.Sprintf("%s\n%s\n", header, stable)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -206,32 +207,34 @@ func formatFullPlainText(r models.ScanResult) string {
 | 
			
		||||
			header, r.Errors)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(r.KnownCves) == 0 && len(r.UnknownCves) == 0 {
 | 
			
		||||
		return fmt.Sprintf(`
 | 
			
		||||
%s
 | 
			
		||||
No CVE-IDs are found in updatable packages.
 | 
			
		||||
%s
 | 
			
		||||
`, header, r.Packages.FormatUpdatablePacksSummary())
 | 
			
		||||
	}
 | 
			
		||||
	//TODO
 | 
			
		||||
	//      if len(r.KnownCves) == 0 && len(r.UnknownCves) == 0 {
 | 
			
		||||
	//          return fmt.Sprintf(`
 | 
			
		||||
	//  %s
 | 
			
		||||
	//  No CVE-IDs are found in updatable packages.
 | 
			
		||||
	//  %s
 | 
			
		||||
	//  `, header, r.Packages.FormatUpdatablePacksSummary())
 | 
			
		||||
	//      }
 | 
			
		||||
 | 
			
		||||
	scoredReport, unscoredReport := []string{}, []string{}
 | 
			
		||||
	scoredReport, unscoredReport = formatPlainTextDetails(r, r.Family)
 | 
			
		||||
	//      scoredReport, unscoredReport := []string{}, []string{}
 | 
			
		||||
	//      scoredReport, unscoredReport = formatPlainTextDetails(r, r.Family)
 | 
			
		||||
 | 
			
		||||
	unscored := ""
 | 
			
		||||
	if !config.Conf.IgnoreUnscoredCves {
 | 
			
		||||
		unscored = strings.Join(unscoredReport, "\n\n")
 | 
			
		||||
	}
 | 
			
		||||
	//      unscored := ""
 | 
			
		||||
	//      if !config.Conf.IgnoreUnscoredCves {
 | 
			
		||||
	//          unscored = strings.Join(unscoredReport, "\n\n")
 | 
			
		||||
	//      }
 | 
			
		||||
 | 
			
		||||
	scored := strings.Join(scoredReport, "\n\n")
 | 
			
		||||
	detail := fmt.Sprintf(`
 | 
			
		||||
%s
 | 
			
		||||
	//      scored := strings.Join(scoredReport, "\n\n")
 | 
			
		||||
	//      detail := fmt.Sprintf(`
 | 
			
		||||
	//  %s
 | 
			
		||||
 | 
			
		||||
%s
 | 
			
		||||
`,
 | 
			
		||||
		scored,
 | 
			
		||||
		unscored,
 | 
			
		||||
	)
 | 
			
		||||
	return fmt.Sprintf("%s\n%s\n%s", header, detail, formatChangelogs(r))
 | 
			
		||||
	//  %s
 | 
			
		||||
	//  `,
 | 
			
		||||
	//          scored,
 | 
			
		||||
	//          unscored,
 | 
			
		||||
	//      )
 | 
			
		||||
	//  return fmt.Sprintf("%s\n%s\n%s", header, detail, formatChangelogs(r))
 | 
			
		||||
	return ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//TODO
 | 
			
		||||
@@ -266,116 +269,116 @@ func formatPlainTextDetails(r models.ScanResult, osFamily string) (scoredReport,
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func formatPlainTextUnknownCve(cveInfo models.CveInfo, osFamily string) string {
 | 
			
		||||
	cveID := cveInfo.VulnInfo.CveID
 | 
			
		||||
	dtable := uitable.New()
 | 
			
		||||
	dtable.MaxColWidth = maxColWidth
 | 
			
		||||
	dtable.Wrap = true
 | 
			
		||||
	dtable.AddRow(cveID)
 | 
			
		||||
	dtable.AddRow("-------------")
 | 
			
		||||
	dtable.AddRow("Score", "?")
 | 
			
		||||
	dtable.AddRow("NVD", fmt.Sprintf("%s/%s", nvdBaseURL, cveID))
 | 
			
		||||
	dlinks := distroLinks(cveInfo, osFamily)
 | 
			
		||||
	for _, link := range dlinks {
 | 
			
		||||
		dtable.AddRow(link.title, link.url)
 | 
			
		||||
	}
 | 
			
		||||
	dtable.AddRow("CVE Details", fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID))
 | 
			
		||||
	dtable = addPackageInfos(dtable, cveInfo.Packages)
 | 
			
		||||
	dtable = addCpeNames(dtable, cveInfo.CpeNames)
 | 
			
		||||
	dtable.AddRow("Confidence", cveInfo.VulnInfo.Confidence)
 | 
			
		||||
//  func formatPlainTextUnknownCve(cveInfo models.CveInfo, osFamily string) string {
 | 
			
		||||
//      cveID := cveInfo.VulnInfo.CveID
 | 
			
		||||
//      dtable := uitable.New()
 | 
			
		||||
//      dtable.MaxColWidth = maxColWidth
 | 
			
		||||
//      dtable.Wrap = true
 | 
			
		||||
//      dtable.AddRow(cveID)
 | 
			
		||||
//      dtable.AddRow("-------------")
 | 
			
		||||
//      dtable.AddRow("Score", "?")
 | 
			
		||||
//      dtable.AddRow("NVD", fmt.Sprintf("%s/%s", nvdBaseURL, cveID))
 | 
			
		||||
//      dlinks := distroLinks(cveInfo, osFamily)
 | 
			
		||||
//      for _, link := range dlinks {
 | 
			
		||||
//          dtable.AddRow(link.title, link.url)
 | 
			
		||||
//      }
 | 
			
		||||
//      dtable.AddRow("CVE Details", fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID))
 | 
			
		||||
//      dtable = addPackageInfos(dtable, cveInfo.Packages)
 | 
			
		||||
//      dtable = addCpeNames(dtable, cveInfo.CpeNames)
 | 
			
		||||
//      dtable.AddRow("Confidence", cveInfo.VulnInfo.Confidence)
 | 
			
		||||
 | 
			
		||||
	return fmt.Sprintf("%s", dtable)
 | 
			
		||||
}
 | 
			
		||||
//      return fmt.Sprintf("%s", dtable)
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
//TODO
 | 
			
		||||
func formatPlainTextDetailsLangJa(cveInfo models.CveInfo, osFamily string) string {
 | 
			
		||||
	return "TODO"
 | 
			
		||||
	//  cveDetail := cveInfo.CveDetail
 | 
			
		||||
	//  cveID := cveDetail.CveID
 | 
			
		||||
	//  jvn := cveDetail.Jvn
 | 
			
		||||
//  func formatPlainTextDetailsLangJa(cveInfo models.CveInfo, osFamily string) string {
 | 
			
		||||
//  return "TODO"
 | 
			
		||||
//  cveDetail := cveInfo.CveDetail
 | 
			
		||||
//  cveID := cveDetail.CveID
 | 
			
		||||
//  jvn := cveDetail.Jvn
 | 
			
		||||
 | 
			
		||||
	//  dtable := uitable.New()
 | 
			
		||||
	//  dtable.MaxColWidth = maxColWidth
 | 
			
		||||
	//  dtable.Wrap = true
 | 
			
		||||
	//  dtable.AddRow(cveID)
 | 
			
		||||
	//  dtable.AddRow("-------------")
 | 
			
		||||
	//  if score := cveDetail.Jvn.CvssScore(); 0 < score {
 | 
			
		||||
	//      dtable.AddRow("Score",
 | 
			
		||||
	//          fmt.Sprintf("%4.1f (%s)",
 | 
			
		||||
	//              cveDetail.Jvn.CvssScore(),
 | 
			
		||||
	//              jvn.CvssSeverity(),
 | 
			
		||||
	//          ))
 | 
			
		||||
	//  } else {
 | 
			
		||||
	//      dtable.AddRow("Score", "?")
 | 
			
		||||
	//  }
 | 
			
		||||
	//  dtable.AddRow("Vector", jvn.CvssVector())
 | 
			
		||||
	//  dtable.AddRow("Title", jvn.CveTitle())
 | 
			
		||||
	//  dtable.AddRow("Description", jvn.CveSummary())
 | 
			
		||||
	//  dtable.AddRow(cveDetail.CweID(), cweURL(cveDetail.CweID()))
 | 
			
		||||
	//  dtable.AddRow(cveDetail.CweID()+"(JVN)", cweJvnURL(cveDetail.CweID()))
 | 
			
		||||
//  dtable := uitable.New()
 | 
			
		||||
//  dtable.MaxColWidth = maxColWidth
 | 
			
		||||
//  dtable.Wrap = true
 | 
			
		||||
//  dtable.AddRow(cveID)
 | 
			
		||||
//  dtable.AddRow("-------------")
 | 
			
		||||
//  if score := cveDetail.Jvn.CvssScore(); 0 < score {
 | 
			
		||||
//      dtable.AddRow("Score",
 | 
			
		||||
//          fmt.Sprintf("%4.1f (%s)",
 | 
			
		||||
//              cveDetail.Jvn.CvssScore(),
 | 
			
		||||
//              jvn.CvssSeverity(),
 | 
			
		||||
//          ))
 | 
			
		||||
//  } else {
 | 
			
		||||
//      dtable.AddRow("Score", "?")
 | 
			
		||||
//  }
 | 
			
		||||
//  dtable.AddRow("Vector", jvn.CvssVector())
 | 
			
		||||
//  dtable.AddRow("Title", jvn.CveTitle())
 | 
			
		||||
//  dtable.AddRow("Description", jvn.CveSummary())
 | 
			
		||||
//  dtable.AddRow(cveDetail.CweID(), cweURL(cveDetail.CweID()))
 | 
			
		||||
//  dtable.AddRow(cveDetail.CweID()+"(JVN)", cweJvnURL(cveDetail.CweID()))
 | 
			
		||||
 | 
			
		||||
	//  dtable.AddRow("JVN", jvn.Link())
 | 
			
		||||
	//  dtable.AddRow("NVD", fmt.Sprintf("%s/%s", nvdBaseURL, cveID))
 | 
			
		||||
	//  dtable.AddRow("MITRE", fmt.Sprintf("%s%s", mitreBaseURL, cveID))
 | 
			
		||||
	//  dtable.AddRow("CVE Details", fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID))
 | 
			
		||||
	//  dtable.AddRow("CVSSv2 Clac", fmt.Sprintf(cvssV2CalcBaseURL, cveID))
 | 
			
		||||
	//  dtable.AddRow("CVSSv3 Clac", fmt.Sprintf(cvssV3CalcBaseURL, cveID))
 | 
			
		||||
//  dtable.AddRow("JVN", jvn.Link())
 | 
			
		||||
//  dtable.AddRow("NVD", fmt.Sprintf("%s/%s", nvdBaseURL, cveID))
 | 
			
		||||
//  dtable.AddRow("MITRE", fmt.Sprintf("%s%s", mitreBaseURL, cveID))
 | 
			
		||||
//  dtable.AddRow("CVE Details", fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID))
 | 
			
		||||
//  dtable.AddRow("CVSSv2 Clac", fmt.Sprintf(cvssV2CalcBaseURL, cveID))
 | 
			
		||||
//  dtable.AddRow("CVSSv3 Clac", fmt.Sprintf(cvssV3CalcBaseURL, cveID))
 | 
			
		||||
 | 
			
		||||
	//  dlinks := distroLinks(cveInfo, osFamily)
 | 
			
		||||
	//  for _, link := range dlinks {
 | 
			
		||||
	//      dtable.AddRow(link.title, link.url)
 | 
			
		||||
	//  }
 | 
			
		||||
//  dlinks := distroLinks(cveInfo, osFamily)
 | 
			
		||||
//  for _, link := range dlinks {
 | 
			
		||||
//      dtable.AddRow(link.title, link.url)
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
	//  dtable = addPackageInfos(dtable, cveInfo.Packages)
 | 
			
		||||
	//  dtable = addCpeNames(dtable, cveInfo.CpeNames)
 | 
			
		||||
	//  dtable.AddRow("Confidence", cveInfo.VulnInfo.Confidence)
 | 
			
		||||
//  dtable = addPackageInfos(dtable, cveInfo.Packages)
 | 
			
		||||
//  dtable = addCpeNames(dtable, cveInfo.CpeNames)
 | 
			
		||||
//  dtable.AddRow("Confidence", cveInfo.VulnInfo.Confidence)
 | 
			
		||||
 | 
			
		||||
	//  return fmt.Sprintf("%s", dtable)
 | 
			
		||||
}
 | 
			
		||||
//  return fmt.Sprintf("%s", dtable)
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
//TODO
 | 
			
		||||
func formatPlainTextDetailsLangEn(d models.CveInfo, osFamily string) string {
 | 
			
		||||
	return ""
 | 
			
		||||
	//  cveDetail := d.CveDetail
 | 
			
		||||
	//  cveID := cveDetail.CveID
 | 
			
		||||
	//  nvd := cveDetail.Nvd
 | 
			
		||||
//  func formatPlainTextDetailsLangEn(d models.CveInfo, osFamily string) string {
 | 
			
		||||
//  return ""
 | 
			
		||||
//  cveDetail := d.CveDetail
 | 
			
		||||
//  cveID := cveDetail.CveID
 | 
			
		||||
//  nvd := cveDetail.Nvd
 | 
			
		||||
 | 
			
		||||
	//  dtable := uitable.New()
 | 
			
		||||
	//  dtable.MaxColWidth = maxColWidth
 | 
			
		||||
	//  dtable.Wrap = true
 | 
			
		||||
	//  dtable.AddRow(cveID)
 | 
			
		||||
	//  dtable.AddRow("-------------")
 | 
			
		||||
//  dtable := uitable.New()
 | 
			
		||||
//  dtable.MaxColWidth = maxColWidth
 | 
			
		||||
//  dtable.Wrap = true
 | 
			
		||||
//  dtable.AddRow(cveID)
 | 
			
		||||
//  dtable.AddRow("-------------")
 | 
			
		||||
 | 
			
		||||
	//  if score := cveDetail.Nvd.CvssScore(); 0 < score {
 | 
			
		||||
	//      dtable.AddRow("Score",
 | 
			
		||||
	//          fmt.Sprintf("%4.1f (%s)",
 | 
			
		||||
	//              cveDetail.Nvd.CvssScore(),
 | 
			
		||||
	//              nvd.CvssSeverity(),
 | 
			
		||||
	//          ))
 | 
			
		||||
	//  } else {
 | 
			
		||||
	//      dtable.AddRow("Score", "?")
 | 
			
		||||
	//  }
 | 
			
		||||
//  if score := cveDetail.Nvd.CvssScore(); 0 < score {
 | 
			
		||||
//      dtable.AddRow("Score",
 | 
			
		||||
//          fmt.Sprintf("%4.1f (%s)",
 | 
			
		||||
//              cveDetail.Nvd.CvssScore(),
 | 
			
		||||
//              nvd.CvssSeverity(),
 | 
			
		||||
//          ))
 | 
			
		||||
//  } else {
 | 
			
		||||
//      dtable.AddRow("Score", "?")
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
	//  dtable.AddRow("Vector", nvd.CvssVector())
 | 
			
		||||
	//  dtable.AddRow("Summary", nvd.CveSummary())
 | 
			
		||||
	//  dtable.AddRow("CWE", cweURL(cveDetail.CweID()))
 | 
			
		||||
//  dtable.AddRow("Vector", nvd.CvssVector())
 | 
			
		||||
//  dtable.AddRow("Summary", nvd.CveSummary())
 | 
			
		||||
//  dtable.AddRow("CWE", cweURL(cveDetail.CweID()))
 | 
			
		||||
 | 
			
		||||
	//  dtable.AddRow("NVD", fmt.Sprintf("%s/%s", nvdBaseURL, cveID))
 | 
			
		||||
	//  dtable.AddRow("MITRE", fmt.Sprintf("%s%s", mitreBaseURL, cveID))
 | 
			
		||||
	//  dtable.AddRow("CVE Details", fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID))
 | 
			
		||||
	//  dtable.AddRow("CVSSv2 Clac", fmt.Sprintf(cvssV2CalcBaseURL, cveID))
 | 
			
		||||
	//  dtable.AddRow("CVSSv3 Clac", fmt.Sprintf(cvssV3CalcBaseURL, cveID))
 | 
			
		||||
//  dtable.AddRow("NVD", fmt.Sprintf("%s/%s", nvdBaseURL, cveID))
 | 
			
		||||
//  dtable.AddRow("MITRE", fmt.Sprintf("%s%s", mitreBaseURL, cveID))
 | 
			
		||||
//  dtable.AddRow("CVE Details", fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID))
 | 
			
		||||
//  dtable.AddRow("CVSSv2 Clac", fmt.Sprintf(cvssV2CalcBaseURL, cveID))
 | 
			
		||||
//  dtable.AddRow("CVSSv3 Clac", fmt.Sprintf(cvssV3CalcBaseURL, cveID))
 | 
			
		||||
 | 
			
		||||
	//  links := distroLinks(d, osFamily)
 | 
			
		||||
	//  for _, link := range links {
 | 
			
		||||
	//      dtable.AddRow(link.title, link.url)
 | 
			
		||||
	//  }
 | 
			
		||||
	//  dtable = addPackageInfos(dtable, d.Packages)
 | 
			
		||||
	//  dtable = addCpeNames(dtable, d.CpeNames)
 | 
			
		||||
	//  dtable.AddRow("Confidence", d.VulnInfo.Confidence)
 | 
			
		||||
//  links := distroLinks(d, osFamily)
 | 
			
		||||
//  for _, link := range links {
 | 
			
		||||
//      dtable.AddRow(link.title, link.url)
 | 
			
		||||
//  }
 | 
			
		||||
//  dtable = addPackageInfos(dtable, d.Packages)
 | 
			
		||||
//  dtable = addCpeNames(dtable, d.CpeNames)
 | 
			
		||||
//  dtable.AddRow("Confidence", d.VulnInfo.Confidence)
 | 
			
		||||
 | 
			
		||||
	//  return fmt.Sprintf("%s\n", dtable)
 | 
			
		||||
}
 | 
			
		||||
//  return fmt.Sprintf("%s\n", dtable)
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
type distroLink struct {
 | 
			
		||||
	title string
 | 
			
		||||
@@ -383,84 +386,84 @@ type distroLink struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// distroLinks add Vendor URL of the CVE to table
 | 
			
		||||
func distroLinks(cveInfo models.CveInfo, osFamily string) []distroLink {
 | 
			
		||||
	cveID := cveInfo.VulnInfo.CveID
 | 
			
		||||
	switch osFamily {
 | 
			
		||||
	case "rhel", "centos":
 | 
			
		||||
		links := []distroLink{
 | 
			
		||||
			{
 | 
			
		||||
				"RHEL-CVE",
 | 
			
		||||
				fmt.Sprintf("%s/%s", redhatSecurityBaseURL, cveID),
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
		for _, advisory := range cveInfo.DistroAdvisories {
 | 
			
		||||
			aidURL := strings.Replace(advisory.AdvisoryID, ":", "-", -1)
 | 
			
		||||
			links = append(links, distroLink{
 | 
			
		||||
				//  "RHEL-errata",
 | 
			
		||||
				advisory.AdvisoryID,
 | 
			
		||||
				fmt.Sprintf(redhatRHSABaseBaseURL, aidURL),
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
		return links
 | 
			
		||||
	case "oraclelinux":
 | 
			
		||||
		links := []distroLink{
 | 
			
		||||
			{
 | 
			
		||||
				"Oracle-CVE",
 | 
			
		||||
				fmt.Sprintf(oracleSecurityBaseURL, cveID),
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
		for _, advisory := range cveInfo.DistroAdvisories {
 | 
			
		||||
			links = append(links, distroLink{
 | 
			
		||||
				// "Oracle-ELSA"
 | 
			
		||||
				advisory.AdvisoryID,
 | 
			
		||||
				fmt.Sprintf(oracleELSABaseBaseURL, advisory.AdvisoryID),
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
		return links
 | 
			
		||||
	case "amazon":
 | 
			
		||||
		links := []distroLink{
 | 
			
		||||
			{
 | 
			
		||||
				"RHEL-CVE",
 | 
			
		||||
				fmt.Sprintf("%s/%s", redhatSecurityBaseURL, cveID),
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
		for _, advisory := range cveInfo.DistroAdvisories {
 | 
			
		||||
			links = append(links, distroLink{
 | 
			
		||||
				//  "Amazon-ALAS",
 | 
			
		||||
				advisory.AdvisoryID,
 | 
			
		||||
				fmt.Sprintf(amazonSecurityBaseURL, advisory.AdvisoryID),
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
		return links
 | 
			
		||||
	case "ubuntu":
 | 
			
		||||
		return []distroLink{
 | 
			
		||||
			{
 | 
			
		||||
				"Ubuntu-CVE",
 | 
			
		||||
				fmt.Sprintf("%s/%s", ubuntuSecurityBaseURL, cveID),
 | 
			
		||||
			},
 | 
			
		||||
			//TODO Ubuntu USN
 | 
			
		||||
		}
 | 
			
		||||
	case "debian":
 | 
			
		||||
		return []distroLink{
 | 
			
		||||
			{
 | 
			
		||||
				"Debian-CVE",
 | 
			
		||||
				fmt.Sprintf("%s/%s", debianTrackerBaseURL, cveID),
 | 
			
		||||
			},
 | 
			
		||||
			//  TODO Debian dsa
 | 
			
		||||
		}
 | 
			
		||||
	case "FreeBSD":
 | 
			
		||||
		links := []distroLink{}
 | 
			
		||||
		for _, advisory := range cveInfo.DistroAdvisories {
 | 
			
		||||
			links = append(links, distroLink{
 | 
			
		||||
				"FreeBSD-VuXML",
 | 
			
		||||
				fmt.Sprintf(freeBSDVuXMLBaseURL, advisory.AdvisoryID),
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
		return links
 | 
			
		||||
	default:
 | 
			
		||||
		return []distroLink{}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
//  func distroLinks(cveInfo models.CveInfo, osFamily string) []distroLink {
 | 
			
		||||
//      cveID := cveInfo.VulnInfo.CveID
 | 
			
		||||
//      switch osFamily {
 | 
			
		||||
//      case "rhel", "centos":
 | 
			
		||||
//          links := []distroLink{
 | 
			
		||||
//              {
 | 
			
		||||
//                  "RHEL-CVE",
 | 
			
		||||
//                  fmt.Sprintf("%s/%s", redhatSecurityBaseURL, cveID),
 | 
			
		||||
//              },
 | 
			
		||||
//          }
 | 
			
		||||
//          for _, advisory := range cveInfo.DistroAdvisories {
 | 
			
		||||
//              aidURL := strings.Replace(advisory.AdvisoryID, ":", "-", -1)
 | 
			
		||||
//              links = append(links, distroLink{
 | 
			
		||||
//                  //  "RHEL-errata",
 | 
			
		||||
//                  advisory.AdvisoryID,
 | 
			
		||||
//                  fmt.Sprintf(redhatRHSABaseBaseURL, aidURL),
 | 
			
		||||
//              })
 | 
			
		||||
//          }
 | 
			
		||||
//          return links
 | 
			
		||||
//      case "oraclelinux":
 | 
			
		||||
//          links := []distroLink{
 | 
			
		||||
//              {
 | 
			
		||||
//                  "Oracle-CVE",
 | 
			
		||||
//                  fmt.Sprintf(oracleSecurityBaseURL, cveID),
 | 
			
		||||
//              },
 | 
			
		||||
//          }
 | 
			
		||||
//          for _, advisory := range cveInfo.DistroAdvisories {
 | 
			
		||||
//              links = append(links, distroLink{
 | 
			
		||||
//                  // "Oracle-ELSA"
 | 
			
		||||
//                  advisory.AdvisoryID,
 | 
			
		||||
//                  fmt.Sprintf(oracleELSABaseBaseURL, advisory.AdvisoryID),
 | 
			
		||||
//              })
 | 
			
		||||
//          }
 | 
			
		||||
//          return links
 | 
			
		||||
//      case "amazon":
 | 
			
		||||
//          links := []distroLink{
 | 
			
		||||
//              {
 | 
			
		||||
//                  "RHEL-CVE",
 | 
			
		||||
//                  fmt.Sprintf("%s/%s", redhatSecurityBaseURL, cveID),
 | 
			
		||||
//              },
 | 
			
		||||
//          }
 | 
			
		||||
//          for _, advisory := range cveInfo.DistroAdvisories {
 | 
			
		||||
//              links = append(links, distroLink{
 | 
			
		||||
//                  //  "Amazon-ALAS",
 | 
			
		||||
//                  advisory.AdvisoryID,
 | 
			
		||||
//                  fmt.Sprintf(amazonSecurityBaseURL, advisory.AdvisoryID),
 | 
			
		||||
//              })
 | 
			
		||||
//          }
 | 
			
		||||
//          return links
 | 
			
		||||
//      case "ubuntu":
 | 
			
		||||
//          return []distroLink{
 | 
			
		||||
//              {
 | 
			
		||||
//                  "Ubuntu-CVE",
 | 
			
		||||
//                  fmt.Sprintf("%s/%s", ubuntuSecurityBaseURL, cveID),
 | 
			
		||||
//              },
 | 
			
		||||
//              //TODO Ubuntu USN
 | 
			
		||||
//          }
 | 
			
		||||
//      case "debian":
 | 
			
		||||
//          return []distroLink{
 | 
			
		||||
//              {
 | 
			
		||||
//                  "Debian-CVE",
 | 
			
		||||
//                  fmt.Sprintf("%s/%s", debianTrackerBaseURL, cveID),
 | 
			
		||||
//              },
 | 
			
		||||
//              //  TODO Debian dsa
 | 
			
		||||
//          }
 | 
			
		||||
//      case "FreeBSD":
 | 
			
		||||
//          links := []distroLink{}
 | 
			
		||||
//          for _, advisory := range cveInfo.DistroAdvisories {
 | 
			
		||||
//              links = append(links, distroLink{
 | 
			
		||||
//                  "FreeBSD-VuXML",
 | 
			
		||||
//                  fmt.Sprintf(freeBSDVuXMLBaseURL, advisory.AdvisoryID),
 | 
			
		||||
//              })
 | 
			
		||||
//          }
 | 
			
		||||
//          return links
 | 
			
		||||
//      default:
 | 
			
		||||
//          return []distroLink{}
 | 
			
		||||
//      }
 | 
			
		||||
//  }
 | 
			
		||||
 | 
			
		||||
// addPackageInfos add package information related the CVE to table
 | 
			
		||||
func addPackageInfos(table *uitable.Table, packs []models.PackageInfo) *uitable.Table {
 | 
			
		||||
 
 | 
			
		||||
@@ -267,9 +267,11 @@ func (l base) isAwsInstanceID(str string) bool {
 | 
			
		||||
 | 
			
		||||
func (l *base) convertToModel() models.ScanResult {
 | 
			
		||||
	for _, p := range l.VulnInfos {
 | 
			
		||||
		//TODO
 | 
			
		||||
		sort.Sort(models.PackageInfosByName(p.Packages))
 | 
			
		||||
	}
 | 
			
		||||
	sort.Sort(l.VulnInfos)
 | 
			
		||||
	//TODO
 | 
			
		||||
	//  sort.Sort(l.VulnInfos)
 | 
			
		||||
 | 
			
		||||
	ctype := l.ServerInfo.Containers.Type
 | 
			
		||||
	if l.ServerInfo.Container.ContainerID != "" && ctype == "" {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										29
									
								
								util/util.go
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								util/util.go
									
									
									
									
									
								
							@@ -20,7 +20,6 @@ package util
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/future-architect/vuls/config"
 | 
			
		||||
@@ -136,31 +135,3 @@ func Truncate(str string, length int) string {
 | 
			
		||||
	}
 | 
			
		||||
	return str
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseCvss2 divide CVSSv2 string into score and vector
 | 
			
		||||
// 5/AV:N/AC:L/Au:N/C:N/I:N/A:P
 | 
			
		||||
func ParseCvss2(scoreVector string) (score float64, vector string) {
 | 
			
		||||
	var err error
 | 
			
		||||
	ss := strings.Split(scoreVector, "/")
 | 
			
		||||
	if 1 < len(ss) {
 | 
			
		||||
		if score, err = strconv.ParseFloat(ss[0], 64); err != nil {
 | 
			
		||||
			return 0, ""
 | 
			
		||||
		}
 | 
			
		||||
		return score, strings.Join(ss[1:len(ss)], "/")
 | 
			
		||||
	}
 | 
			
		||||
	return 0, ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseCvss3 divide CVSSv3 string into score and vector
 | 
			
		||||
// 5.6/CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L
 | 
			
		||||
func ParseCvss3(scoreVector string) (score float64, vector string) {
 | 
			
		||||
	var err error
 | 
			
		||||
	ss := strings.Split(scoreVector, "/CVSS:3.0/")
 | 
			
		||||
	if 1 < len(ss) {
 | 
			
		||||
		if score, err = strconv.ParseFloat(ss[0], 64); err != nil {
 | 
			
		||||
			return 0, ""
 | 
			
		||||
		}
 | 
			
		||||
		return score, strings.Join(ss[1:len(ss)], "/")
 | 
			
		||||
	}
 | 
			
		||||
	return 0, ""
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -171,69 +171,3 @@ func TestTruncate(t *testing.T) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestParseCvss2(t *testing.T) {
 | 
			
		||||
	type out struct {
 | 
			
		||||
		score  float64
 | 
			
		||||
		vector string
 | 
			
		||||
	}
 | 
			
		||||
	var tests = []struct {
 | 
			
		||||
		in  string
 | 
			
		||||
		out out
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			in: "5/AV:N/AC:L/Au:N/C:N/I:N/A:P",
 | 
			
		||||
			out: out{
 | 
			
		||||
				score:  5.0,
 | 
			
		||||
				vector: "AV:N/AC:L/Au:N/C:N/I:N/A:P",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			in: "",
 | 
			
		||||
			out: out{
 | 
			
		||||
				score:  0,
 | 
			
		||||
				vector: "",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		s, v := ParseCvss2(tt.in)
 | 
			
		||||
		if s != tt.out.score || v != tt.out.vector {
 | 
			
		||||
			t.Errorf("\nexpected: %f, %s\n  actual: %f, %s",
 | 
			
		||||
				tt.out.score, tt.out.vector, s, v)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestParseCvss3(t *testing.T) {
 | 
			
		||||
	type out struct {
 | 
			
		||||
		score  float64
 | 
			
		||||
		vector string
 | 
			
		||||
	}
 | 
			
		||||
	var tests = []struct {
 | 
			
		||||
		in  string
 | 
			
		||||
		out out
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			in: "5.6/CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L",
 | 
			
		||||
			out: out{
 | 
			
		||||
				score:  5.6,
 | 
			
		||||
				vector: "AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			in: "",
 | 
			
		||||
			out: out{
 | 
			
		||||
				score:  0,
 | 
			
		||||
				vector: "",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		s, v := ParseCvss3(tt.in)
 | 
			
		||||
		if s != tt.out.score || v != tt.out.vector {
 | 
			
		||||
			t.Errorf("\nexpected: %f, %s\n  actual: %f, %s",
 | 
			
		||||
				tt.out.score, tt.out.vector, s, v)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user