From dee1ccfd3e5fab518a718b71c7f4f7d269ff2c5d Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Thu, 22 Jun 2017 07:18:14 -0400 Subject: [PATCH] updates to allow old suppression file configuration --- .../owasp/dependencycheck/taskdefs/Check.java | 13 +++-- .../taskdefs/SuppressionFile.java | 6 ++- .../taskdefs/DependencyCheckTaskTest.java | 35 +++++++++--- .../src/test/resources/build.xml | 37 +++++++++---- .../org/owasp/dependencycheck/CliParser.java | 6 ++- .../src/site/markdown/arguments.md | 2 +- .../invoker.properties | 18 +++++++ .../pom.xml | 54 +++++++++++++++++++ .../postbuild.groovy | 35 ++++++++++++ .../test-suppression1.xml | 27 ++++++++++ .../test-suppression2.xml | 27 ++++++++++ .../maven/BaseDependencyCheckMojo.java | 41 +++++++++++--- .../dependencycheck/utils/FileUtils.java | 4 +- .../owasp/dependencycheck/utils/Settings.java | 2 +- 14 files changed, 269 insertions(+), 38 deletions(-) create mode 100644 dependency-check-maven/src/it/730-multiple-suppression-files-configs/invoker.properties create mode 100644 dependency-check-maven/src/it/730-multiple-suppression-files-configs/pom.xml create mode 100644 dependency-check-maven/src/it/730-multiple-suppression-files-configs/postbuild.groovy create mode 100644 dependency-check-maven/src/it/730-multiple-suppression-files-configs/test-suppression1.xml create mode 100644 dependency-check-maven/src/it/730-multiple-suppression-files-configs/test-suppression2.xml 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(); }