blackListToPresent = processResult.getScanResult().getExistedBlackListVulSet();
boolean numberExceed = false;
+ boolean criticalExceed = false;
+ boolean highExceed = false;
+ boolean medExceed = false;
StringBuilder statementBuilder = new StringBuilder();
- if (scanConfig.getHighVul() != null && !scanConfig.getHighVul().trim().isEmpty()) {
- int configNumberOfHigh = Integer.parseInt(scanConfig.getHighVul().trim());
- if (configNumberOfHigh != 0 && configNumberOfHigh <= totalHighSeverity) {
- numberExceed = true;
- statementBuilder.append(totalHighSeverity).append(" High severity vulnerabilities");
+ if (scanConfig.getNumberOfCriticalSeverityToFail() != null) {
+ if (scanConfig.getNumberOfCriticalSeverityToFail() != 0 && scanConfig.getNumberOfCriticalSeverityToFail() <= currentCriticalSeverity) {
+ criticalExceed = true;
+ statementBuilder.append(currentCriticalSeverity).append(" Critical severity vulnerabilities");
+ }
+ }
+
+ if (scanConfig.getNumberOfHighSeverityToFail() != null) {
+ if (scanConfig.getNumberOfHighSeverityToFail() != 0 && scanConfig.getNumberOfHighSeverityToFail() <= currentCriticalSeverity) {
+ if (criticalExceed) {
+ statementBuilder.append(", ");
+ }
+ highExceed = true;
+ statementBuilder.append(currentHighSeverity).append(" High severity vulnerabilities");
}
}
- if (scanConfig.getMediumVul() != null && !scanConfig.getMediumVul().trim().isEmpty()) {
- int configNumberOfMedium = Integer.parseInt(scanConfig.getMediumVul().trim());
- if (configNumberOfMedium != 0 && configNumberOfMedium <= totalMediumSeverity) {
- if (numberExceed) {
+ if (scanConfig.getNumberOfMediumSeverityToFail() != null) {
+ if (scanConfig.getNumberOfMediumSeverityToFail() != 0 && scanConfig.getNumberOfMediumSeverityToFail() <= currentCriticalSeverity) {
+ if (criticalExceed || highExceed) {
statementBuilder.append(", ");
}
+ medExceed = true;
+ statementBuilder.append(currentMediumSeverity).append(" Medium severity vulnerabilities");
+ }
+ }
+
+ // Handle the upgrade to include critical severity cases.
+ if ((!criticalExceed && !highExceed) && scanConfig.getIsUpgradedToIncludeCriticalSeverity()) {
+ if (aboveHighSeverityNumber != 0 && aboveHighSeverityNumber <= (currentCriticalSeverity + currentHighSeverity)) {
numberExceed = true;
- statementBuilder.append(totalMediumSeverity).append(" Medium severity vulnerabilities");
+ statementBuilder.append(currentCriticalSeverity).append(" Critical severity vulnerabilities, ");
+ statementBuilder.append(currentHighSeverity).append(" High severity vulnerabilities");
}
}
+ numberExceed = (numberExceed || criticalExceed || highExceed || medExceed);
+
if (foundNameInBlackList) {
if (numberExceed) {
statementBuilder.append(", and ");
}
- numberExceed = true;
statementBuilder.append("vulnerabilities: ").append(blackListToPresent.toString());
}
- if (numberExceed) {
+ if (numberExceed || foundNameInBlackList) {
statementBuilder.append(" are present.");
buildLogger.addErrorLogEntry("Build failed because " + statementBuilder.toString());
processResult.setSuccess(false);
@@ -275,6 +353,7 @@ public void writeTxtReport(final TaskContext taskContext, ProcessResult processR
}
writer.write("Repository: " + scanResult.getRepository() + "\n");
writer.write("Tag: " + scanResult.getTag() + "\n");
+ writer.write("Critical severity vulnerabilities: " + scanResult.getCriticalSeverityNumber() + "\n");
writer.write("High severity vulnerabilities: " + scanResult.getHighSeverityNumber() + "\n");
writer.write("Medium severity vulnerabilities: " + scanResult.getMediumSeverityNumber() + "\n");
writer.write("Total vulnerabilities: " + scanResult.getTotalVulnerabilityNumber() + "\n");
@@ -285,6 +364,9 @@ public void writeTxtReport(final TaskContext taskContext, ProcessResult processR
writer.write("Scanned. No vulnerabilities found.\n");
} else {
// Detailed vulnerabilities
+ for (Vulnerability vulnerability : scanResult.getCriticalVulnerabilitySet()) {
+ writeTxtReportVulnerabilityDetails(writer, vulnerability, "Critical");
+ }
for (Vulnerability vulnerability : scanResult.getHighVulnerabilitySet()) {
writeTxtReportVulnerabilityDetails(writer, vulnerability, "High");
}
@@ -365,6 +447,8 @@ public void writeHTMLReport(final TaskContext taskContext, ProcessResult process
.append("Registry URL | \n")
.append("Repository | \n")
.append("Tag | \n")
+ .append("Critical severity VULs | \n")
+ .append("Critical severity threshold | \n")
.append("High severity VULs | \n")
.append("High severity threshold | \n")
.append("Medium severity VULs | \n")
@@ -376,10 +460,12 @@ public void writeHTMLReport(final TaskContext taskContext, ProcessResult process
.append("").append(escapeHtml(scanResult.getRegistry())).append(" | \n")
.append("").append(escapeHtml(scanResult.getRepository())).append(" | \n")
.append("").append(escapeHtml(scanResult.getTag())).append(" | \n")
+ .append("").append(Integer.toString(scanResult.getCriticalVulnerabilitySet().size())).append(" | \n")
+ .append("").append(scanResult.getCriticalSeverityThreshold() != 0.0 ? Double.toString(scanResult.getCriticalSeverityThreshold()) : "No Limit").append(" | \n")
.append("").append(Integer.toString(scanResult.getHighVulnerabilitySet().size())).append(" | \n")
- .append("").append(scanResult.getHighSeverityThreshold() != 0 ? Integer.toString(scanResult.getHighSeverityThreshold()) : "No Limit").append(" | \n")
+ .append("").append(scanResult.getHighSeverityThreshold() != 0.0 ? Double.toString(scanResult.getHighSeverityThreshold()) : "No Limit").append(" | \n")
.append("").append(Integer.toString(scanResult.getMediumVulnerabilitySet().size())).append(" | \n")
- .append("").append(scanResult.getMediumSeverityThreshold() != 0 ? Integer.toString(scanResult.getMediumSeverityThreshold()) : "No Limit").append(" | \n")
+ .append("").append(scanResult.getMediumSeverityThreshold() != 0.0 ? Double.toString(scanResult.getMediumSeverityThreshold()) : "No Limit").append(" | \n")
.append("").append(escapeHtml(String.join(", ", scanResult.getExistedBlackListVulSet()))).append(" | \n")
.append("").append(Integer.toString(scanResult.getTotalVulnerabilityNumber())).append(" | \n")
.append("\n")
@@ -400,6 +486,11 @@ public void writeHTMLReport(final TaskContext taskContext, ProcessResult process
.append("Description | \n")
.append("Feed_rating | \n")
.append("\n");
+
+ // Critical vulnerabilities
+ for (Vulnerability vulnerability : scanResult.getCriticalVulnerabilitySet()) {
+ htmlContent.append(getVulnerabilityRowHtml(vulnerability, "Critical"));
+ }
// High vulnerabilities
for (Vulnerability vulnerability : scanResult.getHighVulnerabilitySet()) {
htmlContent.append(getVulnerabilityRowHtml(vulnerability, "High"));
diff --git a/src/main/java/neuvector/NeuVectorTaskConfigurator.java b/src/main/java/neuvector/NeuVectorTaskConfigurator.java
index cd3894c..fbc7873 100644
--- a/src/main/java/neuvector/NeuVectorTaskConfigurator.java
+++ b/src/main/java/neuvector/NeuVectorTaskConfigurator.java
@@ -37,6 +37,7 @@ public Map generateTaskConfigMap(@NotNull final ActionParameters
config.put("repository", params.getString("repository"));
config.put("tag", params.getString("tag"));
config.put("scanLayers", params.getString("scanLayers"));
+ config.put("criticalVul", params.getString("criticalVul"));
config.put("highVul", params.getString("highVul"));
config.put("mediumVul", params.getString("mediumVul"));
if (registryType != null && registryType.equals("custom")) {
@@ -85,6 +86,7 @@ public void populateContextForEdit(@NotNull final Map context, @
context.put("repository", taskDefinition.getConfiguration().get("repository"));
context.put("tag", taskDefinition.getConfiguration().get("tag"));
context.put("scanLayers", taskDefinition.getConfiguration().get("scanLayers"));
+ context.put("criticalVul", taskDefinition.getConfiguration().get("criticalVul"));
context.put("highVul", taskDefinition.getConfiguration().get("highVul"));
context.put("mediumVul", taskDefinition.getConfiguration().get("mediumVul"));
if (registryType != null && registryType.equals("custom")) {
diff --git a/src/main/java/neuvector/ScanConfig.java b/src/main/java/neuvector/ScanConfig.java
index 5c10f81..8649685 100644
--- a/src/main/java/neuvector/ScanConfig.java
+++ b/src/main/java/neuvector/ScanConfig.java
@@ -16,10 +16,14 @@ public class ScanConfig {
private String registryType;
private String repository;
private String tag;
+
private boolean scanLayers;
private boolean enableStandalone;
- private String highVul;
- private String mediumVul;
+ private boolean isUpgradedToIncludeCriticalSeverity;
+
+ // private String criticalVul;
+ // private String highVul;
+ // private String mediumVul;
private String controllerIP;
private String controllerPortString;
private int controllerPort;
@@ -33,6 +37,14 @@ public class ScanConfig {
private String scannerRegistryUsername;
private String scannerRegistryPassword;
+ private Integer numberOfCriticalSeverityToFail = 0;
+ private Integer numberOfHighSeverityToFail = 0;
+ private Integer numberOfMediumSeverityToFail = 0;
+
+ private String criticalVulFailureLimit;
+ private String highVulFailureLimit;
+ private String mediumVulFailureLimit;
+
private Set vulBlackListSet;
private Set vulWhiteListSet;
@@ -40,10 +52,13 @@ public ScanConfig(final TaskContext taskContext, ProcessResult processResult) {
enableStandalone = Boolean.valueOf((String)taskContext.getConfigurationMap().get("enableStandalone"));
repository = (String)taskContext.getConfigurationMap().get("repository");
scanLayers = Boolean.valueOf((String)taskContext.getConfigurationMap().get("scanLayers"));
- highVul = (String)taskContext.getConfigurationMap().get("highVul");
- mediumVul = (String)taskContext.getConfigurationMap().get("mediumVul");
+
+ taskContext.getBuildLogger().addBuildLogEntry("taskContext.getConfigurationMap(): " + taskContext.getConfigurationMap());
+
+ criticalVulFailureLimit = (String)taskContext.getConfigurationMap().get("criticalVul");
+ highVulFailureLimit = (String)taskContext.getConfigurationMap().get("highVul");
+ mediumVulFailureLimit = (String)taskContext.getConfigurationMap().get("mediumVul");
tag = (String)taskContext.getConfigurationMap().get("tag");
-
registryType = (String)taskContext.getConfigurationMap().get("registryType");
if (registryType != null && registryType.equals("custom")) {
registryURL = (String)taskContext.getConfigurationMap().get("customRegistryURL");
@@ -60,22 +75,60 @@ public ScanConfig(final TaskContext taskContext, ProcessResult processResult) {
scanResult.setRepository(repository);
scanResult.setTag(tag);
- int highSeverityThreshold = 0;
- if(!highVul.isEmpty()){
- try {
- highSeverityThreshold = Integer.parseInt(highVul);
- } finally {
- scanResult.setHighSeverityThreshold(highSeverityThreshold);
- }
- }
-
- int mediumSeverityThreshold = 0;
- if(!mediumVul.isEmpty()){
- try {
- mediumSeverityThreshold = Integer.parseInt(mediumVul);
- } finally {
- scanResult.setMediumSeverityThreshold(mediumSeverityThreshold);
- }
+ // Parsing and setting the medium severity threshold
+ numberOfMediumSeverityToFail = parseAndSetSeverityThresholdToFail(mediumVulFailureLimit, taskContext, 0);
+
+ // Parsing and setting the high severity threshold
+ numberOfHighSeverityToFail = parseAndSetSeverityThresholdToFail(highVulFailureLimit, taskContext, 0);
+
+ // int mediumVulFailureLimit = 0;
+ // // Check if mediumVul is not null
+ // if (mediumVulFailureLimit != null) {
+ // // Further check if mediumVul is not empty
+ // if (!mediumVulFailureLimit.isEmpty()) {
+ // try {
+ // mediumVulFailureLimit = Integer.parseInt(mediumVulFailureLimit);
+ // } catch (NumberFormatException e) {
+ // taskContext.getBuildLogger().addBuildLogEntry("Invalid number format: " + mediumVul);
+ // // Handle the error, maybe set a default value or log the error
+ // } finally {
+ // numberOfMediumSeverityToFail = mediumVulFailureLimit;
+ // }
+ // } else {
+ // taskContext.getBuildLogger().addBuildLogEntry("mediumVul is empty");
+ // // Handle the case where mediumVul is empty, maybe set a default value or log this condition
+ // }
+ // } else {
+ // taskContext.getBuildLogger().addBuildLogEntry("mediumVul is null");
+ // // Handle the case where mediumVul is null, maybe set a default value or log this condition
+ // }
+
+ // int highSeverityThreshold = 0;
+ // if(!highVul.isEmpty()){
+ // try {
+ // highSeverityThreshold = Integer.parseInt(highVul);
+ // } finally {
+ // numberOfHighSeverityToFail = highSeverityThreshold;
+ // }
+ // }
+
+ // int criticalSeverityThreshold = 0;
+ if(criticalVulFailureLimit == null) {
+ /*
+ * Support Critical, Medium, and High severity thresholds in new version, add this condition for backward compatibility.
+ * If critical is not set, we assume that this is a migrate from the version prior to the support of Critical, Medium, and High.
+ */
+ isUpgradedToIncludeCriticalSeverity = true;
+ scanResult.setAboveHighSeverityNumber(numberOfHighSeverityToFail);
+ } else {
+ // if(!criticalVul.isEmpty()){
+ // try {
+ // criticalSeverityThreshold = Integer.parseInt(criticalVul);
+ // } finally {
+ // numberOfCriticalSeverityToFail = criticalSeverityThreshold;
+ // }
+ // }
+ numberOfCriticalSeverityToFail = parseAndSetSeverityThresholdToFail(criticalVulFailureLimit, taskContext, 0);
}
String storedVulnsToFail = (String)taskContext.getConfigurationMap().get("vulnerabilitiesToFail").toLowerCase();
@@ -106,6 +159,26 @@ public ScanConfig(final TaskContext taskContext, ProcessResult processResult) {
scannerRegistryPassword = AdminConfigUtil.getAdminConfig("scannerRegistryPassword");
}
+ /**
+ * Attempts to parse a string as an integer to set a severity threshold.
+ * If parsing fails, it logs an error and sets a default value.
+ *
+ * @param vulValue the string input representing the severity threshold.
+ * @param taskContext the task context for logging.
+ * @param defaultValue the default value to use if parsing fails or the input is empty.
+ * @return the parsed or default severity threshold.
+ */
+ public static Integer parseAndSetSeverityThresholdToFail(String vulValue, TaskContext taskContext, Integer defaultValue) {
+ if (vulValue != null && !vulValue.isEmpty()) {
+ try {
+ return Integer.parseInt(vulValue);
+ } catch (NumberFormatException e) {
+ taskContext.getBuildLogger().addBuildLogEntry("Invalid number format: " + vulValue);
+ }
+ }
+ return defaultValue; // Return default value in case of empty input or parse failure
+ }
+
public String getToken() {
return token;
}
@@ -154,21 +227,22 @@ public void setEnableStandalone(boolean enableStandalone) {
this.enableStandalone = enableStandalone;
}
- public String getHighVul() {
- return highVul;
- }
+ // how much to fail
+ // public String getHighVul() {
+ // return highVul;
+ // }
- public void setHighVul(String highVul) {
- this.highVul = highVul;
- }
+ // public void setHighVul(String highVul) {
+ // this.highVul = highVul;
+ // }
- public String getMediumVul() {
- return mediumVul;
- }
+ // public String getMediumVul() {
+ // return mediumVul;
+ // }
- public void setMediumVul(String mediumVul) {
- this.mediumVul = mediumVul;
- }
+ // public void setMediumVul(String mediumVul) {
+ // this.mediumVul = mediumVul;
+ // }
public String getControllerIP() {
return controllerIP;
@@ -281,4 +355,36 @@ public Set getVulWhiteListSet() {
public void setVulWhiteListSet(Set vulWhiteListSet) {
this.vulWhiteListSet = vulWhiteListSet;
}
+
+ public boolean getIsUpgradedToIncludeCriticalSeverity() {
+ return isUpgradedToIncludeCriticalSeverity;
+ }
+
+ public void setIsUpgradedToIncludeCriticalSeverity(boolean value) {
+ isUpgradedToIncludeCriticalSeverity = value;
+ }
+
+ public Integer getNumberOfCriticalSeverityToFail() {
+ return numberOfCriticalSeverityToFail;
+ }
+
+ public void setNumberOfCriticalSeverityToFail(Integer numberOfCriticalSeverityToFail) {
+ this.numberOfCriticalSeverityToFail = numberOfCriticalSeverityToFail;
+ }
+
+ public Integer getNumberOfHighSeverityToFail() {
+ return numberOfHighSeverityToFail;
+ }
+
+ public void setNumberOfHighSeverityToFail(Integer numberOfHighSeverityToFail) {
+ this.numberOfHighSeverityToFail = numberOfHighSeverityToFail;
+ }
+
+ public Integer getNumberOfMediumSeverityToFail() {
+ return numberOfMediumSeverityToFail;
+ }
+
+ public void setNumberOfMediumSeverityToFail(Integer numberOfMediumSeverityToFail) {
+ this.numberOfMediumSeverityToFail = numberOfMediumSeverityToFail;
+ }
}
diff --git a/src/main/java/neuvector/SeverityRating.java b/src/main/java/neuvector/SeverityRating.java
new file mode 100644
index 0000000..80cdceb
--- /dev/null
+++ b/src/main/java/neuvector/SeverityRating.java
@@ -0,0 +1,9 @@
+package neuvector;
+
+public enum SeverityRating {
+ None,
+ Low,
+ Medium,
+ High,
+ Critical
+}
diff --git a/src/main/java/neuvector/report/ScanResult.java b/src/main/java/neuvector/report/ScanResult.java
index 9665ab4..7300c33 100644
--- a/src/main/java/neuvector/report/ScanResult.java
+++ b/src/main/java/neuvector/report/ScanResult.java
@@ -1,6 +1,5 @@
package neuvector.report;
-
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Set;
@@ -19,13 +18,18 @@ public class ScanResult {
Set existedBlackListVulSet = new HashSet<>();
Set existedWhiteListVulSet = new HashSet<>();
boolean isSeverityScaleCustomized;
+ double customizedCriticalSeverityScale;
double customizedHighSeverityScale;
double customizedMediumSeverityScale;
- int highSeverityThreshold;
- int mediumSeverityThreshold;
+ Double criticalSeverityThreshold = 0.0;
+ Double highSeverityThreshold = 0.0;
+ Double mediumSeverityThreshold = 0.0;
+ int aboveHighSeverityNumber;
+ int criticalSeverityNumber; // total found high severity vuls number
int highSeverityNumber; // total found high severity vuls number
int mediumSeverityNumber; // total found medium severity vuls number
int totalVulnerabilityNumber; // total vuls number
+ Set criticalVulnerabilitySet = new HashSet<>();
Set highVulnerabilitySet = new HashSet<>();
Set mediumVulnerabilitySet = new HashSet<>();
boolean scanLayerConfigured;
@@ -50,6 +54,22 @@ public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
+ public int getAboveHighSeverityNumber() {
+ return aboveHighSeverityNumber;
+ }
+
+ public void setAboveHighSeverityNumber(int aboveHighSeverityNumber) {
+ this.aboveHighSeverityNumber = aboveHighSeverityNumber;
+ }
+
+ public int getCriticalSeverityNumber() {
+ return criticalSeverityNumber;
+ }
+
+ public void setCriticalSeverityNumber(int criticalSeverityNumber) {
+ this.criticalSeverityNumber = criticalSeverityNumber;
+ }
+
public int getHighSeverityNumber() {
return highSeverityNumber;
}
@@ -154,6 +174,14 @@ public void setSeverityScaleCustomized(boolean severityScaleCustomized) {
isSeverityScaleCustomized = severityScaleCustomized;
}
+ public double getCustomizedCriticalSeverityScale() {
+ return customizedCriticalSeverityScale;
+ }
+
+ public void setCustomizedCriticalSeverityScale(double customizedCriticalSeverityScale) {
+ this.customizedCriticalSeverityScale = customizedCriticalSeverityScale;
+ }
+
public double getCustomizedHighSeverityScale() {
return customizedHighSeverityScale;
}
@@ -170,19 +198,27 @@ public void setCustomizedMediumSeverityScale(double customizedMediumSeverityScal
this.customizedMediumSeverityScale = customizedMediumSeverityScale;
}
- public int getHighSeverityThreshold() {
+ public Double getCriticalSeverityThreshold() {
+ return criticalSeverityThreshold;
+ }
+
+ public void setCriticalSeverityThreshold(Double criticalSeverityThreshold) {
+ this.criticalSeverityThreshold = criticalSeverityThreshold;
+ }
+
+ public Double getHighSeverityThreshold() {
return highSeverityThreshold;
}
- public void setHighSeverityThreshold(int highSeverityThreshold) {
+ public void setHighSeverityThreshold(Double highSeverityThreshold) {
this.highSeverityThreshold = highSeverityThreshold;
}
- public int getMediumSeverityThreshold() {
+ public Double getMediumSeverityThreshold() {
return mediumSeverityThreshold;
}
- public void setMediumSeverityThreshold(int mediumSeverityThreshold) {
+ public void setMediumSeverityThreshold(Double mediumSeverityThreshold) {
this.mediumSeverityThreshold = mediumSeverityThreshold;
}
@@ -194,6 +230,15 @@ public void setTotalVulnerabilityNumber(int totalVulnerabilityNumber) {
this.totalVulnerabilityNumber = totalVulnerabilityNumber;
}
+ public Set getCriticalVulnerabilitySet() {
+ return criticalVulnerabilitySet;
+ }
+
+ public void setCriticalVulnerabilitySet(Set criticalVulnerabilitySet) {
+ this.criticalVulnerabilitySet = criticalVulnerabilitySet;
+
+ }
+
public Set getHighVulnerabilitySet() {
return highVulnerabilitySet;
}
diff --git a/src/main/resources/templates/neuvectorGlobalConfiguration.ftl b/src/main/resources/templates/neuvectorGlobalConfiguration.ftl
index e27685d..ab250f0 100644
--- a/src/main/resources/templates/neuvectorGlobalConfiguration.ftl
+++ b/src/main/resources/templates/neuvectorGlobalConfiguration.ftl
@@ -24,6 +24,12 @@
[@ww.textfield labelKey="NeuVector Scanner Registry User" name="scannerRegistryUsername" description="Enter the NeuVector Scanner Registry username, if applicable." required="false"/]
[@ww.password labelKey="NeuVector Scanner Registry Password" name="scannerRegistryPassword" description="Enter the NeuVector Scanner Registry password, if applicable." showPassword="true" required="false"/]
[/@ui.bambooSection]
+
+ [@ui.bambooSection titleKey="NeuVector Custom Criteria Configuration"]
+ [@ww.textfield labelKey="Custom Critical Severity Threshold" name="customCriticalThreshold" description="From the Critical Severity Threshold to 10.0 is the Critical Severity Range. Vulnerabilities that score in the Critical Severity Range has the Critical severity level.." required="false"/]
+ [@ww.textfield labelKey="Custom High Severity Threshold" name="customHighThreshold" description="From the High Severity Threshold to Critical Severity Threshold is the High Severity Range. Vulnerabilities that score in the High Severity Range has the High severity level." required="false"/]
+ [@ww.textfield labelKey="Custom Medium Severity Threshold" name="customMediumThreshold" description="From the Medium Severity Threshold to the High Severity Threshold is the Medium Severity Range. Vulnerabilities that score in the Medium Severity Range has the Medium severity level." required="false"/]
+ [/@ui.bambooSection]
[/@ww.form]