1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-09-16 09:26:22 +02:00

CxOne: support Critical severity (#5418)

This commit is contained in:
thtri
2025-07-24 14:22:05 +02:00
committed by GitHub
parent 6a715b8c16
commit e778c5bfa2
6 changed files with 117 additions and 12 deletions

View File

@@ -808,6 +808,7 @@ func (c *checkmarxOneExecuteScanHelper) getDetailedResults(scan *checkmarxOne.Sc
resultMap["Preset"] = scanmeta.PresetName
resultMap["DeepLink"] = fmt.Sprintf("%v/projects/%v/overview?branch=%v", c.config.ServerURL, c.Project.ProjectID, url.QueryEscape(scan.Branch))
resultMap["ReportCreationTime"] = time.Now().String()
resultMap["Critical"] = map[string]int{}
resultMap["High"] = map[string]int{}
resultMap["Medium"] = map[string]int{}
resultMap["Low"] = map[string]int{}
@@ -817,6 +818,8 @@ func (c *checkmarxOneExecuteScanHelper) getDetailedResults(scan *checkmarxOne.Sc
for _, result := range *results {
key := "Information"
switch result.Severity {
case "CRITICAL":
key = "Critical"
case "HIGH":
key = "High"
case "MEDIUM":
@@ -1075,20 +1078,29 @@ func (c *checkmarxOneExecuteScanHelper) enforceThresholds(results *map[string]in
insecureResults := []string{}
insecure := false
cxCriticalThreshold := c.config.VulnerabilityThresholdCritical
cxHighThreshold := c.config.VulnerabilityThresholdHigh
cxMediumThreshold := c.config.VulnerabilityThresholdMedium
cxLowThreshold := c.config.VulnerabilityThresholdLow
cxLowThresholdPerQuery := c.config.VulnerabilityThresholdLowPerQuery
cxLowThresholdPerQueryMax := c.config.VulnerabilityThresholdLowPerQueryMax
criticalValue := (*results)["Critical"].(map[string]int)["NotFalsePositive"]
highValue := (*results)["High"].(map[string]int)["NotFalsePositive"]
mediumValue := (*results)["Medium"].(map[string]int)["NotFalsePositive"]
lowValue := (*results)["Low"].(map[string]int)["NotFalsePositive"]
var unit string
criticalViolation := ""
highViolation := ""
mediumViolation := ""
lowViolation := ""
if c.config.VulnerabilityThresholdUnit == "percentage" {
unit = "%"
criticalAudited := (*results)["Critical"].(map[string]int)["Issues"] - (*results)["Critical"].(map[string]int)["NotFalsePositive"]
criticalOverall := (*results)["Critical"].(map[string]int)["Issues"]
if criticalOverall == 0 {
criticalAudited = 1
criticalOverall = 1
}
highAudited := (*results)["High"].(map[string]int)["Issues"] - (*results)["High"].(map[string]int)["NotFalsePositive"]
highOverall := (*results)["High"].(map[string]int)["Issues"]
if highOverall == 0 {
@@ -1107,10 +1119,15 @@ func (c *checkmarxOneExecuteScanHelper) enforceThresholds(results *map[string]in
lowAudited = 1
lowOverall = 1
}
criticalValue = int(float32(criticalAudited) / float32(criticalOverall) * 100.0)
highValue = int(float32(highAudited) / float32(highOverall) * 100.0)
mediumValue = int(float32(mediumAudited) / float32(mediumOverall) * 100.0)
lowValue = int(float32(lowAudited) / float32(lowOverall) * 100.0)
if criticalValue < cxCriticalThreshold {
insecure = true
criticalViolation = fmt.Sprintf("<-- %v %v deviation", cxCriticalThreshold-criticalValue, unit)
}
if highValue < cxHighThreshold {
insecure = true
highViolation = fmt.Sprintf("<-- %v %v deviation", cxHighThreshold-highValue, unit)
@@ -1148,6 +1165,10 @@ func (c *checkmarxOneExecuteScanHelper) enforceThresholds(results *map[string]in
}
if c.config.VulnerabilityThresholdUnit == "absolute" {
unit = " findings"
if criticalValue > cxCriticalThreshold {
insecure = true
criticalViolation = fmt.Sprintf("<-- %v%v deviation", criticalValue-cxCriticalThreshold, unit)
}
if highValue > cxHighThreshold {
insecure = true
highViolation = fmt.Sprintf("<-- %v%v deviation", highValue-cxHighThreshold, unit)
@@ -1162,9 +1183,17 @@ func (c *checkmarxOneExecuteScanHelper) enforceThresholds(results *map[string]in
}
}
criticalText := fmt.Sprintf("Critical %v%v %v", criticalValue, unit, criticalViolation)
highText := fmt.Sprintf("High %v%v %v", highValue, unit, highViolation)
mediumText := fmt.Sprintf("Medium %v%v %v", mediumValue, unit, mediumViolation)
lowText := fmt.Sprintf("Low %v%v %v", lowValue, unit, lowViolation)
if len(criticalViolation) > 0 {
insecureResults = append(insecureResults, criticalText)
log.Entry().Error(criticalText)
} else {
neutralResults = append(neutralResults, criticalText)
log.Entry().Info(criticalText)
}
if len(highViolation) > 0 {
insecureResults = append(insecureResults, highText)
log.Entry().Error(highText)
@@ -1191,6 +1220,13 @@ func (c *checkmarxOneExecuteScanHelper) enforceThresholds(results *map[string]in
}
func (c *checkmarxOneExecuteScanHelper) reportToInflux(results *map[string]interface{}) {
c.influx.checkmarxOne_data.fields.critical_issues = (*results)["Critical"].(map[string]int)["Issues"]
c.influx.checkmarxOne_data.fields.critical_not_false_postive = (*results)["Critical"].(map[string]int)["NotFalsePositive"]
c.influx.checkmarxOne_data.fields.critical_not_exploitable = (*results)["Critical"].(map[string]int)["NotExploitable"]
c.influx.checkmarxOne_data.fields.critical_confirmed = (*results)["Critical"].(map[string]int)["Confirmed"]
c.influx.checkmarxOne_data.fields.critical_urgent = (*results)["Critical"].(map[string]int)["Urgent"]
c.influx.checkmarxOne_data.fields.critical_proposed_not_exploitable = (*results)["Critical"].(map[string]int)["ProposedNotExploitable"]
c.influx.checkmarxOne_data.fields.critical_to_verify = (*results)["Critical"].(map[string]int)["ToVerify"]
c.influx.checkmarxOne_data.fields.high_issues = (*results)["High"].(map[string]int)["Issues"]
c.influx.checkmarxOne_data.fields.high_not_false_postive = (*results)["High"].(map[string]int)["NotFalsePositive"]

View File

@@ -54,6 +54,7 @@ type checkmarxOneExecuteScanOptions struct {
ClientID string `json:"clientId,omitempty"`
VerifyOnly bool `json:"verifyOnly,omitempty"`
VulnerabilityThresholdEnabled bool `json:"vulnerabilityThresholdEnabled,omitempty"`
VulnerabilityThresholdCritical int `json:"vulnerabilityThresholdCritical,omitempty"`
VulnerabilityThresholdHigh int `json:"vulnerabilityThresholdHigh,omitempty"`
VulnerabilityThresholdMedium int `json:"vulnerabilityThresholdMedium,omitempty"`
VulnerabilityThresholdLow int `json:"vulnerabilityThresholdLow,omitempty"`
@@ -76,6 +77,13 @@ type checkmarxOneExecuteScanInflux struct {
}
checkmarxOne_data struct {
fields struct {
critical_issues int
critical_not_false_postive int
critical_not_exploitable int
critical_confirmed int
critical_urgent int
critical_proposed_not_exploitable int
critical_to_verify int
high_issues int
high_not_false_postive int
high_not_exploitable int
@@ -134,6 +142,13 @@ func (i *checkmarxOneExecuteScanInflux) persist(path, resourceName string) {
value interface{}
}{
{valType: config.InfluxField, measurement: "step_data", name: "checkmarxOne", value: i.step_data.fields.checkmarxOne},
{valType: config.InfluxField, measurement: "checkmarxOne_data", name: "critical_issues", value: i.checkmarxOne_data.fields.critical_issues},
{valType: config.InfluxField, measurement: "checkmarxOne_data", name: "critical_not_false_postive", value: i.checkmarxOne_data.fields.critical_not_false_postive},
{valType: config.InfluxField, measurement: "checkmarxOne_data", name: "critical_not_exploitable", value: i.checkmarxOne_data.fields.critical_not_exploitable},
{valType: config.InfluxField, measurement: "checkmarxOne_data", name: "critical_confirmed", value: i.checkmarxOne_data.fields.critical_confirmed},
{valType: config.InfluxField, measurement: "checkmarxOne_data", name: "critical_urgent", value: i.checkmarxOne_data.fields.critical_urgent},
{valType: config.InfluxField, measurement: "checkmarxOne_data", name: "critical_proposed_not_exploitable", value: i.checkmarxOne_data.fields.critical_proposed_not_exploitable},
{valType: config.InfluxField, measurement: "checkmarxOne_data", name: "critical_to_verify", value: i.checkmarxOne_data.fields.critical_to_verify},
{valType: config.InfluxField, measurement: "checkmarxOne_data", name: "high_issues", value: i.checkmarxOne_data.fields.high_issues},
{valType: config.InfluxField, measurement: "checkmarxOne_data", name: "high_not_false_postive", value: i.checkmarxOne_data.fields.high_not_false_postive},
{valType: config.InfluxField, measurement: "checkmarxOne_data", name: "high_not_exploitable", value: i.checkmarxOne_data.fields.high_not_exploitable},
@@ -400,11 +415,12 @@ func addCheckmarxOneExecuteScanFlags(cmd *cobra.Command, stepConfig *checkmarxOn
cmd.Flags().StringVar(&stepConfig.ClientID, "clientId", os.Getenv("PIPER_clientId"), "The username to authenticate")
cmd.Flags().BoolVar(&stepConfig.VerifyOnly, "verifyOnly", false, "Whether the step shall only apply verification checks or whether it does a full scan and check cycle")
cmd.Flags().BoolVar(&stepConfig.VulnerabilityThresholdEnabled, "vulnerabilityThresholdEnabled", true, "Whether the thresholds are enabled or not. If enabled the build will be set to `vulnerabilityThresholdResult` in case a specific threshold value is exceeded")
cmd.Flags().IntVar(&stepConfig.VulnerabilityThresholdHigh, "vulnerabilityThresholdHigh", 100, "The specific threshold for high severity findings")
cmd.Flags().IntVar(&stepConfig.VulnerabilityThresholdMedium, "vulnerabilityThresholdMedium", 100, "The specific threshold for medium severity findings")
cmd.Flags().IntVar(&stepConfig.VulnerabilityThresholdLow, "vulnerabilityThresholdLow", 10, "The specific threshold for low severity findings")
cmd.Flags().BoolVar(&stepConfig.VulnerabilityThresholdLowPerQuery, "vulnerabilityThresholdLowPerQuery", false, "Flag to activate/deactivate the threshold of low severity findings per query")
cmd.Flags().IntVar(&stepConfig.VulnerabilityThresholdLowPerQueryMax, "vulnerabilityThresholdLowPerQueryMax", 10, "Upper threshold of low severity findings per query (in absolute number)")
cmd.Flags().IntVar(&stepConfig.VulnerabilityThresholdCritical, "vulnerabilityThresholdCritical", 100, "The specific threshold for Critical severity findings")
cmd.Flags().IntVar(&stepConfig.VulnerabilityThresholdHigh, "vulnerabilityThresholdHigh", 100, "The specific threshold for High severity findings")
cmd.Flags().IntVar(&stepConfig.VulnerabilityThresholdMedium, "vulnerabilityThresholdMedium", 100, "The specific threshold for Medium severity findings")
cmd.Flags().IntVar(&stepConfig.VulnerabilityThresholdLow, "vulnerabilityThresholdLow", 10, "The specific threshold for Low severity findings")
cmd.Flags().BoolVar(&stepConfig.VulnerabilityThresholdLowPerQuery, "vulnerabilityThresholdLowPerQuery", false, "Flag to activate/deactivate the threshold of Low severity findings per query")
cmd.Flags().IntVar(&stepConfig.VulnerabilityThresholdLowPerQueryMax, "vulnerabilityThresholdLowPerQueryMax", 10, "Upper threshold of Low severity findings per query (in absolute number)")
cmd.Flags().StringVar(&stepConfig.VulnerabilityThresholdResult, "vulnerabilityThresholdResult", `FAILURE`, "The result of the build in case thresholds are enabled and exceeded")
cmd.Flags().StringVar(&stepConfig.VulnerabilityThresholdUnit, "vulnerabilityThresholdUnit", `percentage`, "The unit for the threshold to apply.")
cmd.Flags().BoolVar(&stepConfig.IsOptimizedAndScheduled, "isOptimizedAndScheduled", false, "Whether the pipeline runs in optimized mode and the current execution is a scheduled one")
@@ -782,6 +798,15 @@ func checkmarxOneExecuteScanMetadata() config.StepData {
Aliases: []config.Alias{},
Default: true,
},
{
Name: "vulnerabilityThresholdCritical",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "int",
Mandatory: false,
Aliases: []config.Alias{},
Default: 100,
},
{
Name: "vulnerabilityThresholdHigh",
ResourceRef: []config.ResourceReference{},
@@ -891,7 +916,7 @@ func checkmarxOneExecuteScanMetadata() config.StepData {
Type: "influx",
Parameters: []map[string]interface{}{
{"name": "step_data", "fields": []map[string]string{{"name": "checkmarxOne"}}},
{"name": "checkmarxOne_data", "fields": []map[string]string{{"name": "high_issues"}, {"name": "high_not_false_postive"}, {"name": "high_not_exploitable"}, {"name": "high_confirmed"}, {"name": "high_urgent"}, {"name": "high_proposed_not_exploitable"}, {"name": "high_to_verify"}, {"name": "medium_issues"}, {"name": "medium_not_false_postive"}, {"name": "medium_not_exploitable"}, {"name": "medium_confirmed"}, {"name": "medium_urgent"}, {"name": "medium_proposed_not_exploitable"}, {"name": "medium_to_verify"}, {"name": "low_issues"}, {"name": "low_not_false_postive"}, {"name": "low_not_exploitable"}, {"name": "low_confirmed"}, {"name": "low_urgent"}, {"name": "low_proposed_not_exploitable"}, {"name": "low_to_verify"}, {"name": "information_issues"}, {"name": "information_not_false_postive"}, {"name": "information_not_exploitable"}, {"name": "information_confirmed"}, {"name": "information_urgent"}, {"name": "information_proposed_not_exploitable"}, {"name": "information_to_verify"}, {"name": "lines_of_code_scanned"}, {"name": "files_scanned"}, {"name": "initiator_name"}, {"name": "owner"}, {"name": "scan_id"}, {"name": "project_id"}, {"name": "projectName"}, {"name": "group"}, {"name": "group_full_path_on_report_date"}, {"name": "scan_start"}, {"name": "scan_time"}, {"name": "tool_version"}, {"name": "scan_type"}, {"name": "preset"}, {"name": "deep_link"}, {"name": "report_creation_time"}}},
{"name": "checkmarxOne_data", "fields": []map[string]string{{"name": "critical_issues"}, {"name": "critical_not_false_postive"}, {"name": "critical_not_exploitable"}, {"name": "critical_confirmed"}, {"name": "critical_urgent"}, {"name": "critical_proposed_not_exploitable"}, {"name": "critical_to_verify"}, {"name": "high_issues"}, {"name": "high_not_false_postive"}, {"name": "high_not_exploitable"}, {"name": "high_confirmed"}, {"name": "high_urgent"}, {"name": "high_proposed_not_exploitable"}, {"name": "high_to_verify"}, {"name": "medium_issues"}, {"name": "medium_not_false_postive"}, {"name": "medium_not_exploitable"}, {"name": "medium_confirmed"}, {"name": "medium_urgent"}, {"name": "medium_proposed_not_exploitable"}, {"name": "medium_to_verify"}, {"name": "low_issues"}, {"name": "low_not_false_postive"}, {"name": "low_not_exploitable"}, {"name": "low_confirmed"}, {"name": "low_urgent"}, {"name": "low_proposed_not_exploitable"}, {"name": "low_to_verify"}, {"name": "information_issues"}, {"name": "information_not_false_postive"}, {"name": "information_not_exploitable"}, {"name": "information_confirmed"}, {"name": "information_urgent"}, {"name": "information_proposed_not_exploitable"}, {"name": "information_to_verify"}, {"name": "lines_of_code_scanned"}, {"name": "files_scanned"}, {"name": "initiator_name"}, {"name": "owner"}, {"name": "scan_id"}, {"name": "project_id"}, {"name": "projectName"}, {"name": "group"}, {"name": "group_full_path_on_report_date"}, {"name": "scan_start"}, {"name": "scan_time"}, {"name": "tool_version"}, {"name": "scan_type"}, {"name": "preset"}, {"name": "deep_link"}, {"name": "report_creation_time"}}},
},
},
{

View File

@@ -1356,6 +1356,7 @@ func (sys *SystemInstance) RequestNewReportV2(scanID, reportType string) (string
"filters": map[string][]string{
"scanners": {"sast"},
"severities": {
"critical",
"high",
"medium",
"low",

View File

@@ -94,6 +94,13 @@ func CreateCustomReport(data *map[string]interface{}, insecure, neutral []string
WithCounter: false,
}
detailRows := []reporting.OverviewRow{
{Description: "Critical issues", Details: fmt.Sprint((*data)["Critical"].(map[string]int)["Issues"])},
{Description: "Critical not false positive issues", Details: fmt.Sprint((*data)["Critical"].(map[string]int)["NotFalsePositive"])},
{Description: "Critical not exploitable issues", Details: fmt.Sprint((*data)["Critical"].(map[string]int)["NotExploitable"])},
{Description: "Critical confirmed issues", Details: fmt.Sprint((*data)["Critical"].(map[string]int)["Confirmed"])},
{Description: "Critical urgent issues", Details: fmt.Sprint((*data)["Critical"].(map[string]int)["Urgent"])},
{Description: "Critical proposed not exploitable issues", Details: fmt.Sprint((*data)["Critical"].(map[string]int)["ProposedNotExploitable"])},
{Description: "Critical to verify issues", Details: fmt.Sprint((*data)["Critical"].(map[string]int)["ToVerify"])},
{Description: "High issues", Details: fmt.Sprint((*data)["High"].(map[string]int)["Issues"])},
{Description: "High not false positive issues", Details: fmt.Sprint((*data)["High"].(map[string]int)["NotFalsePositive"])},
{Description: "High not exploitable issues", Details: fmt.Sprint((*data)["High"].(map[string]int)["NotExploitable"])},
@@ -152,6 +159,13 @@ func CreateJSONHeaderReport(data *map[string]interface{}) CheckmarxOneReportData
}
findings := []Finding{}
// Critical
criticalFindings := Finding{}
criticalFindings.ClassificationName = "Critical"
criticalFindings.Total = (*data)["Critical"].(map[string]int)["Issues"]
criticalAudited := (*data)["Critical"].(map[string]int)["Issues"] - (*data)["Critical"].(map[string]int)["NotFalsePositive"]
criticalFindings.Audited = &criticalAudited
findings = append(findings, criticalFindings)
// High
highFindings := Finding{}
highFindings.ClassificationName = "High"

View File

@@ -21,13 +21,20 @@ func TestCreateJSONReport(t *testing.T) {
resultMap["ProjectId"] = `f5702f86-b396-417f-82e2-4949a55d5382`
resultMap["ScanId"] = `21e40b36-0dd7-48e5-9768-da1a8f36c907`
resultMap["Critical"] = map[string]int{}
resultMap["High"] = map[string]int{}
resultMap["Medium"] = map[string]int{}
resultMap["Low"] = map[string]int{}
resultMap["Information"] = map[string]int{}
submap := map[string]int{}
submap["Issues"] = 10
submap["NotFalsePositive"] = 10
resultMap["Critical"] = submap
submap = map[string]int{}
submap["Issues"] = 10
submap["NotFalsePositive"] = 10
resultMap["High"] = submap
submap = map[string]int{}
@@ -74,7 +81,7 @@ func TestCreateJSONReport(t *testing.T) {
assert.Equal(t, "v1", reportingData.ToolVersion)
assert.Equal(t, "Incremental", reportingData.ScanType)
lowList := (*reportingData.Findings)[2].LowPerQuery
lowList := (*reportingData.Findings)[3].LowPerQuery
lowListLen := len(*lowList)
assert.Equal(t, 2, lowListLen)

View File

@@ -327,9 +327,17 @@ spec:
- STAGES
- STEPS
default: true
- name: vulnerabilityThresholdCritical
type: int
description: The specific threshold for Critical severity findings
scope:
- PARAMETERS
- STAGES
- STEPS
default: 100
- name: vulnerabilityThresholdHigh
type: int
description: The specific threshold for high severity findings
description: The specific threshold for High severity findings
scope:
- PARAMETERS
- STAGES
@@ -337,7 +345,7 @@ spec:
default: 100
- name: vulnerabilityThresholdMedium
type: int
description: The specific threshold for medium severity findings
description: The specific threshold for Medium severity findings
scope:
- PARAMETERS
- STAGES
@@ -345,7 +353,7 @@ spec:
default: 100
- name: vulnerabilityThresholdLow
type: int
description: The specific threshold for low severity findings
description: The specific threshold for Low severity findings
scope:
- PARAMETERS
- STAGES
@@ -353,7 +361,7 @@ spec:
default: 10
- name: vulnerabilityThresholdLowPerQuery
type: bool
description: Flag to activate/deactivate the threshold of low severity findings per query
description: Flag to activate/deactivate the threshold of Low severity findings per query
scope:
- PARAMETERS
- STAGES
@@ -361,7 +369,7 @@ spec:
default: false
- name: vulnerabilityThresholdLowPerQueryMax
type: int
description: Upper threshold of low severity findings per query (in absolute number)
description: Upper threshold of Low severity findings per query (in absolute number)
scope:
- PARAMETERS
- STAGES
@@ -427,6 +435,20 @@ spec:
type: bool
- name: checkmarxOne_data
fields:
- name: critical_issues
type: int
- name: critical_not_false_postive
type: int
- name: critical_not_exploitable
type: int
- name: critical_confirmed
type: int
- name: critical_urgent
type: int
- name: critical_proposed_not_exploitable
type: int
- name: critical_to_verify
type: int
- name: high_issues
type: int
- name: high_not_false_postive