diff --git a/common/logs.go b/common/logs.go index caad3263dc6c534ac132456cf264ac732f245f2c..5dcc0a4b3f86273f3312b5171416f2b4b678ec6e 100644 --- a/common/logs.go +++ b/common/logs.go @@ -15,7 +15,7 @@ func InitLogger() (err error) { } maxlines, lerr := BConfig.Int64("log::maxlines") if lerr != nil { - maxlines = 100000 + maxlines = 20000 } logConf := make(map[string]interface{}) diff --git a/conf/app.conf b/conf/app.conf index d8f7ad733a94d61f46c353f9e9aae93839c6d727..f06b5dff12884f81fb84ba512f0331149caee7a1 100644 --- a/conf/app.conf +++ b/conf/app.conf @@ -38,10 +38,10 @@ maxconn = 3000 [log] -log_level = 7 +log_level = 5 log_dir = ./logs log_path = logs/cve.log -maxlines=50000 +maxlines=25000 maxsize=204800 [crontab] diff --git a/conf/product_app.conf b/conf/product_app.conf index 200677aa7dfe89a95e35f1ab515d040b425e1b08..d02e8263761cc31ca8afbffeccc5e18bb6e68662 100644 --- a/conf/product_app.conf +++ b/conf/product_app.conf @@ -39,23 +39,23 @@ maxconn = 3000 [log] -log_level = 7 +log_level = 5 log_dir = ./logs log_path = logs/cve.log -maxlines=50000 +maxlines=20000 maxsize=204800 [crontab] ymalflag = 1 getymal = 0 0 1 * * 1 cveflag = 1 -getcve = 0 55 15 * * * +getcve = 0 0 3 * * * oricveflag = 1 oricvecheck = 0 0 2 * * * getissueflag = 1 getissue = 0 20 1 * * * issueflag = 1 -createissue = 0 0 16 * * * +createissue = 0 0 6 * * * test = 0/10 * * * * * gittokenflag = 2 issueoath = * * */20 * * * @@ -64,7 +64,7 @@ genexcel = 0 30 7 * * * days = -30 prcnum = 50 printlogflag = 1 -printlog = 0 0 1 * * 1 +printlog = 0 0 1 * * 2,6 unlockflag = 1 unlock = 0 0 12 * * * hookflag = 1 diff --git a/cve-py/main.py b/cve-py/main.py index f502341dc471c4dbf8ea510b5db0a7c16a13b390..f988f87b7beae364ba70a7f312d389af54cf89b5 100644 --- a/cve-py/main.py +++ b/cve-py/main.py @@ -16,9 +16,7 @@ Authors: xiaojianghui Date: 10/22/2020 11:01 AM """ from controller import timertaskcontroller -from controller import taskcontroller if __name__ == '__main__': print("The program starts, waiting for the timing task to execute") - taskcontroller.runtabletask() timertaskcontroller.timertask() diff --git a/cve-py/tabletask/export_excel_task.py b/cve-py/tabletask/export_excel_task.py index 63cf08c09b9bcb2410a03026c86e9397bc78718e..851693f7531d05033f2633cf923c35accb351f83 100644 --- a/cve-py/tabletask/export_excel_task.py +++ b/cve-py/tabletask/export_excel_task.py @@ -71,8 +71,10 @@ def generate_excels(status, path): f = xlwt.Workbook() sheet1 = f.add_sheet('sheet1', cell_overwrite_ok=True) # Column field - column_names = ['id', 'cve_id', 'cve_num', 'cve_desc', 'cve_level', 'cve_version', 'repair_time', 'pack_name', - 'nvd_score', 'n_vector_value', 'create_time', 'update_time', 'delete_time', 'status'] + column_names = ['id', 'cve_id', 'cve_num', 'cve_desc', 'cve_level', + 'cve_version', 'repair_time', 'pack_name', + 'nvd_score', 'n_vector_value', 'create_time', 'update_time', + 'delete_time', 'status', 'error_description'] # Write the first row, column name for i in range(0, len(column_names)): sheet1.write(0, i, column_names[i]) @@ -93,6 +95,7 @@ def generate_excels(status, path): sheet1.write(num + 1, 11, i["update_time"]) sheet1.write(num + 1, 12, i["delete_time"]) sheet1.write(num + 1, 13, i['status']) + sheet1.write(num + 1, 14, i['error_description']) num += 1 # save document f.save(path + '-' + cur_date() + '.xls') diff --git a/cve-py/tabletask/gauss_yaml.py b/cve-py/tabletask/gauss_yaml.py index 5ba237ccf7c3d377c760ea52241f76f2bc21daa1..faa444ea939a0e38fabf5a7f7064e81353ecd994 100644 --- a/cve-py/tabletask/gauss_yaml.py +++ b/cve-py/tabletask/gauss_yaml.py @@ -68,7 +68,7 @@ def store_yaml_data(yaml_data): for yaml_key, yaml_value in yaml_data.items(): try: origin_data = select_yaml_origin_data(yaml_key, yaml_value, mysql) - if origin_data is not None: + if origin_data: update_yaml_origin_data(origin_data["id"], yaml_value, mysql) else: insert_yaml_origin_data(yaml_key, yaml_value, mysql) @@ -207,7 +207,7 @@ def select_yaml_origin_data(yaml_key, yaml_value, mysql): "and version = %s" val = (yaml_key, yaml_value["version"]) packages_data = mysql.getOne(sql, val) - if packages_data and len(packages_data) > 0: + if packages_data: return packages_data else: return None diff --git a/cve-py/tabletask/toexcel.py b/cve-py/tabletask/toexcel.py index 89ebcf19db4cc75838c078bf1ae98e179444ba56..ca11238bfa9d422918b3294edd3fbf56b34a5bf7 100644 --- a/cve-py/tabletask/toexcel.py +++ b/cve-py/tabletask/toexcel.py @@ -69,7 +69,8 @@ class MysqlToExcel(object): 'access_complexity', 'privilege_required', 'user_interaction', 'scope', 'confidentiality', 'integrity', 'availability', - 'authentication', 'cve_status', 'create_time', 'update_time', 'delete_time'] + 'authentication', 'cve_status', 'create_time', 'update_time', + 'delete_time'] # Write the first row, column name for i in range(0, len(column_names)): sheet1.write(0, i, column_names[i]) diff --git a/models/modeldb.go b/models/modeldb.go index b385c46418451fc675091e2b58eb5f8b5e987bfd..520f2bae4f87659a76195f310e48d36176491ee2 100644 --- a/models/modeldb.go +++ b/models/modeldb.go @@ -591,20 +591,21 @@ type IssueRepoWhitelist struct { } type IssueCreateRecord struct { - IssueRecordId int64 `orm:"pk;auto;column(id)"` - CveId int64 `orm:"index;column(cve_id)" description:"VulnCenter 外键"` - CveNum string `orm:"size(256);column(cve_num);index" description:"cve编号"` - Description string `orm:"size(8192);column(cve_desc)" description:"cve描述"` - CveLevel string `orm:"size(32);column(cve_level)" description:"致命(Critical);严重(High);中等(Medium);一般(Low);其他"` - Status int8 `orm:"default(1);column(status)" description:"1:已创建issue;2:未创建issue;3:创建失败; 4: 已导出"` - CveVersion string `orm:"size(128);column(cve_version)" description:"cve归属版本"` - RepairTime string `orm:"size(32);column(repair_time)" description:"cve修复时间"` - PackName string `orm:"size(512);column(pack_name)" description:"cve对应得包名称"` - NVDScore float64 `orm:"digits(10);decimals(1);column(nvd_score)" description:"nvd 评分"` - NvectorVule string `orm:"size(256);column(n_vector_value)" description:"nvd vector 原始值"` - CreateTime string `orm:"size(32);column(create_time)"` - UpdateTime string `orm:"size(32);column(update_time);null"` - DeleteTime string `orm:"size(32);column(delete_time);null"` + IssueRecordId int64 `orm:"pk;auto;column(id)"` + CveId int64 `orm:"index;column(cve_id)" description:"VulnCenter 外键"` + CveNum string `orm:"size(256);column(cve_num);index" description:"cve编号"` + Description string `orm:"size(8192);column(cve_desc)" description:"cve描述"` + CveLevel string `orm:"size(32);column(cve_level)" description:"致命(Critical);严重(High);中等(Medium);一般(Low);其他"` + Status int8 `orm:"default(1);column(status)" description:"1:已创建issue;2:未创建issue;3:创建失败; 4: 已导出"` + CveVersion string `orm:"size(128);column(cve_version)" description:"cve归属版本"` + RepairTime string `orm:"size(32);column(repair_time)" description:"cve修复时间"` + PackName string `orm:"size(512);column(pack_name)" description:"cve对应得包名称"` + NVDScore float64 `orm:"digits(10);decimals(1);column(nvd_score)" description:"nvd 评分"` + NvectorVule string `orm:"size(256);column(n_vector_value)" description:"nvd vector 原始值"` + ErrorDescription string `orm:"size(1024);column(error_description);null" description:"创建cve错误信息反馈"` + CreateTime string `orm:"size(32);column(create_time)"` + UpdateTime string `orm:"size(32);column(update_time);null"` + DeleteTime string `orm:"size(32);column(delete_time);null"` } type OpenGussYaml struct { diff --git a/task/issuetask.go b/task/issuetask.go index 1a1f9d77e1fb5b9913d7b6f4c222b152b82c3815..c9c542f398e0d2644ceaf7cecf0f704942b497b9 100644 --- a/task/issuetask.go +++ b/task/issuetask.go @@ -5,6 +5,7 @@ import ( "cvevulner/models" "cvevulner/taskhandler" "errors" + "fmt" "github.com/astaxie/beego" "github.com/astaxie/beego/config" "github.com/astaxie/beego/logs" @@ -77,6 +78,24 @@ func GenIssueRecordData(icr *models.IssueCreateRecord, issueValue models.VulnCen icr.CreateTime = common.GetCurTime() } +func ErrorCveStatistics(errDesc string, issueValue models.VulnCenter, status int8) { + if issueValue.OrganizationID != 2 { + sc, err := models.QueryIssueScore(issueValue.CveId) + if err != nil || sc.Id == 0 { + logs.Error("获取Score 失败, err: ", err, "cveId: ", issueValue.CveId) + return + } + icr := models.IssueCreateRecord{ErrorDescription: errDesc} + GenIssueRecordData(&icr, issueValue, sc, status) + issueRecordId, issReErr := models.CreateIssueRecord(&icr) + if issReErr == nil && issueRecordId > 0 { + logs.Info("Issue record data created successfully, id:", issueRecordId) + } else { + logs.Error("Failed to create issue record data, err: ", issReErr) + } + } +} + var mutex sync.Mutex func addUnlimitedIssue(beforeTime string, prcnum int, years, toolYears, manYears int) error { @@ -111,6 +130,7 @@ func addUnlimitedIssue(beforeTime string, prcnum int, years, toolYears, manYears if seError == nil && se.Id > 0 { models.UpdateIssueStatus(issueValue, 5) logs.Info("The current issue does not need to be processed, it has been processed, cveData: ", issueValue) + ErrorCveStatistics("CVE已经归档无需处理", issueValue, 2) continue } // Determine whether the issue has been processed @@ -120,6 +140,7 @@ func addUnlimitedIssue(beforeTime string, prcnum int, years, toolYears, manYears goi.State == "已完成" || goi.State == "已拒绝" || goi.IssueState == "已挂起" { models.UpdateIssueStatus(issueValue, 2) logs.Info("The cve data has already been submitted to the issue, no need to submit repeatedly, cveData: ", issueValue) + ErrorCveStatistics("CVE已创建issue, 且已归档", issueValue, 2) continue } } @@ -134,23 +155,11 @@ func addUnlimitedIssue(beforeTime string, prcnum int, years, toolYears, manYears years = manYears } if cveYears <= years { - icr := models.IssueCreateRecord{} models.UpdateIssueStatus(issueValue, 4) logs.Info("cve: ", issueValue.CveNum, ",Need to be greater than: ", years, ",Otherwise, there is no need to submit an issue on git, cveData: ", issueValue) - sc, err := models.QueryIssueScore(issueValue.CveId) - if err != nil || sc.Id == 0 { - logs.Error("Failed to get Score, err: ", err, "cveId: ", issueValue.CveId) - continue - } if issueValue.OrganizationID != 2 { - GenIssueRecordData(&icr, issueValue, sc, 2) - issueRecordId, issReErr := models.CreateIssueRecord(&icr) - if issReErr == nil && issueRecordId > 0 { - logs.Info("Issue record data created successfully, id:", issueRecordId) - } else { - logs.Error("Failed to create issue record data, err: ", issReErr) - } + ErrorCveStatistics("CVE年限受限", issueValue, 2) } continue } @@ -162,6 +171,7 @@ func addUnlimitedIssue(beforeTime string, prcnum int, years, toolYears, manYears models.UpdateIssueStatus(issueValue, 2) logs.Info("The cve data has been displayed on the official website, "+ "no need to submit an issue on git, cveData: ", issueValue) + ErrorCveStatistics("CVE已经在官网展示, 已修复", issueValue, 1) continue } // Process each piece of cve data @@ -172,6 +182,8 @@ func addUnlimitedIssue(beforeTime string, prcnum int, years, toolYears, manYears mutex.Unlock() if err != nil { logs.Error("Failed to create issue, cvenum: ", issueValue.CveNum, "err,err: ", err) + errDesc := fmt.Sprintf("%v", err) + ErrorCveStatistics(errDesc, issueValue, 2) continue } } else { @@ -181,24 +193,14 @@ func addUnlimitedIssue(beforeTime string, prcnum int, years, toolYears, manYears mutex.Unlock() if err != nil { logs.Error("Failed to update issue, cvenum: ", issueValue.CveNum, "err,err: ", err) + errDesc := fmt.Sprintf("%v", err) + ErrorCveStatistics(errDesc, issueValue, 2) continue } } // Collect issue record data - icr := models.IssueCreateRecord{} - sc, err := models.QueryIssueScore(issueValue.CveId) - if err != nil || sc.Id == 0 { - logs.Error("Failed to get Score, err: ", err, "cveId: ", issueValue.CveId) - continue - } if issueValue.OrganizationID != 2 { - GenIssueRecordData(&icr, issueValue, sc, 1) - issueRecordId, issReErr := models.CreateIssueRecord(&icr) - if issReErr == nil && issueRecordId > 0 { - logs.Info("Issue record data created successfully, id:", issueRecordId) - } else { - logs.Error("Failed to create issue record data, err: ", issReErr) - } + ErrorCveStatistics("success", issueValue, 1) } } } @@ -246,6 +248,7 @@ func addLimitedIssue(beforeTime string, prcnum int, years, toolYears, manYears i models.UpdateIssueStatus(issueValue, 5) logs.Info("The current issue does not need to be processed,"+ " it has been processed, cveData: ", issueValue) + ErrorCveStatistics("CVE已经归档无需处理", issueValue, 2) continue } // Determine whether the issue has been processed @@ -255,6 +258,7 @@ func addLimitedIssue(beforeTime string, prcnum int, years, toolYears, manYears i goi.State == "已完成" || goi.State == "已拒绝" || goi.IssueState == "已挂起" { models.UpdateIssueStatus(issueValue, 2) logs.Info("cve数据已经已经提交过issue,不需要重复提交, cveData: ", issueValue) + ErrorCveStatistics("CVE已创建issue, 且已归档", issueValue, 2) continue } } @@ -269,23 +273,11 @@ func addLimitedIssue(beforeTime string, prcnum int, years, toolYears, manYears i years = manYears } if cveYears <= years { - icr := models.IssueCreateRecord{} models.UpdateIssueStatus(issueValue, 4) logs.Info("cve: ", issueValue.CveNum, ",需要大于: ", years, ",否则不需要在git上提交issue, cveData: ", issueValue) - sc, err := models.QueryIssueScore(issueValue.CveId) - if err != nil || sc.Id == 0 { - logs.Error("获取Score 失败, err: ", err, "cveId: ", issueValue.CveId) - continue - } if issueValue.OrganizationID != 2 { - GenIssueRecordData(&icr, issueValue, sc, 2) - issueRecordId, issReErr := models.CreateIssueRecord(&icr) - if issReErr == nil && issueRecordId > 0 { - logs.Info("Issue record data created successfully, id:", issueRecordId) - } else { - logs.Error("Failed to create issue record data, err: ", issReErr) - } + ErrorCveStatistics("CVE年限受限", issueValue, 2) } continue } @@ -296,6 +288,7 @@ func addLimitedIssue(beforeTime string, prcnum int, years, toolYears, manYears i if issueExist { models.UpdateIssueStatus(issueValue, 2) logs.Info("cve数据已经在官网上展示过,不需要在git上提交issue, cveData: ", issueValue) + ErrorCveStatistics("CVE已经在官网展示, 已修复", issueValue, 1) continue } // Process each piece of cve data @@ -305,6 +298,8 @@ func addLimitedIssue(beforeTime string, prcnum int, years, toolYears, manYears i mutex.Unlock() if err != nil { logs.Error("创建issue失败, cvenum: ", issueValue.CveNum, "err,err: ", err) + errDesc := fmt.Sprintf("%v", err) + ErrorCveStatistics(errDesc, issueValue, 2) continue } } else { @@ -313,24 +308,14 @@ func addLimitedIssue(beforeTime string, prcnum int, years, toolYears, manYears i mutex.Unlock() if err != nil { logs.Error("修改issue失败, cvenum: ", issueValue.CveNum, "err,err: ", err) + errDesc := fmt.Sprintf("%v", err) + ErrorCveStatistics(errDesc, issueValue, 2) continue } } // Collect issue record data - icr := models.IssueCreateRecord{} - sc, err := models.QueryIssueScore(issueValue.CveId) - if err != nil || sc.Id == 0 { - logs.Error("获取Score 失败, err: ", err, "cveId: ", issueValue.CveId) - continue - } if issueValue.OrganizationID != 2 { - GenIssueRecordData(&icr, issueValue, sc, 1) - issueRecordId, issReErr := models.CreateIssueRecord(&icr) - if issReErr == nil && issueRecordId > 0 { - logs.Info("Issue record data created successfully, id:", issueRecordId) - } else { - logs.Error("Failed to create issue record data, err: ", issReErr) - } + ErrorCveStatistics("success", issueValue, 1) } } } @@ -403,7 +388,13 @@ func ProcUpdateIssue(issueValue models.VulnCenter, accessToken, owner string) er sr, err := models.QueryIssueScoreRecord(issueValue.CveId, 0) if err != nil { logs.Error("Failed to query score records, cveId: ", issueValue.CveId, "err: ", err) - return err + sc, err := models.QueryIssueScore(issueValue.CveId) + if err != nil { + logs.Error("获取Score 失败, err: ", err, "cveId: ", issueValue.CveId) + return errors.New("NVD评分缺失") + } + sr.NVDScore = sc.NVDScore + sr.NvectorVule = sc.NvectorVule } // Query issue template var it models.IssueTemplate @@ -440,7 +431,7 @@ func ProcUpdateIssue(issueValue models.VulnCenter, accessToken, owner string) er issueValue.PackName, ",CveVersion: ", issueValue.CveVersion) // Update issue status models.UpdateIssueStatus(issueValue, 6) - return errors.New("Field is empty") + return errors.New("CVE的描述和NVD信息缺失") } _, err := taskhandler.UpdateIssueToGit(accessToken, owner, path, issueValue, it) @@ -457,7 +448,7 @@ func ProcUpdateIssue(issueValue models.VulnCenter, accessToken, owner string) er templetID, err := models.CreateIssueTemplate(&it) if err != nil { logs.Error("修改issue模板失败, cveId: ", issueValue.CveId, "err: ", err) - return err + //return err } models.UpdateIssueScoreRe(issueValue, 1) logs.Info("更新issue模板成功,cveId: ", issueValue.CveId, "templetID: ", templetID) @@ -488,12 +479,12 @@ func ProcIssue(issueValue models.VulnCenter, } } else { logs.Error("获取security 失败, err: ", err, "cveId: ", issueValue.CveId) - return err + return errors.New("CVE描述缺失") } sc, err := models.QueryIssueScore(issueValue.CveId) if err != nil { logs.Error("获取Score 失败, err: ", err, "cveId: ", issueValue.CveId) - return err + return errors.New("NVD评分缺失") } branchList := []string{} errBrands := errors.New("") @@ -516,7 +507,7 @@ func ProcIssue(issueValue models.VulnCenter, issueValue.PackName, ",CveVersion: ", issueValue.CveVersion) // Update issue status models.UpdateIssueStatus(issueValue, 6) - return errors.New("Field is empty") + return errors.New("CVE的描述和NVD信息缺失") } resp, err := taskhandler.CreateIssueToGit(accessToken, owner, path, assignee, issueValue, sc, brandArry) if err != nil && err.Error() != "Recreate issue" { diff --git a/taskhandler/createissue.go b/taskhandler/createissue.go index 8ccea0b4fbc52b96f50a5501e549c88a881b18ac..d3fdda75419d1227a3e6aeb69ccb18ae3835b71c 100644 --- a/taskhandler/createissue.go +++ b/taskhandler/createissue.go @@ -174,11 +174,11 @@ func CreateIssueToGit(accessToken, owner, path, assignee string, updateLock.Unlock() if err != nil { logs.Error("Update issue failed, cveNum: ", cve.CveNum, "err: ", err, ",url: ", url) - return "", err + return "", errors.New("调用gitee更新issue接口失败") } if _, ok := resp["id"]; !ok { logs.Error("Update issue failed, err: ", ok, "url: ", url) - return "", errors.New("Update issue failed") + return "", errors.New("调用gitee更新issue接口失败") } logs.Info("Update issue successfully, cveNum: ", cve.CveNum, "issueNum: ", resp["number"].(string)) // Structure data @@ -188,7 +188,7 @@ func CreateIssueToGit(accessToken, owner, path, assignee string, issTempID, err := models.CreateIssueTemplate(&it) if err != nil { logs.Error("Failed to update data of issue template, cveNum: ", cve.CveNum, ",err: ", err) - return "", err + //return "", nil } logs.Info("Successfully updated the data of the issue template, issTempID: ", issTempID, ",cveNum: ", cve.CveNum) } else { @@ -222,12 +222,12 @@ func CreateIssueToGit(accessToken, owner, path, assignee string, if err != nil { logs.Error("url: ", url, "Failed to create issue, cveNum: ", cve.CveNum, ", err: ", err, ",url:", url) models.DeleteIssueTemplate(issTempID) - return "", err + return "", errors.New("调用gitee的创建issue接口失败") } if _, ok := resp["id"]; !ok { logs.Error("Failed to create issue, err: ", ok, "url: ", url) models.DeleteIssueTemplate(issTempID) - return "", errors.New("Failed to create issue") + return "", errors.New("调用gitee的创建issue接口失败") } //var issueTemps models.IssueTemplate issueTemp.TemplateId = issTempID @@ -248,9 +248,10 @@ func CreateIssueToGit(accessToken, owner, path, assignee string, if idxErr != nil { logs.Error("Failed to create data for issue template, cveNum: ", cve, ",err: ", err) //models.DeleteIssueTemplate(issTempID) - return "", err + return "", errors.New("内部错误, 模板存储失败") } - logs.Info("The data of the issue template was successfully created, issTempID: ", issTempIDx, "cveNum: ", cve.CveNum) + logs.Info("The data of the issue template was successfully " + + "created, issTempID: ", issTempIDx, "cveNum: ", cve.CveNum) // Create issue comment affectedVersion := "" if len(brandArray) > 0 { @@ -273,7 +274,7 @@ func CreateIssueToGit(accessToken, owner, path, assignee string, err = CreateDepositHooks(accessToken, owner, path, cve, issueNum, issueID) if err != nil { logs.Error("Failed to create hooks, cveNum: ", cve.CveNum, "err: ", err) - return "", err + return "", errors.New("创建webhook失败") } logs.Info("Create hooks successfully, cveNum: ", cve.CveNum) // Update issue status @@ -370,11 +371,11 @@ func UpdateIssueToGit(accessToken string, owner string, path string, updateLock.Unlock() if err != nil { logs.Error("更新issue失败, cveNum: ", cve.CveNum, "err: ", err) - return "", err + return "", errors.New("调用gitee更新issue的接口失败") } if _, ok := resp["id"]; !ok { logs.Error("创建issue 失败, err: ", ok, "url: ", url) - return "", errors.New("创建issue失败") + return "", errors.New("调用gitee更新issue的接口失败") } // Store security bulletin related information var sec models.SecurityNotice @@ -382,7 +383,7 @@ func UpdateIssueToGit(accessToken string, owner string, path string, secId, err := models.UpdateSecNotice(&sec) if err != nil { logs.Error("更新安全信息失败,CveNum: ", cve.CveNum, ",path: ", path, ",err: ", err) - return "", err + return "", errors.New("内部错误, 数据错误") } else { logs.Info("更新安全信息成功, secId: ", secId, ",cveNum: ", cve.CveNum) }