From 584fd2a47bb5059afd1a1069967ef99a00709fae Mon Sep 17 00:00:00 2001 From: Phillip Whittlesea Date: Sun, 11 Jun 2017 23:26:57 +0100 Subject: [PATCH] Issue #730: Allow multiple suppression files in Maven The core has been extended to handle multiple suppression files Extended the Ant test to cover multiple suppression files NOTE: This change is breaking for users of the Maven plugin --- .../src/test/resources/build.xml | 3 + .../src/test/resources/test-suppression1.xml | 22 +++- .../src/test/resources/test-suppression2.xml | 41 +++++++ .../analyzer/AbstractSuppressionAnalyzer.java | 101 +++++++++--------- .../src/it/629-jackson-dataformat/pom.xml | 18 ++-- .../invoker.properties | 18 ++++ .../it/730-multiple-suppression-files/pom.xml | 54 ++++++++++ .../postbuild.groovy | 35 ++++++ .../test-suppression1.xml | 27 +++++ .../test-suppression2.xml | 27 +++++ .../maven/BaseDependencyCheckMojo.java | 9 +- 11 files changed, 289 insertions(+), 66 deletions(-) create mode 100644 dependency-check-ant/src/test/resources/test-suppression2.xml create mode 100644 dependency-check-maven/src/it/730-multiple-suppression-files/invoker.properties create mode 100644 dependency-check-maven/src/it/730-multiple-suppression-files/pom.xml create mode 100644 dependency-check-maven/src/it/730-multiple-suppression-files/postbuild.groovy create mode 100644 dependency-check-maven/src/it/730-multiple-suppression-files/test-suppression1.xml create mode 100644 dependency-check-maven/src/it/730-multiple-suppression-files/test-suppression2.xml diff --git a/dependency-check-ant/src/test/resources/build.xml b/dependency-check-ant/src/test/resources/build.xml index d7a2bf845..b48f96154 100644 --- a/dependency-check-ant/src/test/resources/build.xml +++ b/dependency-check-ant/src/test/resources/build.xml @@ -92,6 +92,9 @@ + diff --git a/dependency-check-ant/src/test/resources/test-suppression1.xml b/dependency-check-ant/src/test/resources/test-suppression1.xml index abbc2017d..ff324590e 100644 --- a/dependency-check-ant/src/test/resources/test-suppression1.xml +++ b/dependency-check-ant/src/test/resources/test-suppression1.xml @@ -1,10 +1,26 @@ - + + file name: axis-1.4.jar + ]]> ^org\.apache\.axis:axis:.*$ cpe:/a:apache:axis diff --git a/dependency-check-ant/src/test/resources/test-suppression2.xml b/dependency-check-ant/src/test/resources/test-suppression2.xml new file mode 100644 index 000000000..4fd833855 --- /dev/null +++ b/dependency-check-ant/src/test/resources/test-suppression2.xml @@ -0,0 +1,41 @@ + + + + + + ^jetty:org\.mortbay\.jetty:.*$ + cpe:/a:jetty:jetty + + + + ^jetty:org\.mortbay\.jetty:.*$ + cpe:/a:mortbay:jetty + + + + ^jetty:org\.mortbay\.jetty:.*$ + cpe:/a:mortbay_jetty:jetty + + diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java index 2a24a7892..f2f35a837 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java @@ -117,66 +117,67 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer { return; } - // TODO support more than one file - final String suppressionFilePath = suppressionFilePaths[0]; + for (final String suppressionFilePath : suppressionFilePaths) { + LOGGER.debug("Loading suppression rules from '{}'", suppressionFilePath); - boolean deleteTempFile = false; - try { - final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE); - if (uriRx.matcher(suppressionFilePath).matches()) { - deleteTempFile = true; - file = FileUtils.getTempFile("suppression", "xml"); - final URL url = new URL(suppressionFilePath); - try { - Downloader.fetchFile(url, file, false); - } catch (DownloadFailedException ex) { - Downloader.fetchFile(url, file, true); - } - } else { - file = new File(suppressionFilePath); + boolean deleteTempFile = false; + try { + final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE); + if (uriRx.matcher(suppressionFilePath).matches()) { + deleteTempFile = true; + file = FileUtils.getTempFile("suppression", "xml"); + final URL url = new URL(suppressionFilePath); + try { + Downloader.fetchFile(url, file, false); + } catch (DownloadFailedException ex) { + Downloader.fetchFile(url, file, true); + } + } else { + file = new File(suppressionFilePath); - if (!file.exists()) { - try (InputStream suppressionsFromClasspath = this.getClass().getClassLoader().getResourceAsStream(suppressionFilePath)) { - if (suppressionsFromClasspath != null) { - deleteTempFile = true; - file = FileUtils.getTempFile("suppression", "xml"); - try { - org.apache.commons.io.FileUtils.copyInputStreamToFile(suppressionsFromClasspath, file); - } catch (IOException ex) { - throwSuppressionParseException("Unable to locate suppressions file in classpath", ex); + if (!file.exists()) { + try (InputStream suppressionsFromClasspath = this.getClass().getClassLoader().getResourceAsStream(suppressionFilePath)) { + if (suppressionsFromClasspath != null) { + deleteTempFile = true; + file = FileUtils.getTempFile("suppression", "xml"); + try { + org.apache.commons.io.FileUtils.copyInputStreamToFile(suppressionsFromClasspath, file); + } catch (IOException ex) { + throwSuppressionParseException("Unable to locate suppressions file in classpath", ex); + } } } } } - } - if (file != null) { - if (!file.exists()) { - final String msg = String.format("Suppression file '%s' does not exists", file.getPath()); - LOGGER.warn(msg); - throw new SuppressionParseException(msg); + if (file != null) { + if (!file.exists()) { + final String msg = String.format("Suppression file '%s' does not exists", file.getPath()); + LOGGER.warn(msg); + throw new SuppressionParseException(msg); + } + try { + rules.addAll(parser.parseSuppressionRules(file)); + } catch (SuppressionParseException ex) { + LOGGER.warn("Unable to parse suppression xml file '{}'", file.getPath()); + LOGGER.warn(ex.getMessage()); + throw ex; + } } - try { - rules.addAll(parser.parseSuppressionRules(file)); - LOGGER.debug("{} suppression rules were loaded.", rules.size()); - } catch (SuppressionParseException ex) { - LOGGER.warn("Unable to parse suppression xml file '{}'", file.getPath()); - LOGGER.warn(ex.getMessage()); - throw ex; + } catch (DownloadFailedException ex) { + throwSuppressionParseException("Unable to fetch the configured suppression file", ex); + } catch (MalformedURLException ex) { + throwSuppressionParseException("Configured suppression file has an invalid URL", ex); + } catch (SuppressionParseException ex) { + throw ex; + } catch (IOException ex) { + throwSuppressionParseException("Unable to create temp file for suppressions", ex); + } finally { + if (deleteTempFile && file != null) { + FileUtils.delete(file); } } - } catch (DownloadFailedException ex) { - throwSuppressionParseException("Unable to fetch the configured suppression file", ex); - } catch (MalformedURLException ex) { - throwSuppressionParseException("Configured suppression file has an invalid URL", ex); - } catch (SuppressionParseException ex) { - throw ex; - } catch (IOException ex) { - throwSuppressionParseException("Unable to create temp file for suppressions", ex); - } finally { - if (deleteTempFile && file != null) { - FileUtils.delete(file); - } } + LOGGER.debug("{} suppression rules were loaded.", rules.size()); } /** diff --git a/dependency-check-maven/src/it/629-jackson-dataformat/pom.xml b/dependency-check-maven/src/it/629-jackson-dataformat/pom.xml index f1e6cd154..7c9b78e60 100644 --- a/dependency-check-maven/src/it/629-jackson-dataformat/pom.xml +++ b/dependency-check-maven/src/it/629-jackson-dataformat/pom.xml @@ -22,8 +22,8 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved. test-dataformat-jackson 1.0.0-SNAPSHOT jar - - + + com.fasterxml.jackson.core jackson-databind 2.4.5 @@ -38,10 +38,10 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved. jackson-dataformat-cbor 2.4.5 - - com.fasterxml.jackson.dataformat - jackson-dataformat-xml - 2.4.5 - - - \ No newline at end of file + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + 2.4.5 + + + diff --git a/dependency-check-maven/src/it/730-multiple-suppression-files/invoker.properties b/dependency-check-maven/src/it/730-multiple-suppression-files/invoker.properties new file mode 100644 index 000000000..9c2542d23 --- /dev/null +++ b/dependency-check-maven/src/it/730-multiple-suppression-files/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/pom.xml b/dependency-check-maven/src/it/730-multiple-suppression-files/pom.xml new file mode 100644 index 000000000..8a534171e --- /dev/null +++ b/dependency-check-maven/src/it/730-multiple-suppression-files/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/postbuild.groovy b/dependency-check-maven/src/it/730-multiple-suppression-files/postbuild.groovy new file mode 100644 index 000000000..2a42192d9 --- /dev/null +++ b/dependency-check-maven/src/it/730-multiple-suppression-files/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/test-suppression1.xml b/dependency-check-maven/src/it/730-multiple-suppression-files/test-suppression1.xml new file mode 100644 index 000000000..e3bd8c0b0 --- /dev/null +++ b/dependency-check-maven/src/it/730-multiple-suppression-files/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/test-suppression2.xml b/dependency-check-maven/src/it/730-multiple-suppression-files/test-suppression2.xml new file mode 100644 index 000000000..f0b4fad7b --- /dev/null +++ b/dependency-check-maven/src/it/730-multiple-suppression-files/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 eb945c2ab..0504bdfd5 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 @@ -199,10 +199,10 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma @Parameter(property = "connectionTimeout", defaultValue = "", required = false) private String connectionTimeout; /** - * The path to the suppression file. + * The paths to the suppression files. */ - @Parameter(property = "suppressionFile", defaultValue = "", required = false) - private String suppressionFile; + @Parameter(required = false) + private String[] suppressionFiles; /** * The path to the hints file. @@ -920,8 +920,9 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma Settings.setStringIfNotNull(Settings.KEYS.PROXY_NON_PROXY_HOSTS, proxy.getNonProxyHosts()); } + Settings.setArrayIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFiles); + Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); - Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); Settings.setStringIfNotEmpty(Settings.KEYS.HINTS_FILE, hintsFile); //File Type Analyzer Settings