Output changelog in report, TUI and JSON for Ubuntu/Debian/CentOS
This commit is contained in:
102
scan/debian.go
102
scan/debian.go
@@ -311,7 +311,8 @@ func (o *debian) ensureChangelogCache(current cache.Meta) (*cache.Meta, error) {
|
||||
// Search from cache
|
||||
cached, found, err := cache.DB.GetMeta(current.Name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to get meta. err: %s", err)
|
||||
return nil, fmt.Errorf(
|
||||
"Failed to get meta. Please remove cache.db and then try again. err: %s", err)
|
||||
}
|
||||
|
||||
if !found {
|
||||
@@ -447,7 +448,7 @@ func (o *debian) scanVulnInfos(upgradablePacks []models.PackageInfo, meta *cache
|
||||
func(p models.PackageInfo) {
|
||||
changelog := o.getChangelogCache(meta, p)
|
||||
if 0 < len(changelog) {
|
||||
cveIDs := o.getCveIDsFromChangelog(changelog, p.Name, p.Version)
|
||||
cveIDs, _ := o.getCveIDsFromChangelog(changelog, p.Name, p.Version)
|
||||
resChan <- struct {
|
||||
models.PackageInfo
|
||||
DetectedCveIDs
|
||||
@@ -549,9 +550,9 @@ func (o *debian) scanPackageCveIDs(pack models.PackageInfo) ([]DetectedCveID, er
|
||||
cmd := ""
|
||||
switch o.Distro.Family {
|
||||
case "ubuntu", "raspbian":
|
||||
cmd = fmt.Sprintf(`apt-get changelog %s | grep '\(urgency\|CVE\)'`, pack.Name)
|
||||
cmd = fmt.Sprintf(`PAGER=cat apt-get -q=2 changelog %s`, pack.Name)
|
||||
case "debian":
|
||||
cmd = fmt.Sprintf(`env PAGER=cat aptitude changelog %s | grep '\(urgency\|CVE\)'`, pack.Name)
|
||||
cmd = fmt.Sprintf(`PAGER=cat aptitude -q=2 changelog %s`, pack.Name)
|
||||
}
|
||||
cmd = util.PrependProxyEnv(cmd)
|
||||
|
||||
@@ -562,40 +563,65 @@ func (o *debian) scanPackageCveIDs(pack models.PackageInfo) ([]DetectedCveID, er
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if 0 < len(strings.TrimSpace(r.Stdout)) {
|
||||
err := cache.DB.PutChangelog(o.getServerInfo().GetServerName(), pack.Name, r.Stdout)
|
||||
stdout := strings.Replace(r.Stdout, "\r", "", -1)
|
||||
cveIDs, clog := o.getCveIDsFromChangelog(
|
||||
stdout, pack.Name, pack.Version)
|
||||
|
||||
if clog.Method != models.FailedToGetChangelog {
|
||||
err := cache.DB.PutChangelog(o.getServerInfo().GetServerName(), pack.Name, clog.Contents)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to put changelog into cache")
|
||||
}
|
||||
}
|
||||
|
||||
// No error will be returned. Only logging.
|
||||
return o.getCveIDsFromChangelog(r.Stdout, pack.Name, pack.Version), nil
|
||||
return cveIDs, nil
|
||||
}
|
||||
|
||||
func (o *debian) getCveIDsFromChangelog(changelog string,
|
||||
packName string, versionOrLater string) []DetectedCveID {
|
||||
packName string, versionOrLater string) ([]DetectedCveID, models.Changelog) {
|
||||
|
||||
if cveIDs, err := o.parseChangelog(changelog, packName, versionOrLater); err == nil {
|
||||
return cveIDs
|
||||
if cveIDs, relevantChangelog, err := o.parseChangelog(changelog, packName, versionOrLater); err == nil {
|
||||
return cveIDs, relevantChangelog
|
||||
}
|
||||
|
||||
//TODO switch case ubuntu, debian
|
||||
ver := strings.Split(versionOrLater, "ubuntu")[0]
|
||||
if cveIDs, err := o.parseChangelog(changelog, packName, ver); err == nil {
|
||||
return cveIDs
|
||||
if cveIDs, relevantChangelog, err := o.parseChangelog(changelog, packName, ver); err == nil {
|
||||
return cveIDs, relevantChangelog
|
||||
}
|
||||
|
||||
splittedByColon := strings.Split(versionOrLater, ":")
|
||||
if 1 < len(splittedByColon) {
|
||||
ver = splittedByColon[1]
|
||||
}
|
||||
cveIDs, err := o.parseChangelog(changelog, packName, ver)
|
||||
cveIDs, relevantChangelog, err := o.parseChangelog(changelog, packName, ver)
|
||||
if err == nil {
|
||||
return cveIDs
|
||||
return cveIDs, relevantChangelog
|
||||
}
|
||||
|
||||
ver = strings.Split(ver, "ubuntu")[0]
|
||||
if cveIDs, relevantChangelog, err := o.parseChangelog(changelog, packName, ver); err == nil {
|
||||
return cveIDs, relevantChangelog
|
||||
}
|
||||
|
||||
// Only logging the error.
|
||||
o.log.Error(err)
|
||||
return []DetectedCveID{}
|
||||
|
||||
for i, p := range o.Packages {
|
||||
if p.Name == packName {
|
||||
o.Packages[i].Changelog = models.Changelog{
|
||||
Contents: "",
|
||||
Method: models.FailedToFindVersionInChangelog,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the version is not in changelog, return entire changelog to put into cache
|
||||
return []DetectedCveID{}, models.Changelog{
|
||||
Contents: changelog,
|
||||
Method: models.FailedToFindVersionInChangelog,
|
||||
}
|
||||
}
|
||||
|
||||
// DetectedCveID has CveID, Confidence and DetectionMethod fields
|
||||
@@ -609,13 +635,13 @@ type DetectedCveID struct {
|
||||
// DetectedCveIDs is a slice of DetectedCveID
|
||||
type DetectedCveIDs []DetectedCveID
|
||||
|
||||
var cveRe = regexp.MustCompile(`(CVE-\d{4}-\d{4,})`)
|
||||
|
||||
// Collect CVE-IDs included in the changelog.
|
||||
// The version which specified in argument(versionOrLater) is excluded.
|
||||
func (o *debian) parseChangelog(changelog string,
|
||||
packName string, versionOrLater string) (cves []DetectedCveID, err error) {
|
||||
func (o *debian) parseChangelog(changelog string, packName string, versionOrLater string) ([]DetectedCveID, models.Changelog, error) {
|
||||
|
||||
cveIDs := []string{}
|
||||
cveRe := regexp.MustCompile(`(CVE-\d{4}-\d{4,})`)
|
||||
buf, cveIDs := []string{}, []string{}
|
||||
stopRe := regexp.MustCompile(fmt.Sprintf(`\(%s\)`, regexp.QuoteMeta(versionOrLater)))
|
||||
stopLineFound := false
|
||||
lenientStopLineFound := false
|
||||
@@ -626,6 +652,7 @@ func (o *debian) parseChangelog(changelog string,
|
||||
lenientRe := regexp.MustCompile(fmt.Sprintf(`\(%s\)`, regexp.QuoteMeta(versionOrLaterlenient)))
|
||||
lines := strings.Split(changelog, "\n")
|
||||
for _, line := range lines {
|
||||
buf = append(buf, line)
|
||||
if match := stopRe.MatchString(line); match {
|
||||
// o.log.Debugf("Found the stop line: %s", line)
|
||||
stopLineFound = true
|
||||
@@ -640,21 +667,38 @@ func (o *debian) parseChangelog(changelog string,
|
||||
}
|
||||
}
|
||||
if !stopLineFound && !lenientStopLineFound {
|
||||
return cves, fmt.Errorf(
|
||||
"Failed to scan CVE IDs. The version is not in changelog. name: %s, version: %s",
|
||||
packName,
|
||||
versionOrLater,
|
||||
)
|
||||
return nil, models.Changelog{
|
||||
Contents: "",
|
||||
Method: models.FailedToFindVersionInChangelog,
|
||||
}, fmt.Errorf(
|
||||
"Failed to scan CVE IDs. The version is not in changelog. name: %s, version: %s",
|
||||
packName,
|
||||
versionOrLater,
|
||||
)
|
||||
}
|
||||
|
||||
for _, id := range cveIDs {
|
||||
confidence := models.ChangelogExactMatch
|
||||
if lenientStopLineFound {
|
||||
confidence = models.ChangelogLenientMatch
|
||||
confidence := models.ChangelogExactMatch
|
||||
if lenientStopLineFound {
|
||||
confidence = models.ChangelogLenientMatch
|
||||
}
|
||||
|
||||
clog := models.Changelog{
|
||||
Contents: strings.Join(buf, "\n"),
|
||||
Method: string(confidence.DetectionMethod),
|
||||
}
|
||||
|
||||
for i, p := range o.Packages {
|
||||
if p.Name == packName {
|
||||
o.Packages[i].Changelog = clog
|
||||
}
|
||||
}
|
||||
|
||||
cves := []DetectedCveID{}
|
||||
for _, id := range cveIDs {
|
||||
cves = append(cves, DetectedCveID{id, confidence})
|
||||
}
|
||||
return
|
||||
|
||||
return cves, clog, nil
|
||||
}
|
||||
|
||||
func (o *debian) splitAptCachePolicy(stdout string) map[string]string {
|
||||
|
||||
Reference in New Issue
Block a user