mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-02-25 11:55:21 +01:00
Merge pull request #619 from willowtreeapps/feature/fail-on-cvss
Adds a failOnCVSS command line option
This commit is contained in:
@@ -33,6 +33,7 @@ import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
|||||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
|
||||||
import org.owasp.dependencycheck.dependency.Dependency;
|
import org.owasp.dependencycheck.dependency.Dependency;
|
||||||
import org.apache.tools.ant.DirectoryScanner;
|
import org.apache.tools.ant.DirectoryScanner;
|
||||||
|
import org.owasp.dependencycheck.dependency.Vulnerability;
|
||||||
import org.owasp.dependencycheck.reporting.ReportGenerator;
|
import org.owasp.dependencycheck.reporting.ReportGenerator;
|
||||||
import org.owasp.dependencycheck.utils.Settings;
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -161,8 +162,8 @@ public class App {
|
|||||||
try {
|
try {
|
||||||
final String[] scanFiles = cli.getScanFiles();
|
final String[] scanFiles = cli.getScanFiles();
|
||||||
if (scanFiles != null) {
|
if (scanFiles != null) {
|
||||||
runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getProjectName(), scanFiles,
|
exitCode = runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getProjectName(), scanFiles,
|
||||||
cli.getExcludeList(), cli.getSymLinkDepth());
|
cli.getExcludeList(), cli.getSymLinkDepth(), cli.getFailOnCVSS());
|
||||||
} else {
|
} else {
|
||||||
LOGGER.error("No scan files configured");
|
LOGGER.error("No scan files configured");
|
||||||
}
|
}
|
||||||
@@ -203,6 +204,7 @@ public class App {
|
|||||||
* @param files the files/directories to scan
|
* @param files the files/directories to scan
|
||||||
* @param excludes the patterns for files/directories to exclude
|
* @param excludes the patterns for files/directories to exclude
|
||||||
* @param symLinkDepth the depth that symbolic links will be followed
|
* @param symLinkDepth the depth that symbolic links will be followed
|
||||||
|
* @param cvssFailScore the score to fail on if a vulnerability is found
|
||||||
*
|
*
|
||||||
* @throws InvalidScanPathException thrown if the path to scan starts with
|
* @throws InvalidScanPathException thrown if the path to scan starts with
|
||||||
* "//"
|
* "//"
|
||||||
@@ -213,9 +215,10 @@ public class App {
|
|||||||
* analysis; there may be multiple exceptions contained within the
|
* analysis; there may be multiple exceptions contained within the
|
||||||
* collection.
|
* collection.
|
||||||
*/
|
*/
|
||||||
private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files,
|
private int runScan(String reportDirectory, String outputFormat, String applicationName, String[] files,
|
||||||
String[] excludes, int symLinkDepth) throws InvalidScanPathException, DatabaseException, ExceptionCollection, ReportException {
|
String[] excludes, int symLinkDepth, int cvssFailScore) throws InvalidScanPathException, DatabaseException, ExceptionCollection, ReportException {
|
||||||
Engine engine = null;
|
Engine engine = null;
|
||||||
|
int retCode = 0;
|
||||||
try {
|
try {
|
||||||
engine = new Engine();
|
engine = new Engine();
|
||||||
final List<String> antStylePaths = new ArrayList<String>();
|
final List<String> antStylePaths = new ArrayList<String>();
|
||||||
@@ -302,12 +305,24 @@ public class App {
|
|||||||
if (exCol != null && exCol.getExceptions().size() > 0) {
|
if (exCol != null && exCol.getExceptions().size() > 0) {
|
||||||
throw exCol;
|
throw exCol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Set the exit code based on whether we found a high enough vulnerability
|
||||||
|
for (Dependency dep : dependencies) {
|
||||||
|
if (dep.getVulnerabilities().size() != 0) {
|
||||||
|
for (Vulnerability vuln : dep.getVulnerabilities()) {
|
||||||
|
LOGGER.debug("VULNERABILITY FOUND " + dep.getDisplayFileName());
|
||||||
|
if (vuln.getCvssScore() > cvssFailScore)
|
||||||
|
retCode = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retCode;
|
||||||
} finally {
|
} finally {
|
||||||
if (engine != null) {
|
if (engine != null) {
|
||||||
engine.cleanup();
|
engine.cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -289,6 +289,10 @@ public final class CliParser {
|
|||||||
.desc("Enables the experimental analzers.")
|
.desc("Enables the experimental analzers.")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
final Option failOnCVSS = Option.builder().hasArg().longOpt(ARGUMENT.FAIL_ON_CVSS)
|
||||||
|
.desc("Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11; since the CVSS scores are 0-10, by default the build will never fail.")
|
||||||
|
.build();
|
||||||
|
|
||||||
//This is an option group because it can be specified more then once.
|
//This is an option group because it can be specified more then once.
|
||||||
final OptionGroup og = new OptionGroup();
|
final OptionGroup og = new OptionGroup();
|
||||||
og.addOption(path);
|
og.addOption(path);
|
||||||
@@ -311,7 +315,8 @@ public final class CliParser {
|
|||||||
.addOption(suppressionFile)
|
.addOption(suppressionFile)
|
||||||
.addOption(hintsFile)
|
.addOption(hintsFile)
|
||||||
.addOption(cveValidForHours)
|
.addOption(cveValidForHours)
|
||||||
.addOption(experimentalEnabled);
|
.addOption(experimentalEnabled)
|
||||||
|
.addOption(failOnCVSS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1105,6 +1110,24 @@ public final class CliParser {
|
|||||||
return line.hasOption(ARGUMENT.EXPERIMENTAL);
|
return line.hasOption(ARGUMENT.EXPERIMENTAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the CVSS value to fail on
|
||||||
|
*
|
||||||
|
* @return 11 if nothing is set. Otherwise it returns the int passed from the command line arg
|
||||||
|
*/
|
||||||
|
public int getFailOnCVSS() {
|
||||||
|
if(line.hasOption(ARGUMENT.FAIL_ON_CVSS)) {
|
||||||
|
String value = line.getOptionValue(ARGUMENT.FAIL_ON_CVSS);
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(value);
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
return 11;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 11;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A collection of static final strings that represent the possible command
|
* A collection of static final strings that represent the possible command
|
||||||
* line arguments.
|
* line arguments.
|
||||||
@@ -1408,5 +1431,9 @@ public final class CliParser {
|
|||||||
* The CLI argument to enable the experimental analyzers.
|
* The CLI argument to enable the experimental analyzers.
|
||||||
*/
|
*/
|
||||||
private static final String EXPERIMENTAL = "enableExperimental";
|
private static final String EXPERIMENTAL = "enableExperimental";
|
||||||
|
/**
|
||||||
|
* The CLI argument to enable the experimental analyzers.
|
||||||
|
*/
|
||||||
|
private static final String FAIL_ON_CVSS = "failOnCVSS";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,6 +115,63 @@ public class CliParserTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of parse method with failOnCVSS without an argument
|
||||||
|
*
|
||||||
|
* @throws Exception thrown when an exception occurs.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testParse_failOnCVSSNoArg() throws Exception {
|
||||||
|
|
||||||
|
String[] args = {"--failOnCVSS"};
|
||||||
|
|
||||||
|
CliParser instance = new CliParser();
|
||||||
|
try {
|
||||||
|
instance.parse(args);
|
||||||
|
} catch (ParseException ex) {
|
||||||
|
Assert.assertTrue(ex.getMessage().contains("Missing argument"));
|
||||||
|
}
|
||||||
|
Assert.assertFalse(instance.isGetVersion());
|
||||||
|
Assert.assertFalse(instance.isGetHelp());
|
||||||
|
Assert.assertFalse(instance.isRunScan());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of parse method with failOnCVSS invalid argument. It should default to 11
|
||||||
|
*
|
||||||
|
* @throws Exception thrown when an exception occurs.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testParse_failOnCVSSInvalidArgument() throws Exception {
|
||||||
|
|
||||||
|
String[] args = {"--failOnCVSS","bad"};
|
||||||
|
|
||||||
|
CliParser instance = new CliParser();
|
||||||
|
instance.parse(args);
|
||||||
|
Assert.assertEquals("Default should be 11", 11, instance.getFailOnCVSS());
|
||||||
|
Assert.assertFalse(instance.isGetVersion());
|
||||||
|
Assert.assertFalse(instance.isGetHelp());
|
||||||
|
Assert.assertFalse(instance.isRunScan());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of parse method with failOnCVSS invalid argument. It should default to 11
|
||||||
|
*
|
||||||
|
* @throws Exception thrown when an exception occurs.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testParse_failOnCVSSValidArgument() throws Exception {
|
||||||
|
|
||||||
|
String[] args = {"--failOnCVSS","6"};
|
||||||
|
|
||||||
|
CliParser instance = new CliParser();
|
||||||
|
instance.parse(args);
|
||||||
|
Assert.assertEquals(6, instance.getFailOnCVSS());
|
||||||
|
Assert.assertFalse(instance.isGetVersion());
|
||||||
|
Assert.assertFalse(instance.isGetHelp());
|
||||||
|
Assert.assertFalse(instance.isRunScan());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test of parse method with jar and cpe args, of class CliParser.
|
* Test of parse method with jar and cpe args, of class CliParser.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user