Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Critical Severity - AST 21466 #644

Merged
merged 33 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
1272770
support to critical severity in consoleSummary, markdown, and html re…
igorlombacx Oct 19, 2023
7e535a7
updating critical severity usages
igorlombacx Oct 23, 2023
4a6b925
Merge branch 'main' into FEATURE/AST-21466-CRITICAL-SEVERITY
igorlombacx Oct 23, 2023
4e6bb39
critical severity for sarif and sonar
igorlombacx Oct 24, 2023
3aa617e
Merge branch 'main' into FEATURE/AST-21466-CRITICAL-SEVERITY
igorlombacx Oct 26, 2023
7b16c63
updating securities map
igorlombacx Oct 26, 2023
a972764
adding the check for CVSS3 feature flag
tiagobcx Nov 2, 2023
609ee49
changing critical triage message
tiagobcx Nov 3, 2023
69e7d6c
changing critical triage message
tiagobcx Nov 3, 2023
5fc25fa
merge with main
tiagobcx Jan 22, 2024
9aab42e
Feature/ast 37694 test critical severity (#696)
PravinGadankush Apr 4, 2024
9815a8e
Revert "Feature/ast 37694 test critical severity (#696)"
pedrompflopes May 17, 2024
c7db597
merge with main
tiagobcx May 23, 2024
362f464
Merge branch 'main' into feature/AST-21466-CRITICAL-SEVERITY
tiagobcx Jun 20, 2024
f122d4f
adding N/A message
tiagobcx Jul 12, 2024
af85739
merge with main and new NA behaviour
tiagobcx Jul 15, 2024
bb10bbf
merge with main and new NA behaviour
tiagobcx Jul 15, 2024
d5164f4
fixing linter + triage
tiagobcx Jul 16, 2024
fe8eb09
fixing tests + linter
tiagobcx Jul 16, 2024
55c7a72
fixing unit tests
tiagobcx Jul 16, 2024
3f25f94
Merge branch 'main' into feature/AST-21466-CRITICAL-SEVERITY
tiagobcx Jul 16, 2024
988da3b
Merge branch 'main' into feature/AST-21466-CRITICAL-SEVERITY
tiagobcx Jul 16, 2024
36c129f
adding new test for critical
tiagobcx Jul 18, 2024
d9a84bd
Merge branch 'main' into feature/AST-21466-CRITICAL-SEVERITY
OrShamirCM Jul 23, 2024
34bc8d4
Update pr_test.go
tiagobcx Jul 25, 2024
9de3497
Merge branch 'main' into feature/AST-21466-CRITICAL-SEVERITY
tamarleviCm Jul 29, 2024
f544812
Update results-mock.go
tiagobcx Jul 30, 2024
b22006c
Merge branch 'main' into feature/AST-21466-CRITICAL-SEVERITY
pedrompflopes Jul 31, 2024
14ef4d7
adding na to containers and apisec
tiagobcx Jul 31, 2024
b0622e2
adding na to containers and apisec
tiagobcx Jul 31, 2024
186fd82
adding na to containers and apisec
tiagobcx Jul 31, 2024
c7327ac
changing ssh repo
tiagobcx Aug 1, 2024
51c946b
changing ssh repo
tiagobcx Aug 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions internal/commands/predicates.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ import (
"github.com/spf13/cobra"
)

func NewResultsPredicatesCommand(resultsPredicatesWrapper wrappers.ResultsPredicatesWrapper) *cobra.Command {
func NewResultsPredicatesCommand(resultsPredicatesWrapper wrappers.ResultsPredicatesWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper) *cobra.Command {
triageCmd := &cobra.Command{
Use: "triage",
Short: "Manage results",
Long: "The 'triage' command enables the ability to manage results in Checkmarx One.",
}
triageShowCmd := triageShowSubCommand(resultsPredicatesWrapper)
triageUpdateCmd := triageUpdateSubCommand(resultsPredicatesWrapper)
triageUpdateCmd := triageUpdateSubCommand(resultsPredicatesWrapper, featureFlagsWrapper)

addFormatFlagToMultipleCommands(
[]*cobra.Command{triageShowCmd},
Expand Down Expand Up @@ -55,7 +55,7 @@ func triageShowSubCommand(resultsPredicatesWrapper wrappers.ResultsPredicatesWra
return triageShowCmd
}

func triageUpdateSubCommand(resultsPredicatesWrapper wrappers.ResultsPredicatesWrapper) *cobra.Command {
func triageUpdateSubCommand(resultsPredicatesWrapper wrappers.ResultsPredicatesWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper) *cobra.Command {
triageUpdateCmd := &cobra.Command{
Use: "update",
Short: "Update the state, severity or comment for the given issue",
Expand All @@ -66,12 +66,12 @@ func triageUpdateSubCommand(resultsPredicatesWrapper wrappers.ResultsPredicatesW
--similarity-id <SimilarityID>
--project-id <ProjectID>
--state <TO_VERIFY|NOT_EXPLOITABLE|PROPOSED_NOT_EXPLOITABLE|CONFIRMED|URGENT>
--severity <HIGH|MEDIUM|LOW|INFO>
--severity <CRITICAL|HIGH|MEDIUM|LOW|INFO>
tiagobcx marked this conversation as resolved.
Show resolved Hide resolved
--comment <Comment(Optional)>
--scan-type <SAST|IAC-SECURITY>
`,
),
RunE: runTriageUpdate(resultsPredicatesWrapper),
RunE: runTriageUpdate(resultsPredicatesWrapper, featureFlagsWrapper),
}

triageUpdateCmd.PersistentFlags().String(params.SimilarityIDFlag, "", "Similarity ID")
Expand Down Expand Up @@ -134,15 +134,20 @@ func runTriageShow(resultsPredicatesWrapper wrappers.ResultsPredicatesWrapper) f
}
}

func runTriageUpdate(resultsPredicatesWrapper wrappers.ResultsPredicatesWrapper) func(*cobra.Command, []string) error {
func runTriageUpdate(resultsPredicatesWrapper wrappers.ResultsPredicatesWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper) func(*cobra.Command, []string) error {
return func(cmd *cobra.Command, _ []string) error {
similarityID, _ := cmd.Flags().GetString(params.SimilarityIDFlag)
projectID, _ := cmd.Flags().GetString(params.ProjectIDFlag)
severity, _ := cmd.Flags().GetString(params.SeverityFlag)
state, _ := cmd.Flags().GetString(params.StateFlag)
comment, _ := cmd.Flags().GetString(params.CommentFlag)
scanType, _ := cmd.Flags().GetString(params.ScanTypeFlag)

// check if the current tenant has critical severity available
flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.CVSSV3Enabled)
criticalEnabled := flagResponse.Status
if !criticalEnabled && strings.EqualFold(severity, "critical") {
return errors.Errorf("%s", "Critical severity is not available for your tenant.This severity status will be enabled shortly")
}
predicate := &wrappers.PredicateRequest{
SimilarityID: similarityID,
ProjectID: projectID,
Expand Down
119 changes: 80 additions & 39 deletions internal/commands/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const (
failedListingResults = "Failed listing results"
failedListingCodeBashing = "Failed codebashing link"
mediumLabel = "medium"
criticalLabel = "critical"
highLabel = "high"
lowLabel = "low"
infoLabel = "info"
Expand All @@ -48,6 +49,7 @@ const (
lowSonar = "MINOR"
mediumSonar = "MAJOR"
highSonar = "CRITICAL"
criticalSonar = "BLOCKER"
infoLowSarif = "note"
mediumSarif = "warning"
highSarif = "error"
Expand All @@ -56,15 +58,17 @@ const (
lowCx = "LOW"
mediumCx = "MEDIUM"
highCx = "HIGH"
tableResultsFormat = " | %-10s %4d %6d %4d %4d %-9s |\n"
stringTableResultsFormat = " | %-10s %4s %6s %4s %4s %5s |\n"
TableTitleFormat = " | %-11s %4s %6s %4s %4s %6s |\n"
criticalCx = "CRITICAL"
tableResultsFormat = " | %-10s %6v %5d %6d %5d %4d %-9s |\n"
stringTableResultsFormat = " | %-10s %5s %6s %6s %5s %4s %5s |\n"
TableTitleFormat = " | %-11s %4s %4s %6s %4s %4s %6s |\n"
twoNewLines = "\n\n"
tableLine = " --------------------------------------------------------- "
tableLine = " --------------------------------------------------------------------- "
codeBashingKey = "cb-url"
failedGettingBfl = "Failed getting BFL"
notAvailableString = "-"
scanFailedString = "Failed"
disabledString = "N/A"
scanFailedString = "Failed "
scanCanceledString = "Canceled"
scanSuccessString = "Completed"
scanPartialString = "Partial"
Expand Down Expand Up @@ -133,19 +137,22 @@ var filterResultsListFlagUsage = fmt.Sprintf(
),
)

// Follows: over 9.0 is critical, 7.0 to 8.9 is high, 4.0 to 6.9 is medium and 3.9 or less is low.
var securities = map[string]string{
infoCx: "3.5",
lowCx: "6.5",
mediumCx: "8.5",
highCx: "9.5",
infoCx: "1.0",
tamarleviCm marked this conversation as resolved.
Show resolved Hide resolved
lowCx: "2.0",
mediumCx: "4.0",
highCx: "7.0",
criticalCx: "9.0",
}

// Match cx severity with sonar severity
var sonarSeverities = map[string]string{
infoCx: infoSonar,
lowCx: lowSonar,
mediumCx: mediumSonar,
highCx: highSonar,
infoCx: infoSonar,
lowCx: lowSonar,
mediumCx: mediumSonar,
highCx: highSonar,
criticalCx: criticalSonar,
}

var containerEngineUnsupportedAgents = []string{
Expand Down Expand Up @@ -501,11 +508,12 @@ func convertScanToResultsSummary(scanInfo *wrappers.ScanResponseModel, resultsWr
scsIssues := 0
var containersIssues *int
enginesStatusCode := map[string]int{
commonParams.SastType: 0,
commonParams.ScaType: 0,
commonParams.KicsType: 0,
commonParams.APISecType: 0,
commonParams.ScsType: 0,
commonParams.SastType: 0,
commonParams.ScaType: 0,
commonParams.KicsType: 0,
commonParams.APISecType: 0,
commonParams.ScsType: 0,
commonParams.ContainersType: 0,
}
if wrappers.IsContainersEnabled {
containersIssues = new(int)
Expand Down Expand Up @@ -543,6 +551,7 @@ func convertScanToResultsSummary(scanInfo *wrappers.ScanResponseModel, resultsWr
ProjectID: scanInfo.ProjectID,
RiskStyle: "",
RiskMsg: "",
CriticalIssues: 0,
HighIssues: 0,
MediumIssues: 0,
LowIssues: 0,
Expand All @@ -557,11 +566,12 @@ func convertScanToResultsSummary(scanInfo *wrappers.ScanResponseModel, resultsWr
BranchName: scanInfo.Branch,
EnginesEnabled: scanInfo.Engines,
EnginesResult: map[string]*wrappers.EngineResultSummary{
commonParams.SastType: {StatusCode: enginesStatusCode[commonParams.SastType]},
commonParams.ScaType: {StatusCode: enginesStatusCode[commonParams.ScaType]},
commonParams.KicsType: {StatusCode: enginesStatusCode[commonParams.KicsType]},
commonParams.APISecType: {StatusCode: enginesStatusCode[commonParams.APISecType]},
commonParams.ScsType: {StatusCode: enginesStatusCode[commonParams.ScsType]},
commonParams.SastType: {StatusCode: enginesStatusCode[commonParams.SastType]},
commonParams.ScaType: {StatusCode: enginesStatusCode[commonParams.ScaType]},
commonParams.KicsType: {StatusCode: enginesStatusCode[commonParams.KicsType]},
commonParams.APISecType: {StatusCode: enginesStatusCode[commonParams.APISecType]},
commonParams.ScsType: {StatusCode: enginesStatusCode[commonParams.ScsType]},
commonParams.ContainersType: {StatusCode: enginesStatusCode[commonParams.ContainersType]},
},
}
if wrappers.IsContainersEnabled {
Expand Down Expand Up @@ -592,6 +602,7 @@ func summaryReport(
policies *wrappers.PolicyResponseModel,
risksOverviewWrapper wrappers.RisksOverviewWrapper,
scsScanOverviewWrapper wrappers.ScanOverviewWrapper,
featureFlagsWrapper wrappers.FeatureFlagsWrapper,
results *wrappers.ScanResultsCollection,
) (*wrappers.ResultSummary, error) {
if summary.HasAPISecurity() {
Expand All @@ -614,7 +625,7 @@ func summaryReport(
summary.Policies = filterViolatedRules(*policies)
}

enhanceWithScanSummary(summary, results)
enhanceWithScanSummary(summary, results, featureFlagsWrapper)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we count api security critical severity? i saw that we found it in line 659, right?

setNotAvailableNumberIfZero(summary, &summary.SastIssues, commonParams.SastType)
setNotAvailableNumberIfZero(summary, &summary.ScaIssues, commonParams.ScaType)
Expand All @@ -636,7 +647,10 @@ func setNotAvailableEnginesStatusCode(summary *wrappers.ResultSummary) {
}

func setRiskMsgAndStyle(summary *wrappers.ResultSummary) {
if summary.HighIssues > 0 {
if summary.CriticalIssues > 0 {
summary.RiskStyle = criticalLabel
summary.RiskMsg = "Critical Risk"
} else if summary.HighIssues > 0 {
summary.RiskStyle = highLabel
summary.RiskMsg = "High Risk"
} else if summary.MediumIssues > 0 {
Expand All @@ -656,14 +670,20 @@ func setNotAvailableNumberIfZero(summary *wrappers.ResultSummary, counter *int,
}
}

func enhanceWithScanSummary(summary *wrappers.ResultSummary, results *wrappers.ScanResultsCollection) {
func enhanceWithScanSummary(summary *wrappers.ResultSummary, results *wrappers.ScanResultsCollection, featureFlagsWrapper wrappers.FeatureFlagsWrapper) {
for _, result := range results.Results {
countResult(summary, result)
}
// Set critical count for a specific engine if critical is disabled
flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.CVSSV3Enabled)
criticalEnabled := flagResponse.Status
if summary.HasAPISecurity() {
summary.EnginesResult[commonParams.APISecType].Low = summary.APISecurity.Risks[3]
summary.EnginesResult[commonParams.APISecType].Medium = summary.APISecurity.Risks[2]
summary.EnginesResult[commonParams.APISecType].High = summary.APISecurity.Risks[1]
if !criticalEnabled {
summary.EnginesResult[commonParams.APISecType].Critical = notAvailableNumber
}
}

if summary.HasSCS() && wrappers.IsSCSEnabled {
Expand All @@ -678,13 +698,22 @@ func enhanceWithScanSummary(summary *wrappers.ResultSummary, results *wrappers.S
if summary.SCSOverview.Status == scanPartialString {
summary.EnginesResult[commonParams.ScsType].StatusCode = scanPartialNumber
}
if !criticalEnabled {
summary.EnginesResult[commonParams.ScsType].Critical = notAvailableNumber
}
}
summary.TotalIssues = summary.SastIssues + summary.ScaIssues + summary.KicsIssues + summary.GetAPISecurityDocumentationTotal()
if wrappers.IsContainersEnabled {
if *summary.ContainersIssues >= 0 {
summary.TotalIssues += *summary.ContainersIssues
}
}
if !criticalEnabled {
summary.EnginesResult[commonParams.SastType].Critical = notAvailableNumber
summary.EnginesResult[commonParams.KicsType].Critical = notAvailableNumber
summary.EnginesResult[commonParams.ScaType].Critical = notAvailableNumber
summary.EnginesResult[commonParams.ContainersType].Critical = notAvailableNumber
}
}

func writeHTMLSummary(targetFile string, summary *wrappers.ResultSummary) error {
Expand Down Expand Up @@ -786,15 +815,15 @@ func printAPIsSecuritySummary(summary *wrappers.ResultSummary) {
func printTableRow(title string, counts *wrappers.EngineResultSummary, statusNumber int) {
switch statusNumber {
case notAvailableNumber:
fmt.Printf(stringTableResultsFormat, title, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString)
fmt.Printf(stringTableResultsFormat, title, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString)
case scanFailedNumber:
fmt.Printf(tableResultsFormat, title, counts.High, counts.Medium, counts.Low, counts.Info, scanFailedString)
fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanFailedString)
case scanCanceledNumber:
fmt.Printf(tableResultsFormat, title, counts.High, counts.Medium, counts.Low, counts.Info, scanCanceledString)
fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanCanceledString)
case scanPartialNumber:
fmt.Printf(tableResultsFormat, title, counts.High, counts.Medium, counts.Low, counts.Info, scanPartialString)
fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanPartialString)
default:
fmt.Printf(tableResultsFormat, title, counts.High, counts.Medium, counts.Low, counts.Info, scanSuccessString)
fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanSuccessString)
}
}

Expand Down Expand Up @@ -823,16 +852,25 @@ func printSCSTableRow(microEngineOverview *wrappers.MicroEngineOverview) {
}
}

func getCountValue(count int) interface{} {
if count < 0 {
return disabledString
}
return count
}

func printResultsSummaryTable(summary *wrappers.ResultSummary) {
totalCriticalIssues := summary.EnginesResult.GetCriticalIssues()
totalHighIssues := summary.EnginesResult.GetHighIssues()
totalMediumIssues := summary.EnginesResult.GetMediumIssues()
totalLowIssues := summary.EnginesResult.GetLowIssues()
totalInfoIssues := summary.EnginesResult.GetInfoIssues()

totalIssues := summary.TotalIssues + summary.ScsIssues
fmt.Printf(tableLine + twoNewLines)
fmt.Printf(" Total Results: %d \n", totalIssues)
fmt.Println(tableLine)
fmt.Printf(TableTitleFormat, " ", "High", "Medium", "Low", "Info", "Status")
fmt.Printf(TableTitleFormat, " ", "Critical", "High", "Medium", "Low", "Info", "Status")

printTableRow("APIs", summary.EnginesResult[commonParams.APISecType], summary.EnginesResult[commonParams.APISecType].StatusCode)
printTableRow("IAC", summary.EnginesResult[commonParams.KicsType], summary.EnginesResult[commonParams.KicsType].StatusCode)
Expand All @@ -847,7 +885,7 @@ func printResultsSummaryTable(summary *wrappers.ResultSummary) {

fmt.Println(tableLine)
fmt.Printf(tableResultsFormat,
"TOTAL", totalHighIssues, totalMediumIssues, totalLowIssues, totalInfoIssues, summary.Status)
"TOTAL", getCountValue(totalCriticalIssues), totalHighIssues, totalMediumIssues, totalLowIssues, totalInfoIssues, summary.Status)
fmt.Printf(tableLine + twoNewLines)
}

Expand Down Expand Up @@ -1025,7 +1063,7 @@ func CreateScanReport(
}
isSummaryNeeded := verifyFormatsByReportList(reportList, summaryFormats...)
if isSummaryNeeded && !scanPending {
summary, err = summaryReport(summary, policyResponseModel, risksOverviewWrapper, scsScanOverviewWrapper, results)
summary, err = summaryReport(summary, policyResponseModel, risksOverviewWrapper, scsScanOverviewWrapper, featureFlagsWrapper, results)
if err != nil {
return err
}
Expand Down Expand Up @@ -1061,7 +1099,10 @@ func countResult(summary *wrappers.ResultSummary, result *wrappers.ScanResult) {
return
}
}

switch severity {
case criticalLabel:
summary.CriticalIssues++
case highLabel:
summary.HighIssues++
case mediumLabel:
Expand Down Expand Up @@ -2055,16 +2096,16 @@ func findProperties(result *wrappers.ScanResult) wrappers.SarifProperties {
sarifProperties.Description = findDescriptionText(result)
sarifProperties.SecuritySeverity = securities[result.Severity]
sarifProperties.Tags = []string{"security", "checkmarx", result.Type}

return sarifProperties
}

func findSarifLevel(result *wrappers.ScanResult) string {
level := map[string]string{
infoCx: infoLowSarif,
lowCx: infoLowSarif,
mediumCx: mediumSarif,
highCx: highSarif,
infoCx: infoLowSarif,
lowCx: infoLowSarif,
mediumCx: mediumSarif,
highCx: highSarif,
criticalCx: highSarif,
}
return level[result.Severity]
}
Expand Down
Loading
Loading