diff --git a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java
index 7588f2105..9761effd3 100644
--- a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java
+++ b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java
@@ -64,7 +64,7 @@ public class Check extends Update {
* Whether or not the NSP Analyzer is enabled.
*/
private Boolean nspAnalyzerEnabled;
-
+
/**
* Whether or not the Ruby Bundle Audit Analyzer is enabled.
*/
@@ -154,6 +154,10 @@ public class Check extends Update {
* Default is HTML.
*/
private String reportFormat = "HTML";
+ /**
+ * Suppression file path.
+ */
+ private String suppressionFile = null;
/**
* Suppression file paths.
*/
@@ -462,11 +466,10 @@ public class Check extends Update {
* Set the value of suppressionFile.
*
* @param suppressionFile new value of suppressionFile
- * @deprecated property form of suppressionFile has been replaced by a child element
*/
- @Deprecated
public void setSuppressionFile(String suppressionFile) {
- throw new BuildException("Definition of a suppression file via a property has been deprecated. Suppression files are now defined as a nested element, please update your configuration.");
+ this.suppressionFile = suppressionFile;
+ suppressionFiles.add(suppressionFile);
}
/**
@@ -758,6 +761,7 @@ public class Check extends Update {
public void setNodeAnalyzerEnabled(Boolean nodeAnalyzerEnabled) {
this.nodeAnalyzerEnabled = nodeAnalyzerEnabled;
}
+
/**
* Get the value of nspAnalyzerEnabled.
*
@@ -766,6 +770,7 @@ public class Check extends Update {
public Boolean isNspAnalyzerEnabled() {
return nspAnalyzerEnabled;
}
+
/**
* Set the value of nspAnalyzerEnabled.
*
diff --git a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/SuppressionFile.java b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/SuppressionFile.java
index 962c09cad..0cc3c3364 100644
--- a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/SuppressionFile.java
+++ b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/SuppressionFile.java
@@ -18,8 +18,10 @@
package org.owasp.dependencycheck.taskdefs;
/**
- * Class : {@link SuppressionFile}
- * Responsibility : Models a suppression file nested XML element where the simple content is its location.
+ * Class : {@link SuppressionFile} Responsibility : Models a suppression file
+ * nested XML element where the simple content is its location.
+ *
+ * @author Phillip Whittlesea
*/
public class SuppressionFile {
diff --git a/dependency-check-ant/src/test/java/org/owasp/dependencycheck/taskdefs/DependencyCheckTaskTest.java b/dependency-check-ant/src/test/java/org/owasp/dependencycheck/taskdefs/DependencyCheckTaskTest.java
index e1c41c9e8..1e86afed6 100644
--- a/dependency-check-ant/src/test/java/org/owasp/dependencycheck/taskdefs/DependencyCheckTaskTest.java
+++ b/dependency-check-ant/src/test/java/org/owasp/dependencycheck/taskdefs/DependencyCheckTaskTest.java
@@ -127,22 +127,41 @@ public class DependencyCheckTaskTest {
buildFileRule.executeTarget(antTaskName);
// THEN the ant task executed without error
- final File report = new File("target/dependency-check-report.html");
+ final File report = new File("target/suppression-report.html");
assertTrue("Expected the DependencyCheck report to be generated", report.exists());
}
/**
- * Test the DependencyCheckTask deprecated suppression property throws an exception with a warning.
+ * Test the DependencyCheckTask deprecated suppression property throws an
+ * exception with a warning.
*/
@Test
- public void testDeprecatedSuppressingCVE() {
+ public void testSuppressingSingle() {
// GIVEN an ant task with a vulnerability using the legacy property
- final String antTaskName = "deprecated-suppression";
-
+ final String antTaskName = "suppression-single";
+
// WHEN executing the ant task
- // THEN an exception with a warning is thrown
- expectedException.expect(BuildException.class);
- expectedException.expectMessage("Definition of a suppression file via a property has been deprecated. Suppression files are now defined as a nested element, please update your configuration.");
buildFileRule.executeTarget(antTaskName);
+
+ // THEN the ant task executed without error
+ final File report = new File("target/suppression-single-report.html");
+ assertTrue("Expected the DependencyCheck report to be generated", report.exists());
+ }
+
+ /**
+ * Test the DependencyCheckTask deprecated suppression property throws an
+ * exception with a warning.
+ */
+ @Test
+ public void testSuppressingMultiple() {
+ // GIVEN an ant task with a vulnerability using multiple was to configure the suppression file
+ final String antTaskName = "suppression-multiple";
+
+ // WHEN executing the ant task
+ buildFileRule.executeTarget(antTaskName);
+
+ // THEN the ant task executed without error
+ final File report = new File("target/suppression-multiple-report.html");
+ assertTrue("Expected the DependencyCheck report to be generated", report.exists());
}
}
diff --git a/dependency-check-ant/src/test/resources/build.xml b/dependency-check-ant/src/test/resources/build.xml
index 21f7a84a0..68a71e62d 100644
--- a/dependency-check-ant/src/test/resources/build.xml
+++ b/dependency-check-ant/src/test/resources/build.xml
@@ -72,19 +72,10 @@
-
-
-
-
${project.build.directory}/test-classes/test-suppression1.xml
@@ -97,4 +88,30 @@
files="jetty-6.1.0.jar,org.mortbay.jetty.jar"/>
+
+
+
+
+
+
+
+
+
+ ${project.build.directory}/test-classes/test-suppression2.xml
+
+
+
+
+
+
diff --git a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/CliParser.java b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/CliParser.java
index aed026bd1..8df1725dd 100644
--- a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/CliParser.java
+++ b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/CliParser.java
@@ -274,7 +274,8 @@ public final class CliParser {
.build();
final Option suppressionFile = Option.builder().argName("file").hasArgs().longOpt(ARGUMENT.SUPPRESSION_FILES)
- .desc("The file path to the suppression XML file.")
+ .desc("The file path to the suppression XML file. This can be specified more then once to utilize multiple "
+ + "suppression files")
.build();
final Option hintsFile = Option.builder().argName("file").hasArg().longOpt(ARGUMENT.HINTS_FILE)
@@ -735,7 +736,8 @@ public final class CliParser {
public boolean isNodeJsDisabled() {
return hasDisableOption(ARGUMENT.DISABLE_NODE_JS, Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED);
}
-/**
+
+ /**
* Returns true if the disableNSP command line argument was specified.
*
* @return true if the disableNSP command line argument was specified;
diff --git a/dependency-check-cli/src/site/markdown/arguments.md b/dependency-check-cli/src/site/markdown/arguments.md
index bdf2b3826..f418e0595 100644
--- a/dependency-check-cli/src/site/markdown/arguments.md
+++ b/dependency-check-cli/src/site/markdown/arguments.md
@@ -14,7 +14,7 @@ Short | Argument Name | Parameter | Description | Requir
| \-\-failOnCvss | \ | If the score set between 0 and 10 the exit code from dependency-check will indicate if a vulnerability with a CVSS score equal to or higher was identified. | Optional
\-l | \-\-log | \ | The file path to write verbose logging information. | Optional
\-n | \-\-noupdate | | Disables the automatic updating of the CPE data. | Optional
- | \-\-suppression | \ | The file paths to the suppression XML files; used to suppress [false positives](../general/suppression.html). | Optional
+ | \-\-suppression | \ | The file paths to the suppression XML files; used to suppress [false positives](../general/suppression.html). This can be specified more then once to utilize multiple suppression files. | Optional
\-h | \-\-help | | Print the help message. | Optional
| \-\-advancedHelp | | Print the advanced help message. | Optional
\-v | \-\-version | | Print the version information. | Optional
diff --git a/dependency-check-maven/src/it/730-multiple-suppression-files-configs/invoker.properties b/dependency-check-maven/src/it/730-multiple-suppression-files-configs/invoker.properties
new file mode 100644
index 000000000..9c2542d23
--- /dev/null
+++ b/dependency-check-maven/src/it/730-multiple-suppression-files-configs/invoker.properties
@@ -0,0 +1,18 @@
+#
+# This file is part of dependency-check-core.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Copyright (c) 2017 The OWASP Foundation. All Rights Reserved.
+#
+invoker.goals = install ${project.groupId}:${project.artifactId}:${project.version}:check
diff --git a/dependency-check-maven/src/it/730-multiple-suppression-files-configs/pom.xml b/dependency-check-maven/src/it/730-multiple-suppression-files-configs/pom.xml
new file mode 100644
index 000000000..cec15d819
--- /dev/null
+++ b/dependency-check-maven/src/it/730-multiple-suppression-files-configs/pom.xml
@@ -0,0 +1,54 @@
+
+
+
+ 4.0.0
+ org.owasp.test
+ test-multiple-suppression-files
+ 1.0.0-SNAPSHOT
+ jar
+
+
+
+
+ com.vaadin.external.google
+ android-json
+ 0.0.20131108.vaadin1
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-xml
+ 2.4.5
+
+
+
+
+
+
+ org.owasp
+ dependency-check-maven
+
+ ${project.basedir}/test-suppression1.xml
+
+ ${project.basedir}/test-suppression2.xml
+
+
+
+
+
+
diff --git a/dependency-check-maven/src/it/730-multiple-suppression-files-configs/postbuild.groovy b/dependency-check-maven/src/it/730-multiple-suppression-files-configs/postbuild.groovy
new file mode 100644
index 000000000..2a42192d9
--- /dev/null
+++ b/dependency-check-maven/src/it/730-multiple-suppression-files-configs/postbuild.groovy
@@ -0,0 +1,35 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (c) 2017 The OWASP Foundation. All Rights Reserved.
+ */
+
+import org.apache.commons.io.FileUtils
+import org.apache.commons.lang.StringUtils
+
+import java.nio.charset.Charset
+
+// Check that suppression worked.
+String log = FileUtils.readFileToString(new File(basedir, "build.log"), Charset.defaultCharset().name());
+int count = StringUtils.countMatches(log, "CVE-2016-5696");
+if (count > 0) {
+ System.out.println(String.format("CVE-2016-5696 (android-json-0.0.20131108.vaadin1.jar) was identified and should be suppressed"));
+ return false;
+}
+count = StringUtils.countMatches(log, "CVE-2016-7051");
+if (count > 0) {
+ System.out.println(String.format("CVE-2016-7051 (jackson-module-jaxb-annotations-2.4.5.jar) was identified and should be suppressed"));
+ return false;
+}
diff --git a/dependency-check-maven/src/it/730-multiple-suppression-files-configs/test-suppression1.xml b/dependency-check-maven/src/it/730-multiple-suppression-files-configs/test-suppression1.xml
new file mode 100644
index 000000000..e3bd8c0b0
--- /dev/null
+++ b/dependency-check-maven/src/it/730-multiple-suppression-files-configs/test-suppression1.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+ ^com\.vaadin\.external\.google:android-json:.*$
+ cpe:/a:google:android
+
+
diff --git a/dependency-check-maven/src/it/730-multiple-suppression-files-configs/test-suppression2.xml b/dependency-check-maven/src/it/730-multiple-suppression-files-configs/test-suppression2.xml
new file mode 100644
index 000000000..f0b4fad7b
--- /dev/null
+++ b/dependency-check-maven/src/it/730-multiple-suppression-files-configs/test-suppression2.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+ ^com\.fasterxml\.jackson.*:.*:.*$
+ cpe:/a:fasterxml:jackson
+
+
diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java
index 3b08fe763..941864d3e 100644
--- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java
+++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java
@@ -21,6 +21,7 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import org.apache.maven.artifact.Artifact;
@@ -203,7 +204,11 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
*/
@Parameter(required = false)
private String[] suppressionFiles;
-
+ /**
+ * The paths to the suppression file.
+ */
+ @Parameter(required = false)
+ private String suppressionFile;
/**
* The path to the hints file.
*/
@@ -415,7 +420,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
private boolean skipSystemScope = false;
/**
- * Skip analysis for dependencies which type matches this regular expression.
+ * Skip analysis for dependencies which type matches this regular
+ * expression.
*/
@SuppressWarnings("CanBeFinal")
@Parameter(property = "skipArtifactType", required = false)
@@ -488,7 +494,6 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
*/
private Filter artifactTypeExcluded;
-
//
//
/**
@@ -660,8 +665,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
List nodes, ProjectBuildingRequest buildingRequest) {
ExceptionCollection exCol = null;
for (DependencyNode dependencyNode : nodes) {
- if (artifactScopeExcluded.passes(dependencyNode.getArtifact().getScope()) ||
- artifactTypeExcluded.passes(dependencyNode.getArtifact().getType())) {
+ if (artifactScopeExcluded.passes(dependencyNode.getArtifact().getScope())
+ || artifactTypeExcluded.passes(dependencyNode.getArtifact().getType())) {
continue;
}
exCol = collectDependencies(engine, project, dependencyNode.getChildren(), buildingRequest);
@@ -686,7 +691,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
}
if (!isResolved) {
getLog().error("Unable to resolve system scoped dependency: " + dependencyNode.toNodeString());
- exCol.addException(new DependencyNotFoundException("Unable to resolve system scoped dependency: " + dependencyNode.toNodeString()));
+ exCol.addException(new DependencyNotFoundException("Unable to resolve system scoped dependency: "
+ + dependencyNode.toNodeString()));
}
} else {
final ArtifactCoordinate coordinate = TransferUtils.toArtifactCoordinate(dependencyNode.getArtifact());
@@ -924,8 +930,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
Settings.setStringIfNotNull(Settings.KEYS.PROXY_PASSWORD, password);
Settings.setStringIfNotNull(Settings.KEYS.PROXY_NON_PROXY_HOSTS, proxy.getNonProxyHosts());
}
-
- Settings.setArrayIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFiles);
+ final String[] suppressions = determineSuppressions();
+ Settings.setArrayIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressions);
Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
Settings.setStringIfNotEmpty(Settings.KEYS.HINTS_FILE, hintsFile);
@@ -1015,6 +1021,25 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
artifactTypeExcluded = new ArtifactTypeExcluded(skipArtifactType);
}
+ /**
+ * Combines the configured suppressionFile and suppressionFiles into a
+ * single array.
+ *
+ * @return an array of suppression file paths
+ */
+ private String[] determineSuppressions() {
+ String[] suppressions = suppressionFiles;
+ if (suppressionFile != null) {
+ if (suppressions == null) {
+ suppressions = new String[]{suppressionFile};
+ } else {
+ suppressions = Arrays.copyOf(suppressions, suppressions.length + 1);
+ suppressions[suppressions.length - 1] = suppressionFile;
+ }
+ }
+ return suppressions;
+ }
+
/**
* Returns the maven proxy.
*
diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java
index b4a898192..50df24f14 100644
--- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java
+++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java
@@ -151,10 +151,10 @@ public final class FileUtils {
}
/**
- * Gets the {@link InputStream} for this resource
+ * Gets the {@link InputStream} for this resource.
*
* @param resource path
- * @return
+ * @return the input stream for the given resource
*/
public static InputStream getResourceAsStream(String resource) {
return FileUtils.class.getClassLoader() != null
diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java
index f84ff734f..cb4eece09 100644
--- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java
+++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java
@@ -763,7 +763,7 @@ public final class Settings {
private static File getJarPath() {
String decodedPath = ".";
String jarPath = "";
- ProtectionDomain domain = Settings.class.getProtectionDomain();
+ final ProtectionDomain domain = Settings.class.getProtectionDomain();
if (domain != null && domain.getCodeSource() != null && domain.getCodeSource().getLocation() != null) {
jarPath = Settings.class.getProtectionDomain().getCodeSource().getLocation().getPath();
}