feat(scan): WordPress Vulnerability Scan (core, plugin, theme) (#769)

https://github.com/future-architect/vuls/pull/769
This commit is contained in:
kazuminn
2019-04-08 17:27:44 +09:00
committed by Kota Kanbe
parent 91df593566
commit 99c65eff48
59 changed files with 1284 additions and 602 deletions

View File

@@ -25,6 +25,7 @@ import (
"time"
storage "github.com/Azure/azure-sdk-for-go/storage"
"golang.org/x/xerrors"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
@@ -60,7 +61,7 @@ func (w AzureBlobWriter) Write(rs ...models.ScanResult) (err error) {
k := key + ".json"
var b []byte
if b, err = json.Marshal(r); err != nil {
return fmt.Errorf("Failed to Marshal to JSON: %s", err)
return xerrors.Errorf("Failed to Marshal to JSON: %w", err)
}
if err := createBlockBlob(cli, k, b); err != nil {
return err
@@ -87,7 +88,7 @@ func (w AzureBlobWriter) Write(rs ...models.ScanResult) (err error) {
k := key + ".xml"
var b []byte
if b, err = xml.Marshal(r); err != nil {
return fmt.Errorf("Failed to Marshal to XML: %s", err)
return xerrors.Errorf("Failed to Marshal to XML: %w", err)
}
allBytes := bytes.Join([][]byte{[]byte(xml.Header + vulsOpenTag), b, []byte(vulsCloseTag)}, []byte{})
if err := createBlockBlob(cli, k, allBytes); err != nil {
@@ -117,7 +118,7 @@ func CheckIfAzureContainerExists() error {
}
}
if !found {
return fmt.Errorf("Container not found. Container: %s", c.Conf.Azure.ContainerName)
return xerrors.Errorf("Container not found. Container: %s", c.Conf.Azure.ContainerName)
}
return nil
}
@@ -142,7 +143,7 @@ func createBlockBlob(cli storage.BlobStorageClient, k string, b []byte) error {
ref := cli.GetContainerReference(c.Conf.Azure.ContainerName)
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",
return xerrors.Errorf("Failed to upload data to %s/%s, err: %w",
c.Conf.Azure.ContainerName, k, err)
}
return nil

View File

@@ -25,6 +25,7 @@ import (
"github.com/cenkalti/backoff"
"github.com/parnurzeal/gorequest"
"golang.org/x/xerrors"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/util"
@@ -57,7 +58,7 @@ func (api cvedictClient) CheckHealth() error {
resp, _, errs = gorequest.New().SetDebug(config.Conf.Debug).Get(url).End()
// resp, _, errs = gorequest.New().Proxy(api.httpProxy).Get(url).End()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
return fmt.Errorf("Failed to request to CVE server. url: %s, errs: %v",
return xerrors.Errorf("Failed to request to CVE server. url: %s, errs: %w",
url, errs)
}
return nil
@@ -73,7 +74,7 @@ func (api cvedictClient) FetchCveDetails(driver cvedb.DB, cveIDs []string) (cveD
for _, cveID := range cveIDs {
cveDetail, err := driver.Get(cveID)
if err != nil {
return nil, fmt.Errorf("Failed to fetch CVE. err: %s", err)
return nil, xerrors.Errorf("Failed to fetch CVE. err: %w", err)
}
if len(cveDetail.CveID) == 0 {
cveDetails = append(cveDetails, cve.CveDetail{
@@ -132,12 +133,12 @@ func (api cvedictClient) FetchCveDetails(driver cvedb.DB, cveIDs []string) (cveD
case err := <-errChan:
errs = append(errs, err)
case <-timeout:
return nil, fmt.Errorf("Timeout Fetching CVE")
return nil, xerrors.New("Timeout Fetching CVE")
}
}
if len(errs) != 0 {
return nil,
fmt.Errorf("Failed to fetch CVE. err: %v", errs)
xerrors.Errorf("Failed to fetch CVE. err: %w", errs)
}
return
}
@@ -150,8 +151,8 @@ func (api cvedictClient) httpGet(key, url string, resChan chan<- response, errCh
// resp, body, errs = gorequest.New().SetDebug(config.Conf.Debug).Get(url).End()
resp, body, errs = gorequest.New().Get(url).End()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
return fmt.Errorf("HTTP GET error: %v, url: %s, resp: %v",
errs, url, resp)
return xerrors.Errorf("HTTP GET Error, url: %s, resp: %v, err: %w",
url, resp, errs)
}
return nil
}
@@ -161,13 +162,12 @@ func (api cvedictClient) httpGet(key, url string, resChan chan<- response, errCh
}
err := backoff.RetryNotify(f, backoff.NewExponentialBackOff(), notify)
if err != nil {
errChan <- fmt.Errorf("HTTP Error %s", err)
errChan <- xerrors.Errorf("HTTP Error: %w", err)
return
}
cveDetail := cve.CveDetail{}
if err := json.Unmarshal([]byte(body), &cveDetail); err != nil {
errChan <- fmt.Errorf("Failed to Unmarshall. body: %s, err: %s",
body, err)
errChan <- xerrors.Errorf("Failed to Unmarshall. body: %s, err: %w", body, err)
return
}
resChan <- response{
@@ -203,7 +203,7 @@ func (api cvedictClient) httpPost(key, url string, query map[string]string) ([]c
}
resp, body, errs = req.End()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
return fmt.Errorf("HTTP POST error: %v, url: %s, resp: %v", errs, url, resp)
return xerrors.Errorf("HTTP POST error. url: %s, resp: %v, err: %w", url, resp, errs)
}
return nil
}
@@ -212,13 +212,13 @@ func (api cvedictClient) httpPost(key, url string, query map[string]string) ([]c
}
err := backoff.RetryNotify(f, backoff.NewExponentialBackOff(), notify)
if err != nil {
return nil, fmt.Errorf("HTTP Error %s", err)
return nil, xerrors.Errorf("HTTP Error: %w", err)
}
cveDetails := []cve.CveDetail{}
if err := json.Unmarshal([]byte(body), &cveDetails); err != nil {
return nil,
fmt.Errorf("Failed to Unmarshall. body: %s, err: %s", body, err)
xerrors.Errorf("Failed to Unmarshall. body: %s, err: %w", body, err)
}
return cveDetails, nil
}

View File

@@ -1,7 +1,6 @@
package report
import (
"fmt"
"os"
"github.com/future-architect/vuls/config"
@@ -10,6 +9,7 @@ import (
cvedb "github.com/kotakanbe/go-cve-dictionary/db"
ovaldb "github.com/kotakanbe/goval-dictionary/db"
exploitdb "github.com/mozqnet/go-exploitdb/db"
"golang.org/x/xerrors"
)
// DBClient is a dictionarie's db client for reporting
@@ -33,7 +33,7 @@ type DBClientConf struct {
func NewDBClient(cnf DBClientConf) (dbclient *DBClient, locked bool, err error) {
cveDriver, locked, err := NewCveDB(cnf)
if locked {
return nil, true, fmt.Errorf("CveDB is locked: %s",
return nil, true, xerrors.Errorf("CveDB is locked: %s",
cnf.OvalDictCnf.SQLite3Path)
} else if err != nil {
return nil, locked, err
@@ -41,7 +41,7 @@ func NewDBClient(cnf DBClientConf) (dbclient *DBClient, locked bool, err error)
ovaldb, locked, err := NewOvalDB(cnf)
if locked {
return nil, true, fmt.Errorf("OvalDB is locked: %s",
return nil, true, xerrors.Errorf("OvalDB is locked: %s",
cnf.OvalDictCnf.SQLite3Path)
} else if err != nil {
util.Log.Warnf("Unable to use OvalDB: %s, err: %s",
@@ -50,7 +50,7 @@ func NewDBClient(cnf DBClientConf) (dbclient *DBClient, locked bool, err error)
gostdb, locked, err := NewGostDB(cnf)
if locked {
return nil, true, fmt.Errorf("gostDB is locked: %s",
return nil, true, xerrors.Errorf("gostDB is locked: %s",
cnf.GostCnf.SQLite3Path)
} else if err != nil {
util.Log.Warnf("Unable to use gostDB: %s, err: %s",
@@ -59,7 +59,7 @@ func NewDBClient(cnf DBClientConf) (dbclient *DBClient, locked bool, err error)
exploitdb, locked, err := NewExploitDB(cnf)
if locked {
return nil, true, fmt.Errorf("exploitDB is locked: %s",
return nil, true, xerrors.Errorf("exploitDB is locked: %s",
cnf.ExploitCnf.SQLite3Path)
} else if err != nil {
util.Log.Warnf("Unable to use exploitDB: %s, err: %s",
@@ -88,7 +88,7 @@ func NewCveDB(cnf DBClientConf) (driver cvedb.DB, locked bool, err error) {
util.Log.Debugf("Open cve-dictionary db (%s): %s", cnf.CveDictCnf.Type, path)
driver, locked, err = cvedb.NewDB(cnf.CveDictCnf.Type, path, cnf.DebugSQL)
if err != nil {
err = fmt.Errorf("Failed to init CVE DB. err: %s, path: %s", err, path)
err = xerrors.Errorf("Failed to init CVE DB. err: %w, path: %s", err, path)
return nil, locked, err
}
return driver, false, nil
@@ -112,7 +112,7 @@ func NewOvalDB(cnf DBClientConf) (driver ovaldb.DB, locked bool, err error) {
util.Log.Debugf("Open oval-dictionary db (%s): %s", cnf.OvalDictCnf.Type, path)
driver, locked, err = ovaldb.NewDB("", cnf.OvalDictCnf.Type, path, cnf.DebugSQL)
if err != nil {
err = fmt.Errorf("Failed to new OVAL DB. err: %s", err)
err = xerrors.Errorf("Failed to new OVAL DB. err: %w", err)
if locked {
return nil, true, err
}

View File

@@ -27,6 +27,7 @@ import (
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
"golang.org/x/xerrors"
)
// EMailWriter send mail
@@ -108,7 +109,7 @@ func (e *emailSender) Send(subject, body string) (err error) {
cc := strings.Join(emailConf.Cc[:], ", ")
mailAddresses := append(emailConf.To, emailConf.Cc...)
if _, err := mail.ParseAddressList(strings.Join(mailAddresses[:], ", ")); err != nil {
return fmt.Errorf("Failed to parse email addresses: %s", err)
return xerrors.Errorf("Failed to parse email addresses: %w", err)
}
headers := make(map[string]string)
@@ -141,7 +142,7 @@ func (e *emailSender) Send(subject, body string) (err error) {
[]byte(message),
)
if err != nil {
return fmt.Errorf("Failed to send emails: %s", err)
return xerrors.Errorf("Failed to send emails: %w", err)
}
return nil
}
@@ -153,7 +154,7 @@ func (e *emailSender) Send(subject, body string) (err error) {
[]byte(message),
)
if err != nil {
return fmt.Errorf("Failed to send emails: %s", err)
return xerrors.Errorf("Failed to send emails: %w", err)
}
return nil
}

View File

@@ -22,10 +22,9 @@ import (
"encoding/json"
"net/http"
"github.com/pkg/errors"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
"golang.org/x/xerrors"
)
// HTTPRequestWriter writes results to HTTP request
@@ -53,7 +52,7 @@ type HTTPResponseWriter struct {
func (w HTTPResponseWriter) Write(rs ...models.ScanResult) (err error) {
res, err := json.Marshal(rs)
if err != nil {
return errors.Wrap(err, "Failed to marshal scah results")
return xerrors.Errorf("Failed to marshal scah results: %w", err)
}
w.Writer.Header().Set("Content-Type", "application/json")
_, err = w.Writer.Write(res)

View File

@@ -21,13 +21,13 @@ import (
"bytes"
"encoding/json"
"encoding/xml"
"fmt"
"io/ioutil"
"os"
"path/filepath"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
"golang.org/x/xerrors"
)
// LocalFileWriter writes results to a local file.
@@ -40,8 +40,8 @@ func (w LocalFileWriter) Write(rs ...models.ScanResult) (err error) {
path := filepath.Join(w.CurrentDir, "summary.txt")
text := formatOneLineSummary(rs...)
if err := writeFile(path, []byte(text), 0600); err != nil {
return fmt.Errorf(
"Failed to write to file. path: %s, err: %s",
return xerrors.Errorf(
"Failed to write to file. path: %s, err: %w",
path, err)
}
}
@@ -60,15 +60,15 @@ func (w LocalFileWriter) Write(rs ...models.ScanResult) (err error) {
var b []byte
if c.Conf.Debug {
if b, err = json.MarshalIndent(r, "", " "); err != nil {
return fmt.Errorf("Failed to Marshal to JSON: %s", err)
return xerrors.Errorf("Failed to Marshal to JSON: %w", err)
}
} else {
if b, err = json.Marshal(r); err != nil {
return fmt.Errorf("Failed to Marshal to JSON: %s", err)
return xerrors.Errorf("Failed to Marshal to JSON: %w", err)
}
}
if err := writeFile(p, b, 0600); err != nil {
return fmt.Errorf("Failed to write JSON. path: %s, err: %s", p, err)
return xerrors.Errorf("Failed to write JSON. path: %s, err: %w", p, err)
}
}
@@ -82,8 +82,8 @@ func (w LocalFileWriter) Write(rs ...models.ScanResult) (err error) {
if err := writeFile(
p, []byte(formatList(r)), 0600); err != nil {
return fmt.Errorf(
"Failed to write text files. path: %s, err: %s", p, err)
return xerrors.Errorf(
"Failed to write text files. path: %s, err: %w", p, err)
}
}
@@ -97,8 +97,8 @@ func (w LocalFileWriter) Write(rs ...models.ScanResult) (err error) {
if err := writeFile(
p, []byte(formatFullPlainText(r)), 0600); err != nil {
return fmt.Errorf(
"Failed to write text files. path: %s, err: %s", p, err)
return xerrors.Errorf(
"Failed to write text files. path: %s, err: %w", p, err)
}
}
@@ -112,11 +112,11 @@ func (w LocalFileWriter) Write(rs ...models.ScanResult) (err error) {
var b []byte
if b, err = xml.Marshal(r); err != nil {
return fmt.Errorf("Failed to Marshal to XML: %s", err)
return xerrors.Errorf("Failed to Marshal to XML: %w", err)
}
allBytes := bytes.Join([][]byte{[]byte(xml.Header + vulsOpenTag), b, []byte(vulsCloseTag)}, []byte{})
if err := writeFile(p, allBytes, 0600); err != nil {
return fmt.Errorf("Failed to write XML. path: %s, err: %s", p, err)
return xerrors.Errorf("Failed to write XML. path: %s, err: %w", p, err)
}
}
}

View File

@@ -39,12 +39,13 @@ import (
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/oval"
"github.com/future-architect/vuls/util"
"github.com/future-architect/vuls/wordpress"
"github.com/hashicorp/uuid"
gostdb "github.com/knqyf263/gost/db"
cvedb "github.com/kotakanbe/go-cve-dictionary/db"
ovaldb "github.com/kotakanbe/goval-dictionary/db"
exploitdb "github.com/mozqnet/go-exploitdb/db"
"github.com/pkg/errors"
"golang.org/x/xerrors"
)
const (
@@ -69,7 +70,7 @@ func FillCveInfos(dbclient DBClient, rs []models.ScanResult, dir string) ([]mode
if owaspDCXMLPath != "" {
cpes, err := parser.Parse(owaspDCXMLPath)
if err != nil {
return nil, fmt.Errorf("Failed to read OWASP Dependency Check XML: %s, %s, %s",
return nil, xerrors.Errorf("Failed to read OWASP Dependency Check XML on %s, `%s`, err: %w",
r.ServerName, owaspDCXMLPath, err)
}
cpeURIs = append(cpeURIs, cpes...)
@@ -82,7 +83,7 @@ func FillCveInfos(dbclient DBClient, rs []models.ScanResult, dir string) ([]mode
if owaspDCXMLPath != "" {
cpes, err := parser.Parse(owaspDCXMLPath)
if err != nil {
return nil, fmt.Errorf("Failed to read OWASP Dependency Check XML: %s, %s, %s",
return nil, xerrors.Errorf("Failed to read OWASP Dependency Check XML on %s, `%s`, err: %w",
r.ServerInfo(), owaspDCXMLPath, err)
}
cpeURIs = append(cpeURIs, cpes...)
@@ -91,8 +92,16 @@ func FillCveInfos(dbclient DBClient, rs []models.ScanResult, dir string) ([]mode
}
}
// Integrations
githubInts := GithubSecurityAlerts(c.Conf.Servers[r.ServerName].GitHubRepos)
if err := FillCveInfo(dbclient, &r, cpeURIs, githubInts); err != nil {
wpOpt := WordPressOption{c.Conf.Servers[r.ServerName].WordPress.WPVulnDBToken}
if err := FillCveInfo(dbclient,
&r,
cpeURIs,
githubInts,
wpOpt); err != nil {
return nil, err
}
r.Lang = c.Conf.Lang
@@ -105,7 +114,7 @@ func FillCveInfos(dbclient DBClient, rs []models.ScanResult, dir string) ([]mode
r.ServerName: c.Conf.Servers[r.ServerName],
}
if err := overwriteJSONFile(dir, r); err != nil {
return nil, fmt.Errorf("Failed to write JSON: %s", err)
return nil, xerrors.Errorf("Failed to write JSON: %w", err)
}
filledResults = append(filledResults, r)
} else {
@@ -139,6 +148,7 @@ func FillCveInfos(dbclient DBClient, rs []models.ScanResult, dir string) ([]mode
r = r.FilterIgnoreCves()
r = r.FilterUnfixed()
r = r.FilterIgnorePkgs()
r = r.FilterInactiveWordPressLibs()
if c.Conf.IgnoreUnscoredCves {
r.ScannedCves = r.ScannedCves.FindScoredVulns()
}
@@ -153,7 +163,7 @@ func FillCveInfo(dbclient DBClient, r *models.ScanResult, cpeURIs []string, inte
nCVEs, err := FillWithOval(dbclient.OvalDB, r)
if err != nil {
return fmt.Errorf("Failed to fill with OVAL: %s", err)
return xerrors.Errorf("Failed to fill with OVAL: %w", err)
}
util.Log.Infof("%s: %d CVEs are detected with OVAL",
r.FormatServerName(), nCVEs)
@@ -169,11 +179,11 @@ func FillCveInfo(dbclient DBClient, r *models.ScanResult, cpeURIs []string, inte
nCVEs, err = fillVulnByCpeURIs(dbclient.CveDB, r, cpeURIs)
if err != nil {
return fmt.Errorf("Failed to detect vulns of %s: %s", cpeURIs, err)
return xerrors.Errorf("Failed to detect vulns of `%s`: %w", cpeURIs, err)
}
util.Log.Infof("%s: %d CVEs are detected with CPE", r.FormatServerName(), nCVEs)
ints := &ints{}
ints := &integrationResults{}
for _, o := range integrations {
if err = o.apply(r, ints); err != nil {
return err
@@ -183,20 +193,20 @@ func FillCveInfo(dbclient DBClient, r *models.ScanResult, cpeURIs []string, inte
nCVEs, err = FillWithGost(dbclient.GostDB, r)
if err != nil {
return fmt.Errorf("Failed to fill with gost: %s", err)
return xerrors.Errorf("Failed to fill with gost: %w", err)
}
util.Log.Infof("%s: %d unfixed CVEs are detected with gost",
r.FormatServerName(), nCVEs)
util.Log.Infof("Fill CVE detailed information with CVE-DB")
if err := fillCveDetail(dbclient.CveDB, r); err != nil {
return fmt.Errorf("Failed to fill with CVE: %s", err)
return xerrors.Errorf("Failed to fill with CVE: %w", err)
}
util.Log.Infof("Fill exploit information with Exploit-DB")
nExploitCve, err := FillWithExploit(dbclient.ExploitDB, r)
if err != nil {
return fmt.Errorf("Failed to fill with exploit: %s", err)
return xerrors.Errorf("Failed to fill with exploit: %w", err)
}
util.Log.Infof("%s: %d exploits are detected",
r.FormatServerName(), nExploitCve)
@@ -280,9 +290,9 @@ func FillWithOval(driver ovaldb.DB, r *models.ScanResult) (nCVEs int, err error)
return 0, nil
default:
if r.Family == "" {
return 0, fmt.Errorf("Probably an error occurred during scanning. Check the error message")
return 0, xerrors.New("Probably an error occurred during scanning. Check the error message")
}
return 0, fmt.Errorf("OVAL for %s is not implemented yet", r.Family)
return 0, xerrors.Errorf("OVAL for %s is not implemented yet", r.Family)
}
if !c.Conf.OvalDict.IsFetchViaHTTP() {
@@ -290,7 +300,7 @@ func FillWithOval(driver ovaldb.DB, r *models.ScanResult) (nCVEs int, err error)
return 0, nil
}
if err = driver.NewOvalDB(ovalFamily); err != nil {
return 0, fmt.Errorf("Failed to New Oval DB. err: %s", err)
return 0, xerrors.Errorf("Failed to New Oval DB. err: %w", err)
}
}
@@ -356,13 +366,14 @@ func fillVulnByCpeURIs(driver cvedb.DB, r *models.ScanResult, cpeURIs []string)
return nCVEs, nil
}
type ints struct {
type integrationResults struct {
GithubAlertsCveCounts int
WordPressCveCounts int
}
// Integration is integration of vuls report
type Integration interface {
apply(*models.ScanResult, *ints) error
apply(*models.ScanResult, *integrationResults) error
}
// GithubSecurityAlerts :
@@ -377,14 +388,15 @@ type GithubSecurityAlertOption struct {
GithubConfs map[string]config.GitHubConf
}
func (g GithubSecurityAlertOption) apply(r *models.ScanResult, ints *ints) (err error) {
// https://help.github.com/articles/about-security-alerts-for-vulnerable-dependencies/
func (g GithubSecurityAlertOption) apply(r *models.ScanResult, ints *integrationResults) (err error) {
var nCVEs int
for ownerRepo, setting := range g.GithubConfs {
ss := strings.Split(ownerRepo, "/")
owner, repo := ss[0], ss[1]
n, err := github.FillGitHubSecurityAlerts(r, owner, repo, setting.Token)
if err != nil {
return errors.Wrap(err, "Failed to access GitHub Security Alerts")
return xerrors.Errorf("Failed to access GitHub Security Alerts: %w", err)
}
nCVEs += n
}
@@ -392,19 +404,21 @@ func (g GithubSecurityAlertOption) apply(r *models.ScanResult, ints *ints) (err
return nil
}
// https://help.github.com/articles/about-security-alerts-for-vulnerable-dependencies/
func fillGitHubSecurityAlerts(r *models.ScanResult) (nCVEs int, err error) {
repos := c.Conf.Servers[r.ServerName].GitHubRepos
for ownerRepo, setting := range repos {
ss := strings.Split(ownerRepo, "/")
owner, repo := ss[0], ss[1]
n, err := github.FillGitHubSecurityAlerts(r, owner, repo, setting.Token)
if err != nil {
return 0, err
}
nCVEs += n
// WordPressOption :
type WordPressOption struct {
token string
}
func (g WordPressOption) apply(r *models.ScanResult, ints *integrationResults) (err error) {
if g.token == "" {
return nil
}
return nCVEs, nil
n, err := wordpress.FillWordPress(r, g.token)
if err != nil {
return xerrors.Errorf("Failed to fetch from WPVulnDB. Check the WPVulnDBToken in config.toml. err: %w", err)
}
ints.WordPressCveCounts = n
return nil
}
func fillCweDict(r *models.ScanResult) {
@@ -420,9 +434,6 @@ func fillCweDict(r *models.ScanResult) {
}
}
// TODO check the format of CWEID, clean CWEID
// JVN, NVD XML, JSON, OVALs
dict := map[string]models.CweDictEntry{}
for id := range uniqCweIDMap {
entry := models.CweDictEntry{}
@@ -638,21 +649,21 @@ func EnsureUUIDs(configPath string, results models.ScanResults) error {
// rename the current config.toml to config.toml.bak
info, err := os.Lstat(configPath)
if err != nil {
return fmt.Errorf("Failed to lstat %s: %s", configPath, err)
return xerrors.Errorf("Failed to lstat %s: %w", configPath, err)
}
realPath := configPath
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
if realPath, err = os.Readlink(configPath); err != nil {
return fmt.Errorf("Failed to Read link %s: %s", configPath, err)
return xerrors.Errorf("Failed to Read link %s: %w", configPath, err)
}
}
if err := os.Rename(realPath, realPath+".bak"); err != nil {
return fmt.Errorf("Failed to rename %s: %s", configPath, err)
return xerrors.Errorf("Failed to rename %s: %w", configPath, err)
}
var buf bytes.Buffer
if err := toml.NewEncoder(&buf).Encode(c); err != nil {
return fmt.Errorf("Failed to encode to toml: %s", err)
return xerrors.Errorf("Failed to encode to toml: %w", err)
}
str := strings.Replace(buf.String(), "\n [", "\n\n [", -1)
str = fmt.Sprintf("%s\n\n%s",

View File

@@ -31,6 +31,7 @@ import (
"github.com/aws/aws-sdk-go/aws/ec2metadata"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"golang.org/x/xerrors"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
@@ -75,7 +76,7 @@ func (w S3Writer) Write(rs ...models.ScanResult) (err error) {
k := key + ".json"
var b []byte
if b, err = json.Marshal(r); err != nil {
return fmt.Errorf("Failed to Marshal to JSON: %s", err)
return xerrors.Errorf("Failed to Marshal to JSON: %w", err)
}
if err := putObject(svc, k, b); err != nil {
return err
@@ -102,7 +103,7 @@ func (w S3Writer) Write(rs ...models.ScanResult) (err error) {
k := key + ".xml"
var b []byte
if b, err = xml.Marshal(r); err != nil {
return fmt.Errorf("Failed to Marshal to XML: %s", err)
return xerrors.Errorf("Failed to Marshal to XML: %w", err)
}
allBytes := bytes.Join([][]byte{[]byte(xml.Header + vulsOpenTag), b, []byte(vulsCloseTag)}, []byte{})
if err := putObject(svc, k, allBytes); err != nil {
@@ -118,8 +119,8 @@ func CheckIfBucketExists() error {
svc := getS3()
result, err := svc.ListBuckets(&s3.ListBucketsInput{})
if err != nil {
return fmt.Errorf(
"Failed to list buckets. err: %s, profile: %s, region: %s",
return xerrors.Errorf(
"Failed to list buckets. err: %w, profile: %s, region: %s",
err, c.Conf.AWS.Profile, c.Conf.AWS.Region)
}
@@ -131,7 +132,7 @@ func CheckIfBucketExists() error {
}
}
if !found {
return fmt.Errorf(
return xerrors.Errorf(
"Failed to find the buckets. profile: %s, region: %s, bucket: %s",
c.Conf.AWS.Profile, c.Conf.AWS.Region, c.Conf.AWS.S3Bucket)
}
@@ -158,7 +159,7 @@ func putObject(svc *s3.S3, k string, b []byte) error {
}
if _, err := svc.PutObject(putObjectInput); err != nil {
return fmt.Errorf("Failed to upload data to %s/%s, %s",
return xerrors.Errorf("Failed to upload data to %s/%s, err: %w",
c.Conf.AWS.S3Bucket, k, err)
}
return nil

View File

@@ -37,6 +37,7 @@ import (
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/util"
"golang.org/x/xerrors"
)
// SaasWriter writes results to SaaS
@@ -80,7 +81,7 @@ func (w SaasWriter) Write(rs ...models.ScanResult) (err error) {
var body []byte
if body, err = json.Marshal(payload); err != nil {
return fmt.Errorf("Failed to Marshal to JSON: %s", err)
return xerrors.Errorf("Failed to Marshal to JSON: %w", err)
}
var req *http.Request
@@ -109,7 +110,7 @@ func (w SaasWriter) Write(rs ...models.ScanResult) (err error) {
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return fmt.Errorf("Failed to get Credential. Request JSON : %s,", string(body))
return xerrors.Errorf("Failed to get Credential. Request JSON : %s,", string(body))
}
var t []byte
@@ -119,7 +120,7 @@ func (w SaasWriter) Write(rs ...models.ScanResult) (err error) {
var tempCredential TempCredential
if err = json.Unmarshal(t, &tempCredential); err != nil {
return fmt.Errorf("Failed to unmarshal saas credential file. err : %s", err)
return xerrors.Errorf("Failed to unmarshal saas credential file. err : %s", err)
}
credential := credentials.NewStaticCredentialsFromCreds(credentials.Value{
@@ -133,7 +134,7 @@ func (w SaasWriter) Write(rs ...models.ScanResult) (err error) {
Credentials: credential,
Region: aws.String("ap-northeast-1"),
}); err != nil {
return fmt.Errorf("Failed to new aws session. err : %s", err)
return xerrors.Errorf("Failed to new aws session. err: %w", err)
}
svc := s3.New(sess)
@@ -141,7 +142,7 @@ func (w SaasWriter) Write(rs ...models.ScanResult) (err error) {
s3Key := renameKeyNameUTC(r.ScannedAt, r.ServerUUID, r.Container)
var b []byte
if b, err = json.Marshal(r); err != nil {
return fmt.Errorf("Failed to Marshal to JSON: %s", err)
return xerrors.Errorf("Failed to Marshal to JSON: %w", err)
}
util.Log.Infof("Uploading...: ServerName: %s, ", r.ServerName)
putObjectInput := &s3.PutObjectInput{
@@ -151,7 +152,7 @@ func (w SaasWriter) Write(rs ...models.ScanResult) (err error) {
}
if _, err := svc.PutObject(putObjectInput); err != nil {
return fmt.Errorf("Failed to upload data to %s/%s, %s",
return xerrors.Errorf("Failed to upload data to %s/%s, err: %w",
tempCredential.S3Bucket, s3Key, err)
}
}

View File

@@ -30,6 +30,7 @@ import (
"github.com/nlopes/slack"
"github.com/parnurzeal/gorequest"
log "github.com/sirupsen/logrus"
"golang.org/x/xerrors"
)
type field struct {
@@ -155,9 +156,9 @@ func send(msg message) error {
if count == retryMax {
return nil
}
return fmt.Errorf(
"HTTP POST error: %v, url: %s, resp: %v, body: %s",
errs, conf.HookURL, resp, body)
return xerrors.Errorf(
"HTTP POST error. url: %s, resp: %v, body: %s, err: %w",
conf.HookURL, resp, body, errs)
}
return nil
}
@@ -167,10 +168,10 @@ func send(msg message) error {
}
boff := backoff.NewExponentialBackOff()
if err := backoff.RetryNotify(f, boff, notify); err != nil {
return fmt.Errorf("HTTP error: %s", err)
return xerrors.Errorf("HTTP error: %w", err)
}
if count == retryMax {
return fmt.Errorf("Retry count exceeded")
return xerrors.New("Retry count exceeded")
}
return nil
}
@@ -202,39 +203,44 @@ func msgText(r models.ScanResult) string {
func toSlackAttachments(r models.ScanResult) (attaches []slack.Attachment) {
vinfos := r.ScannedCves.ToSortedSlice()
for _, vinfo := range vinfos {
curent := []string{}
installed, candidate := []string{}, []string{}
for _, affected := range vinfo.AffectedPackages {
if p, ok := r.Packages[affected.Name]; ok {
curent = append(curent,
installed = append(installed,
fmt.Sprintf("%s-%s", p.Name, p.FormatVer()))
} else {
curent = append(curent, affected.Name)
installed = append(installed, affected.Name)
}
}
for _, n := range vinfo.CpeURIs {
curent = append(curent, n)
}
for _, n := range vinfo.GitHubSecurityAlerts {
curent = append(curent, n.PackageName)
}
new := []string{}
for _, affected := range vinfo.AffectedPackages {
if p, ok := r.Packages[affected.Name]; ok {
if affected.NotFixedYet {
new = append(new, "Not Fixed Yet")
candidate = append(candidate, "Not Fixed Yet")
} else {
new = append(new, p.FormatNewVer())
candidate = append(candidate, p.FormatNewVer())
}
} else {
new = append(new, "?")
candidate = append(candidate, "?")
}
}
for range vinfo.CpeURIs {
new = append(new, "?")
for _, n := range vinfo.CpeURIs {
installed = append(installed, n)
candidate = append(candidate, "?")
}
for range vinfo.GitHubSecurityAlerts {
new = append(new, "?")
for _, n := range vinfo.GitHubSecurityAlerts {
installed = append(installed, n.PackageName)
candidate = append(candidate, "?")
}
for _, wp := range vinfo.WpPackageFixStats {
if p, ok := r.WordPressPackages.Find(wp.Name); ok {
installed = append(installed, fmt.Sprintf("%s-%s", wp.Name, p.Version))
candidate = append(candidate, wp.FixedIn)
} else {
installed = append(installed, wp.Name)
candidate = append(candidate, "?")
}
}
a := slack.Attachment{
@@ -246,12 +252,12 @@ func toSlackAttachments(r models.ScanResult) (attaches []slack.Attachment) {
{
// Title: "Current Package/CPE",
Title: "Installed",
Value: strings.Join(curent, "\n"),
Value: strings.Join(installed, "\n"),
Short: true,
},
{
Title: "Candidate",
Value: strings.Join(new, "\n"),
Value: strings.Join(candidate, "\n"),
Short: true,
},
},
@@ -269,7 +275,7 @@ func cvssColor(cvssScore float64) string {
return "danger"
case 4 <= cvssScore && cvssScore < 7:
return "warning"
case cvssScore < 0:
case cvssScore == 0:
return "#C0C0C0"
default:
return "good"

View File

@@ -22,8 +22,7 @@ import (
"strings"
syslog "github.com/RackSec/srslog"
"github.com/pkg/errors"
"golang.org/x/xerrors"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
@@ -40,7 +39,7 @@ func (w SyslogWriter) Write(rs ...models.ScanResult) (err error) {
sysLog, err := syslog.Dial(conf.Protocol, raddr, severity|facility, conf.Tag)
if err != nil {
return errors.Wrap(err, "Failed to initialize syslog client")
return xerrors.Errorf("Failed to initialize syslog client: %w", err)
}
for _, r := range rs {

View File

@@ -22,15 +22,15 @@ func TestSyslogWriterEncodeSyslog(t *testing.T) {
IPv4Addrs: []string{"192.168.0.1", "10.0.2.15"},
ScannedCves: models.VulnInfos{
"CVE-2017-0001": models.VulnInfo{
AffectedPackages: models.PackageStatuses{
models.PackageStatus{Name: "pkg1"},
models.PackageStatus{Name: "pkg2"},
AffectedPackages: models.PackageFixStatuses{
models.PackageFixStatus{Name: "pkg1"},
models.PackageFixStatus{Name: "pkg2"},
},
},
"CVE-2017-0002": models.VulnInfo{
AffectedPackages: models.PackageStatuses{
models.PackageStatus{Name: "pkg3"},
models.PackageStatus{Name: "pkg4"},
AffectedPackages: models.PackageFixStatuses{
models.PackageFixStatus{Name: "pkg3"},
models.PackageFixStatus{Name: "pkg4"},
},
CveContents: models.CveContents{
models.NvdXML: models.CveContent{
@@ -57,8 +57,8 @@ func TestSyslogWriterEncodeSyslog(t *testing.T) {
IPv6Addrs: []string{"2001:0DB8::1"},
ScannedCves: models.VulnInfos{
"CVE-2017-0003": models.VulnInfo{
AffectedPackages: models.PackageStatuses{
models.PackageStatus{Name: "pkg5"},
AffectedPackages: models.PackageFixStatuses{
models.PackageFixStatus{Name: "pkg5"},
},
CveContents: models.CveContents{
models.RedHat: models.CveContent{

View File

@@ -9,6 +9,7 @@ import (
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
"golang.org/x/xerrors"
)
// TelegramWriter sends report to Telegram
@@ -73,5 +74,5 @@ func checkResponse(r *http.Response) error {
if c := r.StatusCode; 200 <= c && c <= 299 {
return nil
}
return fmt.Errorf("API call to %s failed: %s", r.Request.URL.String(), r.Status)
return xerrors.Errorf("API call to %s failed: %s", r.Request.URL.String(), r.Status)
}

View File

@@ -27,6 +27,7 @@ import (
"time"
"github.com/future-architect/vuls/alert"
"golang.org/x/xerrors"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
@@ -581,7 +582,7 @@ func setSideLayout(g *gocui.Gui) error {
fmt.Fprintln(v, result.ServerInfoTui())
}
if len(scanResults) == 0 {
return fmt.Errorf("No scan results")
return xerrors.New("No scan results")
}
currentScanResult = scanResults[0]
vinfos = scanResults[0].ScannedCves.ToSortedSlice()
@@ -634,9 +635,10 @@ func summaryLines(r models.ScanResult) string {
cvssScore = fmt.Sprintf("| %4.1f", max)
}
packname := vinfo.AffectedPackages.FormatTuiSummary()
packname += strings.Join(vinfo.CpeURIs, ", ")
packname += vinfo.GitHubSecurityAlerts.String()
pkgNames := vinfo.AffectedPackages.Names()
pkgNames = append(pkgNames, vinfo.CpeURIs...)
pkgNames = append(pkgNames, vinfo.GitHubSecurityAlerts.Names()...)
pkgNames = append(pkgNames, vinfo.WpPackageFixStats.Names()...)
alert := " "
if vinfo.AlertDict.HasAlert() {
@@ -648,9 +650,9 @@ func summaryLines(r models.ScanResult) string {
fmt.Sprintf(indexFormat, i+1),
alert + vinfo.CveID,
cvssScore + " |",
fmt.Sprintf("%8s |", vinfo.AttackVector()),
fmt.Sprintf("%1s |", vinfo.AttackVector()),
fmt.Sprintf("%7s |", vinfo.PatchStatus(r.Packages)),
packname,
strings.Join(pkgNames, ", "),
}
icols := make([]interface{}, len(cols))
for j := range cols {
@@ -747,6 +749,22 @@ func setChangelogLayout(g *gocui.Gui) error {
lines = append(lines, "* "+alert.PackageName)
}
r := currentScanResult
for _, wp := range vinfo.WpPackageFixStats {
if p, ok := r.WordPressPackages.Find(wp.Name); ok {
if p.Type == models.WPCore {
lines = append(lines, fmt.Sprintf("* %s-%s, FixedIn: %s",
wp.Name, p.Version, wp.FixedIn))
} else {
lines = append(lines,
fmt.Sprintf("* %s-%s, Update: %s, FixedIn: %s, %s",
wp.Name, p.Version, p.Update, wp.FixedIn, p.Status))
}
} else {
lines = append(lines, fmt.Sprintf("* %s", wp.Name))
}
}
for _, adv := range vinfo.DistroAdvisories {
lines = append(lines, "\n",
"Advisories",
@@ -846,10 +864,13 @@ func detailLines() (string, error) {
}
vinfo := vinfos[currentVinfo]
links := []string{vinfo.CveContents.SourceLinks(
config.Conf.Lang, r.Family, vinfo.CveID)[0].Value,
vinfo.Cvss2CalcURL(),
vinfo.Cvss3CalcURL()}
links := []string{}
if strings.HasPrefix(vinfo.CveID, "CVE-") {
links = append(links, vinfo.CveContents.SourceLinks(
config.Conf.Lang, r.Family, vinfo.CveID)[0].Value,
vinfo.Cvss2CalcURL(),
vinfo.Cvss3CalcURL())
}
for _, url := range vinfo.VendorLinks(r.Family) {
links = append(links, url)
}

View File

@@ -35,6 +35,7 @@ import (
"github.com/future-architect/vuls/util"
"github.com/gosuri/uitable"
"github.com/olekukonko/tablewriter"
"golang.org/x/xerrors"
)
const maxColWidth = 100
@@ -121,17 +122,23 @@ No CVE-IDs are found in updatable packages.
exploits = " Y"
}
link := ""
if strings.HasPrefix(vinfo.CveID, "CVE-") {
link = fmt.Sprintf("https://nvd.nist.gov/vuln/detail/%s", vinfo.CveID)
} else if strings.HasPrefix(vinfo.CveID, "WPVDBID-") {
link = fmt.Sprintf("https://wpvulndb.com/vulnerabilities/%s", strings.TrimPrefix(vinfo.CveID, "WPVDBID-"))
}
data = append(data, []string{
vinfo.CveID,
fmt.Sprintf("%7s", vinfo.PatchStatus(r.Packages)),
vinfo.AlertDict.FormatSource(),
fmt.Sprintf("%4.1f", max),
// fmt.Sprintf("%4.1f", v2max),
// fmt.Sprintf("%4.1f", v3max),
fmt.Sprintf("%8s", vinfo.AttackVector()),
fmt.Sprintf("%7s", vinfo.PatchStatus(r.Packages)),
// packname,
fmt.Sprintf("https://nvd.nist.gov/vuln/detail/%s", vinfo.CveID),
fmt.Sprintf("%2s", vinfo.AttackVector()),
exploits,
link,
})
}
@@ -139,15 +146,14 @@ No CVE-IDs are found in updatable packages.
table := tablewriter.NewWriter(&b)
table.SetHeader([]string{
"CVE-ID",
"Fixed",
"CERT",
"CVSS",
// "v3",
// "v2",
"Attack",
"Fixed",
// "Pkg",
"AV",
"PoC",
"NVD",
"Exploit",
})
table.SetBorder(true)
table.AppendBulk(data)
@@ -243,19 +249,37 @@ No CVE-IDs are found in updatable packages.
data = append(data, []string{"GitHub", alert.PackageName})
}
for _, wp := range vuln.WpPackageFixStats {
if p, ok := r.WordPressPackages.Find(wp.Name); ok {
if p.Type == models.WPCore {
data = append(data, []string{"WordPress",
fmt.Sprintf("%s-%s, FixedIn: %s", wp.Name, p.Version, wp.FixedIn)})
} else {
data = append(data, []string{"WordPress",
fmt.Sprintf("%s-%s, Update: %s, FixedIn: %s, %s",
wp.Name, p.Version, p.Update, wp.FixedIn, p.Status)})
}
} else {
data = append(data, []string{"WordPress",
fmt.Sprintf("%s", wp.Name)})
}
}
for _, confidence := range vuln.Confidences {
data = append(data, []string{"Confidence", confidence.String()})
}
links := vuln.CveContents.SourceLinks(
config.Conf.Lang, r.Family, vuln.CveID)
data = append(data, []string{"Source", links[0].Value})
if strings.HasPrefix(vuln.CveID, "CVE-") {
links := vuln.CveContents.SourceLinks(
config.Conf.Lang, r.Family, vuln.CveID)
data = append(data, []string{"Source", links[0].Value})
if 0 < len(vuln.Cvss2Scores(r.Family)) {
data = append(data, []string{"CVSSv2 Calc", vuln.Cvss2CalcURL()})
}
if 0 < len(vuln.Cvss3Scores()) {
data = append(data, []string{"CVSSv3 Calc", vuln.Cvss3CalcURL()})
if 0 < len(vuln.Cvss2Scores(r.Family)) {
data = append(data, []string{"CVSSv2 Calc", vuln.Cvss2CalcURL()})
}
if 0 < len(vuln.Cvss3Scores()) {
data = append(data, []string{"CVSSv3 Calc", vuln.Cvss3CalcURL()})
}
}
vlinks := vuln.VendorLinks(r.Family)
@@ -292,7 +316,7 @@ No CVE-IDs are found in updatable packages.
table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
table.SetHeader([]string{
vuln.CveID,
"",
vuln.PatchStatus(r.Packages),
})
table.SetBorder(true)
table.AppendBulk(data)
@@ -353,7 +377,7 @@ func overwriteJSONFile(dir string, r models.ScanResult) error {
config.Conf.Diff = false
w := LocalFileWriter{CurrentDir: dir}
if err := w.Write(r); err != nil {
return fmt.Errorf("Failed to write summary report: %s", err)
return xerrors.Errorf("Failed to write summary report: %w", err)
}
config.Conf.FormatJSON = before
config.Conf.Diff = beforeDiff
@@ -521,7 +545,7 @@ var jsonDirPattern = regexp.MustCompile(
func ListValidJSONDirs() (dirs []string, err error) {
var dirInfo []os.FileInfo
if dirInfo, err = ioutil.ReadDir(config.Conf.ResultsDir); err != nil {
err = fmt.Errorf("Failed to read %s: %s",
err = xerrors.Errorf("Failed to read %s: %w",
config.Conf.ResultsDir, err)
return
}
@@ -559,20 +583,20 @@ func JSONDir(args []string) (string, error) {
}
}
return "", fmt.Errorf("Invalid path: %s", path)
return "", xerrors.Errorf("Invalid path: %s", path)
}
// PIPE
if config.Conf.Pipe {
bytes, err := ioutil.ReadAll(os.Stdin)
if err != nil {
return "", fmt.Errorf("Failed to read stdin: %s", err)
return "", xerrors.Errorf("Failed to read stdin: %w", err)
}
fields := strings.Fields(string(bytes))
if 0 < len(fields) {
return filepath.Join(config.Conf.ResultsDir, fields[0]), nil
}
return "", fmt.Errorf("Stdin is invalid: %s", string(bytes))
return "", xerrors.Errorf("Stdin is invalid: %s", string(bytes))
}
// returns latest dir when no args or no PIPE
@@ -580,7 +604,7 @@ func JSONDir(args []string) (string, error) {
return "", err
}
if len(dirs) == 0 {
return "", fmt.Errorf("No results under %s",
return "", xerrors.Errorf("No results under %s",
config.Conf.ResultsDir)
}
return dirs[0], nil
@@ -590,7 +614,7 @@ func JSONDir(args []string) (string, error) {
func LoadScanResults(jsonDir string) (results models.ScanResults, err error) {
var files []os.FileInfo
if files, err = ioutil.ReadDir(jsonDir); err != nil {
return nil, fmt.Errorf("Failed to read %s: %s", jsonDir, err)
return nil, xerrors.Errorf("Failed to read %s: %w", jsonDir, err)
}
for _, f := range files {
if filepath.Ext(f.Name()) != ".json" || strings.HasSuffix(f.Name(), "_diff.json") {
@@ -605,7 +629,7 @@ func LoadScanResults(jsonDir string) (results models.ScanResults, err error) {
results = append(results, *r)
}
if len(results) == 0 {
return nil, fmt.Errorf("There is no json file under %s", jsonDir)
return nil, xerrors.Errorf("There is no json file under %s", jsonDir)
}
return
}
@@ -617,11 +641,11 @@ func loadOneServerScanResult(jsonFile string) (*models.ScanResult, error) {
err error
)
if data, err = ioutil.ReadFile(jsonFile); err != nil {
return nil, fmt.Errorf("Failed to read %s: %s", jsonFile, err)
return nil, xerrors.Errorf("Failed to read %s: %w", jsonFile, err)
}
result := &models.ScanResult{}
if err := json.Unmarshal(data, result); err != nil {
return nil, fmt.Errorf("Failed to parse %s: %s", jsonFile, err)
return nil, xerrors.Errorf("Failed to parse %s: %w", jsonFile, err)
}
return result, nil
}

View File

@@ -192,13 +192,13 @@ func TestDiff(t *testing.T) {
ScannedCves: models.VulnInfos{
"CVE-2012-6702": {
CveID: "CVE-2012-6702",
AffectedPackages: models.PackageStatuses{{Name: "libexpat1"}},
AffectedPackages: models.PackageFixStatuses{{Name: "libexpat1"}},
DistroAdvisories: []models.DistroAdvisory{},
CpeURIs: []string{},
},
"CVE-2014-9761": {
CveID: "CVE-2014-9761",
AffectedPackages: models.PackageStatuses{{Name: "libc-bin"}},
AffectedPackages: models.PackageFixStatuses{{Name: "libc-bin"}},
DistroAdvisories: []models.DistroAdvisory{},
CpeURIs: []string{},
},
@@ -217,13 +217,13 @@ func TestDiff(t *testing.T) {
ScannedCves: models.VulnInfos{
"CVE-2012-6702": {
CveID: "CVE-2012-6702",
AffectedPackages: models.PackageStatuses{{Name: "libexpat1"}},
AffectedPackages: models.PackageFixStatuses{{Name: "libexpat1"}},
DistroAdvisories: []models.DistroAdvisory{},
CpeURIs: []string{},
},
"CVE-2014-9761": {
CveID: "CVE-2014-9761",
AffectedPackages: models.PackageStatuses{{Name: "libc-bin"}},
AffectedPackages: models.PackageFixStatuses{{Name: "libc-bin"}},
DistroAdvisories: []models.DistroAdvisory{},
CpeURIs: []string{},
},
@@ -254,7 +254,7 @@ func TestDiff(t *testing.T) {
ScannedCves: models.VulnInfos{
"CVE-2016-6662": {
CveID: "CVE-2016-6662",
AffectedPackages: models.PackageStatuses{{Name: "mysql-libs"}},
AffectedPackages: models.PackageFixStatuses{{Name: "mysql-libs"}},
DistroAdvisories: []models.DistroAdvisory{},
CpeURIs: []string{},
},
@@ -292,7 +292,7 @@ func TestDiff(t *testing.T) {
ScannedCves: models.VulnInfos{
"CVE-2016-6662": {
CveID: "CVE-2016-6662",
AffectedPackages: models.PackageStatuses{{Name: "mysql-libs"}},
AffectedPackages: models.PackageFixStatuses{{Name: "mysql-libs"}},
DistroAdvisories: []models.DistroAdvisory{},
CpeURIs: []string{},
},
@@ -348,7 +348,7 @@ func TestIsCveFixed(t *testing.T) {
in: In{
v: models.VulnInfo{
CveID: "CVE-2016-6662",
AffectedPackages: models.PackageStatuses{
AffectedPackages: models.PackageFixStatuses{
{
Name: "mysql-libs",
NotFixedYet: false,
@@ -366,7 +366,7 @@ func TestIsCveFixed(t *testing.T) {
ScannedCves: models.VulnInfos{
"CVE-2016-6662": {
CveID: "CVE-2016-6662",
AffectedPackages: models.PackageStatuses{
AffectedPackages: models.PackageFixStatuses{
{
Name: "mysql-libs",
NotFixedYet: true,
@@ -389,7 +389,7 @@ func TestIsCveFixed(t *testing.T) {
in: In{
v: models.VulnInfo{
CveID: "CVE-2016-6662",
AffectedPackages: models.PackageStatuses{
AffectedPackages: models.PackageFixStatuses{
{
Name: "mysql-libs",
NotFixedYet: true,
@@ -407,7 +407,7 @@ func TestIsCveFixed(t *testing.T) {
ScannedCves: models.VulnInfos{
"CVE-2016-6662": {
CveID: "CVE-2016-6662",
AffectedPackages: models.PackageStatuses{
AffectedPackages: models.PackageFixStatuses{
{
Name: "mysql-libs",
NotFixedYet: true,