diff --git a/src/main/java/com/cx/restclient/CxSASTClient.java b/src/main/java/com/cx/restclient/CxSASTClient.java index 38f9802d..67758c99 100644 --- a/src/main/java/com/cx/restclient/CxSASTClient.java +++ b/src/main/java/com/cx/restclient/CxSASTClient.java @@ -412,7 +412,11 @@ public String getContentTypeAndApiVersion(CxScanConfig config, String apiName) { if (versionComponents.length >= 2) { String currentVersion = versionComponents[0] + "." + versionComponents[1]; float currentVersionFloat = Float.parseFloat(currentVersion); - if (currentVersionFloat >= Float.parseFloat("9.4")) { + if (currentVersionFloat >= Float.parseFloat("9.7")) { + if (apiName.equalsIgnoreCase(SAST_SCAN_RESULTS_STATISTICS)) { + apiVersion = CONTENT_TYPE_APPLICATION_XML_V6; + } + } else if (currentVersionFloat >= Float.parseFloat("9.4")) { if (SAST_RETENTION_RATE.equalsIgnoreCase(apiName) && config.isEnableDataRetention()) { apiVersion = CONTENT_TYPE_API_VERSION_1_1; } else if (SCAN_WITH_SETTINGS_URL.equalsIgnoreCase(apiName)) { @@ -425,6 +429,9 @@ public String getContentTypeAndApiVersion(CxScanConfig config, String apiName) { apiVersion = CONTENT_TYPE_APPLICATION_JSON_V1; } } + else { + apiVersion = CONTENT_TYPE_APPLICATION_JSON_V1; + } } else if (currentVersionFloat >= 9.2 && currentVersionFloat <= 9.3) { apiVersion = CONTENT_TYPE_APPLICATION_JSON_V1; } @@ -531,7 +538,7 @@ public Results waitForScanResults() { resolveSASTViolation(sastResults, projectId); } if (sastResults.getSastScanLink() != null) - SASTUtils.printSASTResultsToConsole(sastResults, config.getEnablePolicyViolations(), log); + SASTUtils.printSASTResultsToConsole(config, sastResults, config.getEnablePolicyViolations(), log); //PDF report if (config.getGeneratePDFReport()) { @@ -704,7 +711,9 @@ private CxID createRemoteSourceRequest(long projectId, String apiVersion,HttpEnt } private SASTStatisticsResponse getScanStatistics(long scanId) throws IOException { - return httpClient.getRequest(SAST_SCAN_RESULTS_STATISTICS.replace(SCAN_ID_PATH_PARAM, Long.toString(scanId)), CONTENT_TYPE_APPLICATION_JSON_V1, SASTStatisticsResponse.class, 200, "SAST scan statistics", false); + String apiVersion = getContentTypeAndApiVersion(config, SAST_SCAN_RESULTS_STATISTICS); + System.out.println("Using API version for SAST scan statistics: " + apiVersion); + return httpClient.getRequest(SAST_SCAN_RESULTS_STATISTICS.replace(SCAN_ID_PATH_PARAM, Long.toString(scanId)), apiVersion, SASTStatisticsResponse.class, 200, "SAST scan statistics", false); } public List getLatestSASTStatus(long projectId) throws IOException { diff --git a/src/main/java/com/cx/restclient/common/summary/SummaryUtils.java b/src/main/java/com/cx/restclient/common/summary/SummaryUtils.java index a2837e0f..88dc7c5f 100644 --- a/src/main/java/com/cx/restclient/common/summary/SummaryUtils.java +++ b/src/main/java/com/cx/restclient/common/summary/SummaryUtils.java @@ -93,6 +93,14 @@ else if(config.isOsaEnabled()) templateData.put("sastLowTotalHeight", sastLowTotalHeight); templateData.put("sastLowNewHeight", sastLowNewHeight); templateData.put("sastLowRecurrentHeight", sastLowRecurrentHeight); + + //sast critical bars + float sastCriticalTotalHeight = (float) sastResults.getCritical() / sastBarNorm * 238f; + float sastCriticalNewHeight = calculateNewBarHeight(sastResults.getNewCritical(), sastResults.getCritical(), sastCriticalTotalHeight); + float sastCriticalRecurrentHeight = sastCriticalTotalHeight - sastCriticalNewHeight; + templateData.put("sastCriticalTotalHeight", sastCriticalTotalHeight); + templateData.put("sastCriticalNewHeight", sastCriticalNewHeight); + templateData.put("sastCriticalRecurrentHeight", sastCriticalRecurrentHeight); } else { buildFailed = true; } diff --git a/src/main/java/com/cx/restclient/configuration/CxScanConfig.java b/src/main/java/com/cx/restclient/configuration/CxScanConfig.java index 252ed36b..6a34bdc5 100644 --- a/src/main/java/com/cx/restclient/configuration/CxScanConfig.java +++ b/src/main/java/com/cx/restclient/configuration/CxScanConfig.java @@ -19,8 +19,18 @@ public class CxScanConfig implements Serializable { private String cxOrigin; private String cxOriginUrl; private CxVersion cxVersion; + private boolean showCriticalLabel = false; + + + public boolean isShowCriticalLabel() { + return showCriticalLabel; + } + + public void setShowCriticalLabel(boolean showCriticalLabel) { + this.showCriticalLabel = showCriticalLabel; + } - private Integer projectRetentionRate; + private Integer projectRetentionRate; private boolean enableDataRetention; private boolean disableCertificateValidation = false; private boolean useSSOLogin = false; @@ -58,6 +68,7 @@ public class CxScanConfig implements Serializable { private Integer sastHighThreshold; private Integer sastMediumThreshold; private Integer sastLowThreshold; + private Integer sastCriticalThreshold; private Boolean sastNewResultsThresholdEnabled = false; private String sastNewResultsThresholdSeverity; private TokenLoginResponse token; @@ -519,6 +530,14 @@ public Integer getSastLowThreshold() { public void setSastLowThreshold(Integer sastLowThreshold) { this.sastLowThreshold = sastLowThreshold; } + + public Integer getSastCriticalThreshold() { + return sastCriticalThreshold; + } + + public void setSastCriticalThreshold(Integer sastCriticalThreshold) { + this.sastCriticalThreshold = sastCriticalThreshold; + } public String getSastNewResultsThresholdSeverity() { return sastNewResultsThresholdSeverity; @@ -645,7 +664,7 @@ public String getOsaDependenciesJson() { } public boolean isSASTThresholdEffectivelyEnabled() { - return isSastEnabled() && getSastThresholdsEnabled() && (getSastHighThreshold() != null || getSastMediumThreshold() != null || getSastLowThreshold() != null); + return isSastEnabled() && getSastThresholdsEnabled() && (getSastHighThreshold() != null || getSastMediumThreshold() != null || getSastLowThreshold() != null || getSastCriticalThreshold() != null); } public boolean isOSAThresholdEffectivelyEnabled() { diff --git a/src/main/java/com/cx/restclient/dto/scansummary/ScanSummary.java b/src/main/java/com/cx/restclient/dto/scansummary/ScanSummary.java index c2bdeae0..23f15228 100644 --- a/src/main/java/com/cx/restclient/dto/scansummary/ScanSummary.java +++ b/src/main/java/com/cx/restclient/dto/scansummary/ScanSummary.java @@ -93,6 +93,7 @@ private void addSastThresholdErrors(CxScanConfig config, SASTResults sastResults checkForThresholdError(sastResults.getHigh(), config.getSastHighThreshold(), ErrorSource.SAST, Severity.HIGH); checkForThresholdError(sastResults.getMedium(), config.getSastMediumThreshold(), ErrorSource.SAST, Severity.MEDIUM); checkForThresholdError(sastResults.getLow(), config.getSastLowThreshold(), ErrorSource.SAST, Severity.LOW); + checkForThresholdError(sastResults.getCritical(), config.getSastCriticalThreshold(), ErrorSource.SAST, Severity.CRITICAL); } } @@ -103,6 +104,7 @@ private void addDependencyScanThresholdErrors(CxScanConfig config, OSAResults os int totalHigh = 0; int totalMedium = 0; int totalLow = 0; + int totalCritical = 0; boolean hasSummary = false; if (scaResults != null) { @@ -141,6 +143,13 @@ private void addNewResultThresholdErrors(CxScanConfig config, SASTResults sastRe } severity = "MEDIUM"; } + + if ("CRITICAL".equals(severity)) { + if (sastResults.getNewCritical() > 0) { + newResultThresholdErrors.add(Severity.CRITICAL); + } + severity = "LOW"; + } if ("MEDIUM".equals(severity)) { if (sastResults.getNewMedium() > 0) { diff --git a/src/main/java/com/cx/restclient/dto/scansummary/Severity.java b/src/main/java/com/cx/restclient/dto/scansummary/Severity.java index 5773df9e..f2973521 100644 --- a/src/main/java/com/cx/restclient/dto/scansummary/Severity.java +++ b/src/main/java/com/cx/restclient/dto/scansummary/Severity.java @@ -3,5 +3,6 @@ public enum Severity { LOW, MEDIUM, - HIGH + HIGH, + CRITICAL } diff --git a/src/main/java/com/cx/restclient/httpClient/utils/ContentType.java b/src/main/java/com/cx/restclient/httpClient/utils/ContentType.java index 3b80839f..8e238f7d 100644 --- a/src/main/java/com/cx/restclient/httpClient/utils/ContentType.java +++ b/src/main/java/com/cx/restclient/httpClient/utils/ContentType.java @@ -14,4 +14,5 @@ public class ContentType { public static final String CONTENT_TYPE_APPLICATION_PDF_V1 = "application/pdf;v=1.0"; public static final String CONTENT_TYPE_APPLICATION_RTF_V1 = "application/rtf;v=1.0"; public static final String CONTENT_TYPE_APPLICATION_CSV_V1 = "application/csv;v=1.0"; + public static final String CONTENT_TYPE_APPLICATION_XML_V6 = "application/json;v=6.0"; } diff --git a/src/main/java/com/cx/restclient/sast/dto/SASTResults.java b/src/main/java/com/cx/restclient/sast/dto/SASTResults.java index c2974e30..af7b04a6 100644 --- a/src/main/java/com/cx/restclient/sast/dto/SASTResults.java +++ b/src/main/java/com/cx/restclient/sast/dto/SASTResults.java @@ -50,11 +50,13 @@ public class SASTResults extends Results implements Serializable { private int high = 0; private int medium = 0; private int low = 0; + private int critical = 0; private int information = 0; private int newHigh = 0; private int newMedium = 0; private int newLow = 0; + private int newCritical = 0; private int newInfo = 0; private String sastScanLink; @@ -96,7 +98,7 @@ public void setSastLanguage(String sastLanguage) { private List sastPolicies = new ArrayList<>(); public enum Severity { - High, Medium, Low, Information; + High, Medium, Low, CRITICAL, Information; } @@ -129,6 +131,9 @@ public void setScanDetailedReport(CxXMLResults reportObj,CxScanConfig config) th case Low: newLow++; break; + case CRITICAL: + newCritical++; + break; case Information: newInfo++; break; @@ -153,6 +158,7 @@ private void setLanguageEquivalent(String sastLanguage) { languageMap.put("High", lang.getHigh()); languageMap.put("Medium", lang.getMedium()); languageMap.put("Low", lang.getLow()); + languageMap.put("CRITICAL", lang.getCritical()); } } @@ -169,6 +175,7 @@ public void setResults(long scanId, SASTStatisticsResponse statisticsResults, St setHigh(statisticsResults.getHighSeverity()); setMedium(statisticsResults.getMediumSeverity()); setLow(statisticsResults.getLowSeverity()); + setCritical(statisticsResults.getCriticalSeverity()); setInformation(statisticsResults.getInfoSeverity()); setSastScanLink(url, scanId, projectId); setSastProjectLink(url, projectId); @@ -209,6 +216,14 @@ public int getLow() { public void setLow(int low) { this.low = low; } + + public int getCritical() { + return critical; + } + + public void setCritical(int critical) { + this.critical = critical; + } public int getInformation() { return information; @@ -241,6 +256,14 @@ public int getNewLow() { public void setNewLow(int newLow) { this.newLow = newLow; } + + public int getNewCritical() { + return newCritical; + } + + public void setNewCritical(int newCritical) { + this.newCritical = newCritical; + } public int getNewInfo() { return newInfo; @@ -371,7 +394,7 @@ public void setPDFReport(byte[] PDFReport) { } public boolean hasNewResults() { - return newHigh + newMedium + newLow > 0; + return newHigh + newMedium + newLow + newCritical > 0; } private void setScanStartEndDates(String scanStart, String scanTime, String lang) { diff --git a/src/main/java/com/cx/restclient/sast/dto/SASTStatisticsResponse.java b/src/main/java/com/cx/restclient/sast/dto/SASTStatisticsResponse.java index 803fcca0..a4579578 100644 --- a/src/main/java/com/cx/restclient/sast/dto/SASTStatisticsResponse.java +++ b/src/main/java/com/cx/restclient/sast/dto/SASTStatisticsResponse.java @@ -10,6 +10,7 @@ public class SASTStatisticsResponse { private int highSeverity; private int mediumSeverity; private int lowSeverity; + private int criticalSeverity; private int infoSeverity; public int getHighSeverity() { @@ -35,6 +36,14 @@ public int getLowSeverity() { public void setLowSeverity(int lowSeverity) { this.lowSeverity = lowSeverity; } + + public int getCriticalSeverity() { + return criticalSeverity; + } + + public void setCriticalSeverity(int criticalSeverity) { + this.criticalSeverity = criticalSeverity; + } public int getInfoSeverity() { return infoSeverity; diff --git a/src/main/java/com/cx/restclient/sast/dto/SupportedLanguage.java b/src/main/java/com/cx/restclient/sast/dto/SupportedLanguage.java index 3ee06bee..3c3d0c94 100644 --- a/src/main/java/com/cx/restclient/sast/dto/SupportedLanguage.java +++ b/src/main/java/com/cx/restclient/sast/dto/SupportedLanguage.java @@ -4,28 +4,30 @@ public enum SupportedLanguage { - ENUS(new Locale("en-US"),"High","Medium","Low","Information", "EEEE, MMMM dd, yyyy hh:mm:ss a"), - JAJP(new Locale("ja-JP"),"高","中","低","情報","yyyy年M月d日 H:mm:ss"), - FRFR(new Locale("fr-FR"),"Haute","Moyenne","Basse","Informations","EEEE dd MMMM yyyy HH:mm:ss"), - PTBR(new Locale("pt-BR"),"Alto","Médio","Baixo","Em formação", "EEEE, d 'de' MMMM 'de' yyyy HH:mm:ss"), - ESES(new Locale("es-ES"),"Altas","Medias","Bajas","Información","EEEE, d 'de' MMMM 'de' yyyy HH:mm:ss"), - KOKR(new Locale("ko-KR"),"높음","중간","낮음","정보", "yyyy년 M월 d일 EEEE a h:mm:ss"), - ZHCN(new Locale("zh-CN"),"高危","中危","低危","信息", "yyyy年M月d日 HH:mm:ss"), - ZHTW(new Locale("zh-TW"),"高","中","低","信息", "yyyy年M月d日 a hh:mm:ss"), - RURU(new Locale("ru-RU"),"Высокое","Среднее","Низкое","Информация","d MMMM yyyy 'г'. H:mm:ss"); + ENUS(new Locale("en-US"),"High","Medium","Low","CRITICAL","Information", "EEEE, MMMM dd, yyyy hh:mm:ss a"), + JAJP(new Locale("ja-JP"),"高","中","低","危うい","情報","yyyy年M月d日 H:mm:ss"), + FRFR(new Locale("fr-FR"),"Haute","Moyenne","Basse","critique","Informations","EEEE dd MMMM yyyy HH:mm:ss"), + PTBR(new Locale("pt-BR"),"Alto","Médio","Baixo","crítico","Em formação", "EEEE, d 'de' MMMM 'de' yyyy HH:mm:ss"), + ESES(new Locale("es-ES"),"Altas","Medias","Bajas","Crítico","Información","EEEE, d 'de' MMMM 'de' yyyy HH:mm:ss"), + KOKR(new Locale("ko-KR"),"높음","중간","낮음","비판적인","정보", "yyyy년 M월 d일 EEEE a h:mm:ss"), + ZHCN(new Locale("zh-CN"),"高危","中危","低危","危急","信息", "yyyy年M月d日 HH:mm:ss"), + ZHTW(new Locale("zh-TW"),"高","中","低","危急","信息", "yyyy年M月d日 a hh:mm:ss"), + RURU(new Locale("ru-RU"),"Высокое","Среднее","Низкое","критический","Информация","d MMMM yyyy 'г'. H:mm:ss"); private final Locale locale; private final String High; private final String Medium; private final String Low; + private final String Critical; private final String Information; private final String datePattern; - private SupportedLanguage(Locale locale, String high, String medium, String low, String information, String datePattern) { + private SupportedLanguage(Locale locale, String high, String medium, String low, String critical, String information, String datePattern) { this.locale = locale; this.High = high; this.Medium = medium; this.Low = low; + this.Critical = critical; this.Information = information; this.datePattern = datePattern; } @@ -45,6 +47,10 @@ public String getMedium() { public String getLow() { return Low; } + + public String getCritical() { + return Critical; + } public String getInformation() { return Information; diff --git a/src/main/java/com/cx/restclient/sast/utils/LegacyClient.java b/src/main/java/com/cx/restclient/sast/utils/LegacyClient.java index fb16e21e..bd31f27e 100644 --- a/src/main/java/com/cx/restclient/sast/utils/LegacyClient.java +++ b/src/main/java/com/cx/restclient/sast/utils/LegacyClient.java @@ -258,6 +258,12 @@ public String getCxVersion() throws IOException, CxClientException { return version; } + public String login(Boolean isVersionRequired) throws IOException { + String cxVersion = getCxVersion(); + login(cxVersion); + return cxVersion; + } + public void login() throws IOException { String version = getCxVersion(); login(version); diff --git a/src/main/java/com/cx/restclient/sast/utils/SASTUtils.java b/src/main/java/com/cx/restclient/sast/utils/SASTUtils.java index bdb38613..999c481e 100644 --- a/src/main/java/com/cx/restclient/sast/utils/SASTUtils.java +++ b/src/main/java/com/cx/restclient/sast/utils/SASTUtils.java @@ -10,6 +10,8 @@ import org.glassfish.jaxb.runtime.v2.JAXBContextFactory; import org.slf4j.Logger; +import com.cx.restclient.configuration.CxScanConfig; +import com.cx.restclient.dto.CxVersion; import com.cx.restclient.exception.CxClientException; import com.cx.restclient.sast.dto.CxXMLResults; import com.cx.restclient.sast.dto.SASTResults; @@ -38,17 +40,30 @@ public static CxXMLResults convertToXMLResult(byte[] cxReport) throws CxClientEx return reportObj; } - public static void printSASTResultsToConsole(SASTResults sastResults, boolean enableViolations, Logger log) { + public static void printSASTResultsToConsole(CxScanConfig config, SASTResults sastResults, boolean enableViolations, Logger log) { String highNew = sastResults.getNewHigh() > 0 ? " (" + sastResults.getNewHigh() + " new)" : ""; String mediumNew = sastResults.getNewMedium() > 0 ? " (" + sastResults.getNewMedium() + " new)" : ""; String lowNew = sastResults.getNewLow() > 0 ? " (" + sastResults.getNewLow() + " new)" : ""; + String criticalNew = sastResults.getNewCritical() > 0 ? " (" + sastResults.getNewCritical() + " new)" : ""; String infoNew = sastResults.getNewInfo() > 0 ? " (" + sastResults.getNewInfo() + " new)" : ""; log.info("----------------------------Checkmarx Scan Results(CxSAST):-------------------------------"); log.info("High severity results: " + sastResults.getHigh() + highNew); log.info("Medium severity results: " + sastResults.getMedium() + mediumNew); log.info("Low severity results: " + sastResults.getLow() + lowNew); + CxVersion cxVersion = config.getCxVersion(); + String sastVersion = cxVersion != null ? cxVersion.getVersion() : null; + if (sastVersion != null && !sastVersion.isEmpty()) { + String[] versionComponents = sastVersion.split("\\."); + if (versionComponents.length >= 2) { + String currentVersion = versionComponents[0] + "." + versionComponents[1]; + float currentVersionFloat = Float.parseFloat(currentVersion); + if (currentVersionFloat == Float.parseFloat("9.7")) { + log.info("Critical severity results: " + sastResults.getCritical() + criticalNew); + } + } + } log.info("Information severity results: " + sastResults.getInformation() + infoNew); log.info(""); if (sastResults.getSastScanLink() != null) @@ -57,10 +72,10 @@ public static void printSASTResultsToConsole(SASTResults sastResults, boolean en } //PDF Report - //This method is used for generate report for other file formats(CSV , XML, JSON etc) as well not only PDF file format. + //This method is used for generate report for other file formats(CSV , XML, JSON etc) as well not only PDF file format. public static String writePDFReport(byte[] scanReport, File workspace, String pdfFileName, Logger log, String reportFormat) { try { - FileUtils.writeByteArrayToFile(new File(workspace + CX_REPORT_LOCATION, pdfFileName), scanReport); + FileUtils.writeByteArrayToFile(new File(workspace + CX_REPORT_LOCATION, pdfFileName), scanReport); log.info("" +reportFormat + " Report Location: " + workspace + CX_REPORT_LOCATION+ File.separator+ pdfFileName); } catch (Exception e) { log.error("Failed to write "+reportFormat+" report to workspace: ", e.getMessage()); diff --git a/src/main/resources/com/cx/report/report.ftl b/src/main/resources/com/cx/report/report.ftl index 7649d422..0ed6b03e 100644 --- a/src/main/resources/com/cx/report/report.ftl +++ b/src/main/resources/com/cx/report/report.ftl @@ -741,7 +741,8 @@ .cx-report table.cve-table td.sast-cve-table-high, .cx-report table.cve-table td.sast-cve-table-medium, - .cx-report table.cve-table td.sast-cve-table-low { + .cx-report table.cve-table td.sast-cve-table-low + .cx-report table.cve-table td.sast-cve-table-critical { max-width: 19px; } @@ -1307,11 +1308,92 @@ + + + <#if config.cxVersion.version?has_content> + <#assign versionComponents = config.cxVersion.version?split(".")> + <#assign currentVersion = versionComponents[0] + "." + versionComponents[1]> + <#assign currentVersionFloat = currentVersion?number> + <#-- Debug log for currentVersionFloat --> + <#-- Current Version Float: ${currentVersionFloat} --> + <#if (currentVersionFloat?exists) && (currentVersionFloat >= 9.7)> + +
  • + +
    + <#if config.sastThresholdsEnabled && config.sastCriticalThreshold??> + <@thresholdTooltip threshold=config.sastCriticalThreshold count=sast.critical/> + +
    +
    +
    +
    + +
    +
    +
    + + + Med + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    Critical -
    +
    ${sast.critical}
    +
    + <#if sast.hasNewResults()> +
    ${sast.newCritical} + New +
    + +
    +
  • + + + <#if config.isOsaEnabled()|| config.isAstScaEnabled() >
    @@ -1884,7 +1966,7 @@
    --> <#if config.isSastEnabled() && config.generateXmlReport &&sast.sastResultsReady> - <#if sast.high gt 0 || sast.medium gt 0 || sast.low gt 0> + <#if sast.high gt 0 || sast.medium gt 0 || sast.low gt 0 || sast.critical gt 0>
    @@ -2261,6 +2343,58 @@
    + + <#if sast.critical gt 0> +
    +
    +
    + Critical + + + + + + + + + + + + + + + + + + +
    +
    Critical
    +
    ${sast.critical}
    +
    + + + + + + <#list sast.queryList as query> + <#if query.severity == sast.languageMap["CRITICAL"]> + + + + + + +
    VulnerabilityIssues Found
    ${sast.encodeXSS(query.name)}${query.result?size}
    +
    +
    @@ -2605,8 +2739,6 @@ - -