From 6d5d5ceb7bec46bedf20e17918dcb8cde435abc7 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Thu, 14 Jul 2016 06:31:54 -0400 Subject: [PATCH 01/30] Updated exception handling so that issue #215 can be resolved --- .../org/owasp/dependencycheck/Engine.java | 149 ++++++++++++------ .../agent/DependencyCheckScanAgent.java | 79 ++++++---- .../exception/ExceptionCollection.java | 131 +++++++++++++++ .../exception/ReportException.java | 66 ++++++++ .../reporting/ReportGenerator.java | 102 ++++++------ .../EngineIntegrationTest.java | 33 +++- .../analyzer/RubyBundleAuditAnalyzerTest.java | 5 + .../owasp/dependencycheck/maven/Engine.java | 45 ++++-- 8 files changed, 473 insertions(+), 137 deletions(-) create mode 100644 dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java create mode 100644 dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ReportException.java diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java index 675eee417..824f5103a 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java @@ -30,6 +30,8 @@ import org.owasp.dependencycheck.data.update.UpdateService; import org.owasp.dependencycheck.data.update.exception.UpdateException; import org.owasp.dependencycheck.dependency.Dependency; import org.owasp.dependencycheck.exception.NoDataException; +import org.owasp.dependencycheck.exception.ExceptionCollection; +import org.owasp.dependencycheck.exception.InitializationException; import org.owasp.dependencycheck.utils.InvalidSettingException; import org.owasp.dependencycheck.utils.Settings; import org.slf4j.Logger; @@ -47,8 +49,10 @@ import java.util.Map; import java.util.Set; /** - * Scans files, directories, etc. for Dependencies. Analyzers are loaded and used to process the files found by the scan, if a - * file is encountered and an Analyzer is associated with the file type then the file is turned into a dependency. + * Scans files, directories, etc. for Dependencies. Analyzers are loaded and + * used to process the files found by the scan, if a file is encountered and an + * Analyzer is associated with the file type then the file is turned into a + * dependency. * * @author Jeremy Long */ @@ -69,7 +73,8 @@ public class Engine implements FileFilter { private final Set fileTypeAnalyzers = new HashSet(); /** - * The ClassLoader to use when dynamically loading Analyzer and Update services. + * The ClassLoader to use when dynamically loading Analyzer and Update + * services. */ private ClassLoader serviceClassLoader = Thread.currentThread().getContextClassLoader(); /** @@ -80,7 +85,8 @@ public class Engine implements FileFilter { /** * Creates a new Engine. * - * @throws DatabaseException thrown if there is an error connecting to the database + * @throws DatabaseException thrown if there is an error connecting to the + * database */ public Engine() throws DatabaseException { initializeEngine(); @@ -90,7 +96,8 @@ public class Engine implements FileFilter { * Creates a new Engine. * * @param serviceClassLoader a reference the class loader being used - * @throws DatabaseException thrown if there is an error connecting to the database + * @throws DatabaseException thrown if there is an error connecting to the + * database */ public Engine(ClassLoader serviceClassLoader) throws DatabaseException { this.serviceClassLoader = serviceClassLoader; @@ -98,9 +105,11 @@ public class Engine implements FileFilter { } /** - * Creates a new Engine using the specified classloader to dynamically load Analyzer and Update services. + * Creates a new Engine using the specified classloader to dynamically load + * Analyzer and Update services. * - * @throws DatabaseException thrown if there is an error connecting to the database + * @throws DatabaseException thrown if there is an error connecting to the + * database */ protected final void initializeEngine() throws DatabaseException { ConnectionFactory.initialize(); @@ -115,7 +124,8 @@ public class Engine implements FileFilter { } /** - * Loads the analyzers specified in the configuration file (or system properties). + * Loads the analyzers specified in the configuration file (or system + * properties). */ private void loadAnalyzers() { if (!analyzers.isEmpty()) { @@ -164,8 +174,9 @@ public class Engine implements FileFilter { } /** - * Scans an array of files or directories. If a directory is specified, it will be scanned recursively. Any dependencies - * identified are added to the dependency collection. + * Scans an array of files or directories. If a directory is specified, it + * will be scanned recursively. Any dependencies identified are added to the + * dependency collection. * * @param paths an array of paths to files or directories to be analyzed * @return the list of dependencies scanned @@ -183,8 +194,9 @@ public class Engine implements FileFilter { } /** - * Scans a given file or directory. If a directory is specified, it will be scanned recursively. Any dependencies identified - * are added to the dependency collection. + * Scans a given file or directory. If a directory is specified, it will be + * scanned recursively. Any dependencies identified are added to the + * dependency collection. * * @param path the path to a file or directory to be analyzed * @return the list of dependencies scanned @@ -195,8 +207,9 @@ public class Engine implements FileFilter { } /** - * Scans an array of files or directories. If a directory is specified, it will be scanned recursively. Any dependencies - * identified are added to the dependency collection. + * Scans an array of files or directories. If a directory is specified, it + * will be scanned recursively. Any dependencies identified are added to the + * dependency collection. * * @param files an array of paths to files or directories to be analyzed. * @return the list of dependencies @@ -214,8 +227,9 @@ public class Engine implements FileFilter { } /** - * Scans a collection of files or directories. If a directory is specified, it will be scanned recursively. Any dependencies - * identified are added to the dependency collection. + * Scans a collection of files or directories. If a directory is specified, + * it will be scanned recursively. Any dependencies identified are added to + * the dependency collection. * * @param files a set of paths to files or directories to be analyzed * @return the list of dependencies scanned @@ -233,8 +247,9 @@ public class Engine implements FileFilter { } /** - * Scans a given file or directory. If a directory is specified, it will be scanned recursively. Any dependencies identified - * are added to the dependency collection. + * Scans a given file or directory. If a directory is specified, it will be + * scanned recursively. Any dependencies identified are added to the + * dependency collection. * * @param file the path to a file or directory to be analyzed * @return the list of dependencies scanned @@ -257,7 +272,8 @@ public class Engine implements FileFilter { } /** - * Recursively scans files and directories. Any dependencies identified are added to the dependency collection. + * Recursively scans files and directories. Any dependencies identified are + * added to the dependency collection. * * @param dir the directory to scan * @return the list of Dependency objects scanned @@ -282,7 +298,8 @@ public class Engine implements FileFilter { } /** - * Scans a specified file. If a dependency is identified it is added to the dependency collection. + * Scans a specified file. If a dependency is identified it is added to the + * dependency collection. * * @param file The file to scan * @return the scanned dependency @@ -301,20 +318,38 @@ public class Engine implements FileFilter { } /** - * Runs the analyzers against all of the dependencies. Since the mutable dependencies list is exposed via - * {@link #getDependencies()}, this method iterates over a copy of the dependencies list. Thus, the potential for - * {@link java.util.ConcurrentModificationException}s is avoided, and analyzers may safely add or remove entries from the - * dependencies list. + * Runs the analyzers against all of the dependencies. Since the mutable + * dependencies list is exposed via {@link #getDependencies()}, this method + * iterates over a copy of the dependencies list. Thus, the potential for + * {@link java.util.ConcurrentModificationException}s is avoided, and + * analyzers may safely add or remove entries from the dependencies list. + * + * Every effort is made to complete analysis on the dependencies. In some + * cases an exception will occur with part of the analysis being performed + * which may not affect the entire analysis. If an exception occurs it will + * be included in the thrown exception collection. + * + * @throws ExceptionCollection a collections of any exceptions that occurred + * during analysis */ - public void analyzeDependencies() { + public void analyzeDependencies() throws ExceptionCollection { + List exceptions = new ArrayList(); boolean autoUpdate = true; try { autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE); } catch (InvalidSettingException ex) { LOGGER.debug("Invalid setting for auto-update; using true."); + exceptions.add(ex); } if (autoUpdate) { - doUpdates(); + try { + doUpdates(); + } catch (UpdateException ex) { + exceptions.add(ex); + LOGGER.warn("Unable to update Cached Web DataSource, using local " + + "data instead. Results may not include recent vulnerabilities."); + LOGGER.debug("Update Error", ex); + } } //need to ensure that data exists @@ -323,12 +358,13 @@ public class Engine implements FileFilter { } catch (NoDataException ex) { LOGGER.error("{}\n\nUnable to continue dependency-check analysis.", ex.getMessage()); LOGGER.debug("", ex); - return; + exceptions.add(ex); + throw new ExceptionCollection(exceptions, true); } catch (DatabaseException ex) { LOGGER.error("{}\n\nUnable to continue dependency-check analysis.", ex.getMessage()); LOGGER.debug("", ex); - return; - + exceptions.add(ex); + throw new ExceptionCollection(exceptions, true); } LOGGER.debug("\n----------------------------------------------------\nBEGIN ANALYSIS\n----------------------------------------------------"); @@ -340,7 +376,12 @@ public class Engine implements FileFilter { final List analyzerList = analyzers.get(phase); for (Analyzer a : analyzerList) { - a = initializeAnalyzer(a); + try { + a = initializeAnalyzer(a); + } catch (InitializationException ex) { + exceptions.add(ex); + continue; + } /* need to create a copy of the collection because some of the * analyzers may modify it. This prevents ConcurrentModificationExceptions. @@ -361,10 +402,12 @@ public class Engine implements FileFilter { } catch (AnalysisException ex) { LOGGER.warn("An error occurred while analyzing '{}'.", d.getActualFilePath()); LOGGER.debug("", ex); + exceptions.add(ex); } catch (Throwable ex) { //final AnalysisException ax = new AnalysisException(axMsg, ex); LOGGER.warn("An unexpected error occurred during analysis of '{}'", d.getActualFilePath()); LOGGER.debug("", ex); + exceptions.add(ex); } } } @@ -380,6 +423,9 @@ public class Engine implements FileFilter { LOGGER.debug("\n----------------------------------------------------\nEND ANALYSIS\n----------------------------------------------------"); LOGGER.info("Analysis Complete ({} ms)", System.currentTimeMillis() - analysisStart); + if (exceptions.size() > 0) { + throw new ExceptionCollection(exceptions); + } } /** @@ -387,12 +433,14 @@ public class Engine implements FileFilter { * * @param analyzer the analyzer to initialize * @return the initialized analyzer + * @throws InitializationException thrown when there is a problem + * initializing the analyzer */ - protected Analyzer initializeAnalyzer(Analyzer analyzer) { + protected Analyzer initializeAnalyzer(Analyzer analyzer) throws InitializationException { try { LOGGER.debug("Initializing {}", analyzer.getName()); analyzer.initialize(); - } catch (Throwable ex) { + } catch (InitializationException ex) { LOGGER.error("Exception occurred initializing {}.", analyzer.getName()); LOGGER.debug("", ex); try { @@ -400,6 +448,16 @@ public class Engine implements FileFilter { } catch (Throwable ex1) { LOGGER.trace("", ex1); } + throw ex; + } catch (Throwable ex) { + LOGGER.error("Unexpected exception occurred initializing {}.", analyzer.getName()); + LOGGER.debug("", ex); + try { + analyzer.close(); + } catch (Throwable ex1) { + LOGGER.trace("", ex1); + } + throw new InitializationException("Unexpected Exception", ex); } return analyzer; } @@ -419,28 +477,26 @@ public class Engine implements FileFilter { } /** - * Cycles through the cached web data sources and calls update on all of them. + * Cycles through the cached web data sources and calls update on all of + * them. + * + * @throws UpdateException */ - public void doUpdates() { + public void doUpdates() throws UpdateException { LOGGER.info("Checking for updates"); final long updateStart = System.currentTimeMillis(); final UpdateService service = new UpdateService(serviceClassLoader); final Iterator iterator = service.getDataSources(); while (iterator.hasNext()) { final CachedWebDataSource source = iterator.next(); - try { - source.update(); - } catch (UpdateException ex) { - LOGGER.warn( - "Unable to update Cached Web DataSource, using local data instead. Results may not include recent vulnerabilities."); - LOGGER.debug("Unable to update details for {}", source.getClass().getName(), ex); - } + source.update(); } LOGGER.info("Check for updates complete ({} ms)", System.currentTimeMillis() - updateStart); } /** - * Returns a full list of all of the analyzers. This is useful for reporting which analyzers where used. + * Returns a full list of all of the analyzers. This is useful for reporting + * which analyzers where used. * * @return a list of Analyzers */ @@ -457,7 +513,8 @@ public class Engine implements FileFilter { * Checks all analyzers to see if an extension is supported. * * @param file a file extension - * @return true or false depending on whether or not the file extension is supported + * @return true or false depending on whether or not the file extension is + * supported */ @Override public boolean accept(File file) { @@ -483,10 +540,12 @@ public class Engine implements FileFilter { } /** - * Checks the CPE Index to ensure documents exists. If none exist a NoDataException is thrown. + * Checks the CPE Index to ensure documents exists. If none exist a + * NoDataException is thrown. * * @throws NoDataException thrown if no data exists in the CPE Index - * @throws DatabaseException thrown if there is an exception opening the database + * @throws DatabaseException thrown if there is an exception opening the + * database */ private void ensureDataExists() throws NoDataException, DatabaseException { final CveDB cve = new CveDB(); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java index b2b63955e..038644a3e 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java @@ -27,6 +27,7 @@ import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties; import org.owasp.dependencycheck.dependency.Dependency; import org.owasp.dependencycheck.dependency.Identifier; import org.owasp.dependencycheck.dependency.Vulnerability; +import org.owasp.dependencycheck.exception.ExceptionCollection; import org.owasp.dependencycheck.exception.ScanAgentException; import org.owasp.dependencycheck.reporting.ReportGenerator; import org.owasp.dependencycheck.utils.Settings; @@ -34,10 +35,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * This class provides a way to easily conduct a scan solely based on existing evidence metadata rather than collecting evidence - * from the files themselves. This class is based on the Ant task and Maven plugin with the exception that it takes a list of - * dependencies that can be programmatically added from data in a spreadsheet, database or some other datasource and conduct a - * scan based on this pre-defined evidence. + * This class provides a way to easily conduct a scan solely based on existing + * evidence metadata rather than collecting evidence from the files themselves. + * This class is based on the Ant task and Maven plugin with the exception that + * it takes a list of dependencies that can be programmatically added from data + * in a spreadsheet, database or some other datasource and conduct a scan based + * on this pre-defined evidence. * *

Example:

*
@@ -138,7 +141,8 @@ public class DependencyCheckScanAgent {
     }
 
     /**
-     * Specifies the destination directory for the generated Dependency-Check report.
+     * Specifies the destination directory for the generated Dependency-Check
+     * report.
      */
     private String reportOutputDirectory;
 
@@ -161,9 +165,11 @@ public class DependencyCheckScanAgent {
     }
 
     /**
-     * Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which
-     * means since the CVSS scores are 0-10, by default the build will never fail and the CVSS score is set to 11. The valid range
-     * for the fail build on CVSS is 0 to 11, where anything above 10 will not cause the build to fail.
+     * Specifies if the build should be failed if a CVSS score above a specified
+     * level is identified. The default is 11 which means since the CVSS scores
+     * are 0-10, by default the build will never fail and the CVSS score is set
+     * to 11. The valid range for the fail build on CVSS is 0 to 11, where
+     * anything above 10 will not cause the build to fail.
      */
     private float failBuildOnCVSS = 11;
 
@@ -186,8 +192,8 @@ public class DependencyCheckScanAgent {
     }
 
     /**
-     * Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. Default
-     * is true.
+     * Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not
+     * recommended that this be turned to false. Default is true.
      */
     private boolean autoUpdate = true;
 
@@ -233,8 +239,9 @@ public class DependencyCheckScanAgent {
     }
 
     /**
-     * The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the
-     * Site plugin unless the externalReport is set to true. Default is HTML.
+     * The report format to be generated (HTML, XML, VULN, ALL). This
+     * configuration option has no affect if using this within the Site plugin
+     * unless the externalReport is set to true. Default is HTML.
      */
     private ReportGenerator.Format reportFormat = ReportGenerator.Format.HTML;
 
@@ -283,7 +290,9 @@ public class DependencyCheckScanAgent {
      * Get the value of proxyServer.
      *
      * @return the value of proxyServer
-     * @deprecated use {@link org.owasp.dependencycheck.agent.DependencyCheckScanAgent#getProxyServer()} instead
+     * @deprecated use
+     * {@link org.owasp.dependencycheck.agent.DependencyCheckScanAgent#getProxyServer()}
+     * instead
      */
     @Deprecated
     public String getProxyUrl() {
@@ -694,8 +703,8 @@ public class DependencyCheckScanAgent {
     }
 
     /**
-     * Additional ZIP File extensions to add analyze. This should be a comma-separated list of file extensions to treat like ZIP
-     * files.
+     * Additional ZIP File extensions to add analyze. This should be a
+     * comma-separated list of file extensions to treat like ZIP files.
      */
     private String zipExtensions;
 
@@ -836,11 +845,17 @@ public class DependencyCheckScanAgent {
      * Executes the Dependency-Check on the dependent libraries.
      *
      * @return the Engine used to scan the dependencies.
-     * @throws org.owasp.dependencycheck.data.nvdcve.DatabaseException thrown if there is an exception connecting to the database
+     * @throws org.owasp.dependencycheck.data.nvdcve.DatabaseException thrown if
+     * there is an exception connecting to the database
      */
-    private Engine executeDependencyCheck() throws DatabaseException {
+    private Engine executeDependencyCheck() throws ExceptionCollection {
         populateSettings();
-        final Engine engine = new Engine();
+        final Engine engine;
+        try {
+            engine = new Engine();
+        } catch (DatabaseException ex) {
+            throw new ExceptionCollection(ex, true);
+        }
         engine.setDependencies(this.dependencies);
         engine.analyzeDependencies();
         return engine;
@@ -881,8 +896,9 @@ public class DependencyCheckScanAgent {
     }
 
     /**
-     * Takes the properties supplied and updates the dependency-check settings. Additionally, this sets the system properties
-     * required to change the proxy server, port, and connection timeout.
+     * Takes the properties supplied and updates the dependency-check settings.
+     * Additionally, this sets the system properties required to change the
+     * proxy server, port, and connection timeout.
      */
     private void populateSettings() {
         Settings.initialize();
@@ -925,7 +941,8 @@ public class DependencyCheckScanAgent {
      * Executes the dependency-check and generates the report.
      *
      * @return a reference to the engine used to perform the scan.
-     * @throws org.owasp.dependencycheck.exception.ScanAgentException thrown if there is an exception executing the scan.
+     * @throws org.owasp.dependencycheck.exception.ScanAgentException thrown if
+     * there is an exception executing the scan.
      */
     public Engine execute() throws ScanAgentException {
         Engine engine = null;
@@ -940,10 +957,12 @@ public class DependencyCheckScanAgent {
             if (this.failBuildOnCVSS <= 10) {
                 checkForFailure(engine.getDependencies());
             }
-        } catch (DatabaseException ex) {
-            LOGGER.error(
-                    "Unable to connect to the dependency-check database; analysis has stopped");
-            LOGGER.debug("", ex);
+        } catch (ExceptionCollection ex) {
+            if (ex.isFatal()) {
+                LOGGER.error("A fatal exception occurred during analysis; analysis has stopped. Please see the debug log for more details.");
+                LOGGER.debug("", ex);
+            }
+            throw new ScanAgentException("One or more exceptions occurred during analysis; please see the debug log for more details.", ex);
         } finally {
             Settings.cleanup(true);
             if (engine != null) {
@@ -954,11 +973,12 @@ public class DependencyCheckScanAgent {
     }
 
     /**
-     * Checks to see if a vulnerability has been identified with a CVSS score that is above the threshold set in the
-     * configuration.
+     * Checks to see if a vulnerability has been identified with a CVSS score
+     * that is above the threshold set in the configuration.
      *
      * @param dependencies the list of dependency objects
-     * @throws org.owasp.dependencycheck.exception.ScanAgentException thrown if there is an exception executing the scan.
+     * @throws org.owasp.dependencycheck.exception.ScanAgentException thrown if
+     * there is an exception executing the scan.
      */
     private void checkForFailure(List dependencies) throws ScanAgentException {
         final StringBuilder ids = new StringBuilder();
@@ -986,7 +1006,8 @@ public class DependencyCheckScanAgent {
     }
 
     /**
-     * Generates a warning message listing a summary of dependencies and their associated CPE and CVE entries.
+     * Generates a warning message listing a summary of dependencies and their
+     * associated CPE and CVE entries.
      *
      * @param dependencies a list of dependency objects
      */
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java
new file mode 100644
index 000000000..67e426a0d
--- /dev/null
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java
@@ -0,0 +1,131 @@
+/*
+ * 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) 2016 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.exception;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A collection of several exceptions.
+ *
+ * @author Jeremy Lomg
+ */
+public class ExceptionCollection extends Exception {
+
+    /**
+     * Instantiates a new exception collection.
+     *
+     * @param exceptions a list of exceptions
+     */
+    public ExceptionCollection(List exceptions) {
+        super();
+        this.exceptions = exceptions;
+    }
+    /**
+     * Instantiates a new exception collection.
+     *
+     * @param exceptions a list of exceptions
+     * @param fatal indicates if the exception that occurred is fatal - meaning
+     * that no analysis was performed.
+     */
+    public ExceptionCollection(List exceptions, boolean fatal) {
+        super();
+        this.exceptions = exceptions;
+        this.fatal = fatal;
+    }
+        /**
+     * Instantiates a new exception collection.
+     *
+     * @param exceptions a list of exceptions
+     * @param fatal indicates if the exception that occurred is fatal - meaning
+     * that no analysis was performed.
+     */
+    public ExceptionCollection(Throwable exceptions, boolean fatal) {
+        super();
+        this.exceptions.add(exceptions);
+        this.fatal = fatal;
+    }
+    /**
+     * Instantiates a new exception collection.
+     */
+    public ExceptionCollection() {
+        super();
+        this.exceptions = new ArrayList();
+    }
+    /**
+     * The serial version uid.
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * A collection of exceptions.
+     */
+    private List exceptions;
+
+    /**
+     * Get the value of exceptions.
+     *
+     * @return the value of exceptions
+     */
+    public List getExceptions() {
+        return exceptions;
+    }
+
+    /**
+     * Adds an exception to the collection.
+     *
+     * @param ex the exception to add
+     */
+    public void addException(Throwable ex) {
+        this.exceptions.add(ex);
+    }
+        /**
+     * Adds an exception to the collection.
+     *
+     * @param ex the exception to add
+     */
+    public void addException(Throwable ex, boolean fatal) {
+        addException(ex);
+        this.fatal = fatal;
+    }
+
+    /**
+     * Flag indicating if a fatal exception occurred that would prevent the attempt
+     * at completing the analysis even if exceptions occurred.
+     */
+    private boolean fatal = false;
+
+    /**
+     * Get the value of fatal
+     *
+     * @return the value of fatal
+     */
+    public boolean isFatal() {
+        return fatal;
+    }
+
+    /**
+     * Set the value of fatal
+     *
+     * @param fatal new value of fatal
+     */
+    public void setFatal(boolean fatal) {
+        this.fatal = fatal;
+    }
+
+}
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ReportException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ReportException.java
new file mode 100644
index 000000000..7199b3520
--- /dev/null
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ReportException.java
@@ -0,0 +1,66 @@
+/*
+ * 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) 2016 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.exception;
+
+/**
+ * An exception used when generating reports.
+ *
+ * @author Jeremy Long
+ */
+public class ReportException extends Exception {
+
+    /**
+     * The serial version uid.
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Creates a new ReportException.
+     */
+    public ReportException() {
+        super();
+    }
+
+    /**
+     * Creates a new ReportException.
+     *
+     * @param msg a message for the exception.
+     */
+    public ReportException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Creates a new ReportException.
+     *
+     * @param ex the cause of the exception.
+     */
+    public ReportException(Throwable ex) {
+        super(ex);
+    }
+
+    /**
+     * Creates a new ReportException.
+     *
+     * @param msg a message for the exception.
+     * @param ex the cause of the exception.
+     */
+    public ReportException(String msg, Throwable ex) {
+        super(msg, ex);
+    }
+}
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java
index b47f9a8b9..99b7b387d 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java
@@ -26,6 +26,7 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Date;
@@ -37,13 +38,16 @@ import org.apache.velocity.runtime.RuntimeConstants;
 import org.owasp.dependencycheck.analyzer.Analyzer;
 import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
 import org.owasp.dependencycheck.dependency.Dependency;
+import org.owasp.dependencycheck.exception.ReportException;
 import org.owasp.dependencycheck.utils.Settings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * The ReportGenerator is used to, as the name implies, generate reports. Internally the generator uses the Velocity
- * Templating Engine. The ReportGenerator exposes a list of Dependencies to the template when generating the report.
+ * The ReportGenerator is used to, as the name implies, generate reports.
+ * Internally the generator uses the Velocity Templating Engine. The
+ * ReportGenerator exposes a list of Dependencies to the template when
+ * generating the report.
  *
  * @author Jeremy Long
  */
@@ -79,7 +83,7 @@ public class ReportGenerator {
     /**
      * The Velocity Engine.
      */
-    private final VelocityEngine engine;
+    private final VelocityEngine velocityEngine;
     /**
      * The Velocity Engine Context.
      */
@@ -91,13 +95,14 @@ public class ReportGenerator {
      * @param applicationName the application name being analyzed
      * @param dependencies the list of dependencies
      * @param analyzers the list of analyzers used
-     * @param properties the database properties (containing timestamps of the NVD CVE data)
+     * @param properties the database properties (containing timestamps of the
+     * NVD CVE data)
      */
     public ReportGenerator(String applicationName, List dependencies, List analyzers, DatabaseProperties properties) {
-        engine = createVelocityEngine();
+        velocityEngine = createVelocityEngine();
         context = createContext();
 
-        engine.init();
+        velocityEngine.init();
 
         final DateFormat dateFormat = new SimpleDateFormat("MMM d, yyyy 'at' HH:mm:ss z");
         final DateFormat dateFormatXML = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
@@ -119,19 +124,19 @@ public class ReportGenerator {
     /**
      * Creates a new Velocity Engine.
      *
-     * @return a velocity engine.
+     * @return a velocity engine
      */
     private VelocityEngine createVelocityEngine() {
-        final VelocityEngine engine = new VelocityEngine();
+        final VelocityEngine velocity = new VelocityEngine();
         // Logging redirection for Velocity - Required by Jenkins and other server applications
-        engine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, VelocityLoggerRedirect.class.getName());
-        return engine;
+        velocity.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, VelocityLoggerRedirect.class.getName());
+        return velocity;
     }
 
     /**
      * Creates a new Velocity Context.
      *
-     * @return a Velocity Context.
+     * @return a Velocity Context
      */
     private Context createContext() {
         return new VelocityContext();
@@ -143,7 +148,7 @@ public class ReportGenerator {
      * @param outputStream the OutputStream to send the generated report to
      * @param format the format the report should be written in
      * @throws IOException is thrown when the template file does not exist
-     * @throws Exception is thrown if there is an error writing out the reports.
+     * @throws Exception is thrown if there is an error writing out the reports
      */
     public void generateReports(OutputStream outputStream, Format format) throws IOException, Exception {
         if (format == Format.XML || format == Format.ALL) {
@@ -162,10 +167,9 @@ public class ReportGenerator {
      *
      * @param outputDir the path where the reports should be written
      * @param format the format the report should be written in
-     * @throws IOException is thrown when the template file does not exist
-     * @throws Exception is thrown if there is an error writing out the reports.
+     * @throws ReportException is thrown if there is an error writing out the reports
      */
-    public void generateReports(String outputDir, Format format) throws IOException, Exception {
+    public void generateReports(String outputDir, Format format) throws ReportException {
         if (format == Format.XML || format == Format.ALL) {
             generateReport("XmlReport", outputDir + File.separator + "dependency-check-report.xml");
         }
@@ -181,11 +185,12 @@ public class ReportGenerator {
      * Generates the Dependency Reports for the identified dependencies.
      *
      * @param outputDir the path where the reports should be written
-     * @param outputFormat the format the report should be written in (XML, HTML, ALL)
-     * @throws IOException is thrown when the template file does not exist
-     * @throws Exception is thrown if there is an error writing out the reports.
+     * @param outputFormat the format the report should be written in (XML,
+     * HTML, ALL)
+     * @throws ReportException is thrown if there is an error creating out the
+     * reports
      */
-    public void generateReports(String outputDir, String outputFormat) throws IOException, Exception {
+    public void generateReports(String outputDir, String outputFormat) throws ReportException {
         final String format = outputFormat.toUpperCase();
         final String pathToCheck = outputDir.toLowerCase();
         if (format.matches("^(XML|HTML|VULN|ALL)$")) {
@@ -217,16 +222,16 @@ public class ReportGenerator {
     }
 
     /**
-     * Generates a report from a given Velocity Template. The template name provided can be the name of a template
-     * contained in the jar file, such as 'XmlReport' or 'HtmlReport', or the template name can be the path to a
+     * Generates a report from a given Velocity Template. The template name
+     * provided can be the name of a template contained in the jar file, such as
+     * 'XmlReport' or 'HtmlReport', or the template name can be the path to a
      * template file.
      *
-     * @param templateName the name of the template to load.
-     * @param outputStream the OutputStream to write the report to.
-     * @throws IOException is thrown when the template file does not exist.
-     * @throws Exception is thrown when an exception occurs.
+     * @param templateName the name of the template to load
+     * @param outputStream the OutputStream to write the report to
+     * @throws ReportException is thrown when an exception occurs
      */
-    protected void generateReport(String templateName, OutputStream outputStream) throws IOException, Exception {
+    protected void generateReport(String templateName, OutputStream outputStream) throws ReportException {
         InputStream input = null;
         String templatePath = null;
         final File f = new File(templateName);
@@ -235,27 +240,30 @@ public class ReportGenerator {
                 templatePath = templateName;
                 input = new FileInputStream(f);
             } catch (FileNotFoundException ex) {
-                LOGGER.error("Unable to generate the report, the report template file could not be found.");
-                LOGGER.debug("", ex);
+                throw new ReportException("Unable to locate template file: " + templateName, ex);
             }
         } else {
             templatePath = "templates/" + templateName + ".vsl";
             input = this.getClass().getClassLoader().getResourceAsStream(templatePath);
         }
         if (input == null) {
-            throw new IOException("Template file doesn't exist");
+            throw new ReportException("Template file doesn't exist: " + templatePath);
         }
 
-        final InputStreamReader reader = new InputStreamReader(input, "UTF-8");
+        InputStreamReader reader = null;
         OutputStreamWriter writer = null;
 
         try {
+            reader = new InputStreamReader(input, "UTF-8");
             writer = new OutputStreamWriter(outputStream, "UTF-8");
-
-            if (!engine.evaluate(context, writer, templatePath, reader)) {
-                throw new Exception("Failed to convert the template into html.");
+            if (!velocityEngine.evaluate(context, writer, templatePath, reader)) {
+                throw new ReportException("Failed to convert the template into html.");
             }
             writer.flush();
+        } catch (UnsupportedEncodingException ex) {
+            throw new ReportException("Unable to generate the report using UTF-8", ex);
+        } catch (IOException ex) {
+            throw new ReportException("Unable to write the report", ex);
         } finally {
             if (writer != null) {
                 try {
@@ -271,25 +279,27 @@ public class ReportGenerator {
                     LOGGER.trace("", ex);
                 }
             }
-            try {
-                reader.close();
-            } catch (IOException ex) {
-                LOGGER.trace("", ex);
+            if (reader != null) {
+                try {
+                    reader.close();
+                } catch (IOException ex) {
+                    LOGGER.trace("", ex);
+                }
             }
         }
     }
 
     /**
-     * Generates a report from a given Velocity Template. The template name provided can be the name of a template
-     * contained in the jar file, such as 'XmlReport' or 'HtmlReport', or the template name can be the path to a
+     * Generates a report from a given Velocity Template. The template name
+     * provided can be the name of a template contained in the jar file, such as
+     * 'XmlReport' or 'HtmlReport', or the template name can be the path to a
      * template file.
      *
-     * @param templateName the name of the template to load.
-     * @param outFileName the filename and path to write the report to.
-     * @throws IOException is thrown when the template file does not exist.
-     * @throws Exception is thrown when an exception occurs.
+     * @param templateName the name of the template to load
+     * @param outFileName the filename and path to write the report to
+     * @throws ReportException is thrown when the report cannot be generated
      */
-    protected void generateReport(String templateName, String outFileName) throws Exception {
+    protected void generateReport(String templateName, String outFileName) throws ReportException {
         File outFile = new File(outFileName);
         if (outFile.getParentFile() == null) {
             outFile = new File(".", outFileName);
@@ -297,7 +307,7 @@ public class ReportGenerator {
         if (!outFile.getParentFile().exists()) {
             final boolean created = outFile.getParentFile().mkdirs();
             if (!created) {
-                throw new Exception("Unable to create directory '" + outFile.getParentFile().getAbsolutePath() + "'.");
+                throw new ReportException("Unable to create directory '" + outFile.getParentFile().getAbsolutePath() + "'.");
             }
         }
 
@@ -305,6 +315,8 @@ public class ReportGenerator {
         try {
             outputSteam = new FileOutputStream(outFile);
             generateReport(templateName, outputSteam);
+        } catch (FileNotFoundException ex) {
+            throw new ReportException("Unable to write to file: " + outFile, ex);
         } finally {
             if (outputSteam != null) {
                 try {
diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIntegrationTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIntegrationTest.java
index 1e12e6a82..bceefc23b 100644
--- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIntegrationTest.java
+++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIntegrationTest.java
@@ -17,12 +17,19 @@
  */
 package org.owasp.dependencycheck;
 
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 import static org.junit.Assert.assertTrue;
 
 import org.junit.Test;
 import org.owasp.dependencycheck.data.nvdcve.CveDB;
+import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
 import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
+import org.owasp.dependencycheck.exception.ExceptionCollection;
+import org.owasp.dependencycheck.exception.ReportException;
 import org.owasp.dependencycheck.reporting.ReportGenerator;
+import org.owasp.dependencycheck.utils.InvalidSettingException;
 import org.owasp.dependencycheck.utils.Settings;
 
 /**
@@ -34,10 +41,14 @@ public class EngineIntegrationTest extends BaseDBTestCase {
     /**
      * Test running the entire engine.
      *
-     * @throws Exception is thrown when an exception occurs.
+     * @throws java.io.IOException
+     * @throws org.owasp.dependencycheck.utils.InvalidSettingException
+     * @throws org.owasp.dependencycheck.data.nvdcve.DatabaseException
+     * @throws org.owasp.dependencycheck.exception.ReportException
+     * @throws org.owasp.dependencycheck.exception.ExceptionCollection
      */
     @Test
-    public void testEngine() throws Exception {
+    public void testEngine() throws IOException, InvalidSettingException, DatabaseException, ReportException, ExceptionCollection {
         String testClasses = "target/test-classes";
         boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
         Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
@@ -45,7 +56,23 @@ public class EngineIntegrationTest extends BaseDBTestCase {
         Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
         instance.scan(testClasses);
         assertTrue(instance.getDependencies().size() > 0);
-        instance.analyzeDependencies();
+        try {
+            instance.analyzeDependencies();
+        } catch (ExceptionCollection ex) {
+            if (ex.getExceptions().size()==1 &&
+                    (ex.getExceptions().get(0).getMessage().contains("bundle-audit") ||
+                    ex.getExceptions().get(0).getMessage().contains("AssemblyAnalyzer"))) {
+                //this is fine to ignore
+            } else if (ex.getExceptions().size()==2 &&
+                    ((ex.getExceptions().get(0).getMessage().contains("bundle-audit") &&
+                    ex.getExceptions().get(1).getMessage().contains("AssemblyAnalyzer")) ||
+                    (ex.getExceptions().get(1).getMessage().contains("bundle-audit") &&
+                    ex.getExceptions().get(0).getMessage().contains("AssemblyAnalyzer")))) {
+                //this is fine to ignore
+            } else {
+                throw ex;
+            }
+        }
         CveDB cveDB = new CveDB();
         cveDB.open();
         DatabaseProperties dbProp = cveDB.getDatabaseProperties();
diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.java
index d1f9101c3..050259597 100644
--- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.java
+++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.java
@@ -26,6 +26,7 @@ import java.io.File;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.logging.Level;
 
 import org.junit.After;
 import org.junit.Assume;
@@ -40,6 +41,7 @@ import org.owasp.dependencycheck.dependency.Dependency;
 import org.owasp.dependencycheck.dependency.Evidence;
 import org.owasp.dependencycheck.dependency.Identifier;
 import org.owasp.dependencycheck.dependency.Vulnerability;
+import org.owasp.dependencycheck.exception.ExceptionCollection;
 import org.owasp.dependencycheck.utils.Settings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -176,6 +178,7 @@ public class RubyBundleAuditAnalyzerTest extends BaseDBTestCase {
      * Test Ruby dependencies and their paths.
      *
      * @throws AnalysisException is thrown when an exception occurs.
+     * @throws DatabaseException thrown when an exception occurs
      */
     @Test
     public void testDependenciesPath() throws AnalysisException, DatabaseException {
@@ -187,6 +190,8 @@ public class RubyBundleAuditAnalyzerTest extends BaseDBTestCase {
         } catch (NullPointerException ex) {
             LOGGER.error("NPE", ex);
             throw ex;
+        } catch (ExceptionCollection ex) {
+            Assume.assumeNoException("Exception setting up RubyBundleAuditAnalyzer; bundle audit may not be installed, or property \"analyzer.bundle.audit.path\" may not be set.", ex);
         }
         List dependencies = engine.getDependencies();
         LOGGER.info(dependencies.size() + " dependencies found.");
diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/Engine.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/Engine.java
index f849c8a7e..b691ccde5 100644
--- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/Engine.java
+++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/Engine.java
@@ -23,13 +23,16 @@ import org.owasp.dependencycheck.analyzer.Analyzer;
 import org.owasp.dependencycheck.analyzer.CPEAnalyzer;
 import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer;
 import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
+import org.owasp.dependencycheck.data.update.exception.UpdateException;
+import org.owasp.dependencycheck.exception.ExceptionCollection;
+import org.owasp.dependencycheck.exception.InitializationException;
 import org.owasp.dependencycheck.utils.Settings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * A modified version of the core engine specifically designed to persist some data between multiple executions of a multi-module
- * Maven project.
+ * A modified version of the core engine specifically designed to persist some
+ * data between multiple executions of a multi-module Maven project.
  *
  * @author Jeremy Long
  */
@@ -52,16 +55,19 @@ public class Engine extends org.owasp.dependencycheck.Engine {
      */
     private List reactorProjects;
     /**
-     * Key used in the MavenProject context values to note whether or not an update has been executed.
+     * Key used in the MavenProject context values to note whether or not an
+     * update has been executed.
      */
     public static final String UPDATE_EXECUTED_FLAG = "dependency-check-update-executed";
 
     /**
-     * Creates a new Engine to perform anyalsis on dependencies.
+     * Creates a new Engine to perform analysis on dependencies.
      *
      * @param project the current Maven project
-     * @param reactorProjects the reactor projects for the current Maven execution
-     * @throws DatabaseException thrown if there is an issue connecting to the database
+     * @param reactorProjects the reactor projects for the current Maven
+     * execution
+     * @throws DatabaseException thrown if there is an issue connecting to the
+     * database
      */
     public Engine(MavenProject project, List reactorProjects) throws DatabaseException {
         this.currentProject = project;
@@ -71,9 +77,12 @@ public class Engine extends org.owasp.dependencycheck.Engine {
 
     /**
      * Runs the analyzers against all of the dependencies.
+     *
+     * @throws ExceptionCollection thrown if an exception occurred; contains a
+     * collection of exceptions that occurred during analysis.
      */
     @Override
-    public void analyzeDependencies() {
+    public void analyzeDependencies() throws ExceptionCollection {
         final MavenProject root = getExecutionRoot();
         if (root != null) {
             LOGGER.debug("Checking root project, {}, if updates have already been completed", root.getArtifactId());
@@ -91,8 +100,10 @@ public class Engine extends org.owasp.dependencycheck.Engine {
 
     /**
      * Runs the update steps of dependency-check.
+     *
+     * @throws UpdateException thrown if there is an exception
      */
-    public void update() {
+    public void update() throws UpdateException {
         final MavenProject root = getExecutionRoot();
         if (root != null && root.getContextValue(UPDATE_EXECUTED_FLAG) != null) {
             System.setProperty(Settings.KEYS.AUTO_UPDATE, Boolean.FALSE.toString());
@@ -103,20 +114,21 @@ public class Engine extends org.owasp.dependencycheck.Engine {
     /**
      * This constructor should not be called. Use Engine(MavenProject) instead.
      *
-     * @throws DatabaseException thrown if there is an issue connecting to the database
+     * @throws DatabaseException thrown if there is an issue connecting to the
+     * database
      */
     private Engine() throws DatabaseException {
     }
 
     /**
-     * Initializes the given analyzer. This skips the initialization of the CPEAnalyzer if it has been initialized by a previous
-     * execution.
+     * Initializes the given analyzer. This skips the initialization of the
+     * CPEAnalyzer if it has been initialized by a previous execution.
      *
      * @param analyzer the analyzer to initialize
      * @return the initialized analyzer
      */
     @Override
-    protected Analyzer initializeAnalyzer(Analyzer analyzer) {
+    protected Analyzer initializeAnalyzer(Analyzer analyzer) throws InitializationException {
         if (analyzer instanceof CPEAnalyzer) {
             CPEAnalyzer cpe = getPreviouslyLoadedCPEAnalyzer();
             if (cpe != null && cpe.isOpen()) {
@@ -129,7 +141,8 @@ public class Engine extends org.owasp.dependencycheck.Engine {
     }
 
     /**
-     * Releases resources used by the analyzers by calling close() on each analyzer.
+     * Releases resources used by the analyzers by calling close() on each
+     * analyzer.
      */
     @Override
     public void cleanup() {
@@ -216,8 +229,10 @@ public class Engine extends org.owasp.dependencycheck.Engine {
     }
 
     /**
-     * Resets the file type analyzers so that they can be re-used to scan additional directories. Without the reset the analyzer
-     * might be disabled because the first scan/analyze did not identify any files that could be processed by the analyzer.
+     * Resets the file type analyzers so that they can be re-used to scan
+     * additional directories. Without the reset the analyzer might be disabled
+     * because the first scan/analyze did not identify any files that could be
+     * processed by the analyzer.
      */
     public void resetFileTypeAnalyzers() {
         for (FileTypeAnalyzer a : getFileTypeAnalyzers()) {

From c5757dc5f412a6680463145cd9a7bbf829944b2e Mon Sep 17 00:00:00 2001
From: Jeremy Long 
Date: Sun, 17 Jul 2016 07:19:56 -0400
Subject: [PATCH 02/30] updates to resolve issue #215

---
 .../owasp/dependencycheck/taskdefs/Check.java |  90 ++++++-----
 .../owasp/dependencycheck/taskdefs/Purge.java |  57 ++++++-
 .../dependencycheck/taskdefs/Update.java      |  34 ++--
 .../src/site/markdown/config-purge.md         |   7 +-
 .../src/site/markdown/config-update.md        |   1 +
 .../src/site/markdown/configuration.md        |   1 +
 .../java/org/owasp/dependencycheck/App.java   | 149 +++++++++++++-----
 .../org/owasp/dependencycheck/Engine.java     |   6 +-
 .../exception/ExceptionCollection.java        |  88 ++++++++++-
 .../dependencycheck/maven/AggregateMojo.java  | 126 +++++++++++----
 .../maven/BaseDependencyCheckMojo.java        |  57 ++++---
 .../dependencycheck/maven/CheckMojo.java      |  73 ++++++---
 .../maven/{Engine.java => MavenEngine.java}   |  10 +-
 .../dependencycheck/maven/PurgeMojo.java      |  33 +++-
 .../dependencycheck/maven/UpdateMojo.java     |  36 +++--
 .../src/site/markdown/configuration.md        |   1 +
 .../maven/BaseDependencyCheckMojoTest.java    |   2 +-
 17 files changed, 569 insertions(+), 202 deletions(-)
 rename dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/{Engine.java => MavenEngine.java} (96%)

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 78f6e823a..86268a2d2 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
@@ -32,9 +32,12 @@ import org.owasp.dependencycheck.Engine;
 import org.owasp.dependencycheck.data.nvdcve.CveDB;
 import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
 import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
+import org.owasp.dependencycheck.data.update.exception.UpdateException;
 import org.owasp.dependencycheck.dependency.Dependency;
 import org.owasp.dependencycheck.dependency.Identifier;
 import org.owasp.dependencycheck.dependency.Vulnerability;
+import org.owasp.dependencycheck.exception.ExceptionCollection;
+import org.owasp.dependencycheck.exception.ReportException;
 import org.owasp.dependencycheck.reporting.ReportGenerator;
 import org.owasp.dependencycheck.reporting.ReportGenerator.Format;
 import org.owasp.dependencycheck.utils.Settings;
@@ -806,52 +809,67 @@ public class Check extends Update {
             engine = new Engine(Check.class.getClassLoader());
             if (isUpdateOnly()) {
                 log("Deprecated 'UpdateOnly' property set; please use the UpdateTask instead", Project.MSG_WARN);
-                engine.doUpdates();
-            } else {
                 try {
-                    for (Resource resource : path) {
-                        final FileProvider provider = resource.as(FileProvider.class);
-                        if (provider != null) {
-                            final File file = provider.getFile();
-                            if (file != null && file.exists()) {
-                                engine.scan(file);
-                            }
+                    engine.doUpdates();
+                } catch (UpdateException ex) {
+                    if (this.isFailOnError()) {
+                        throw new BuildException(ex);
+                    }
+                    log(ex.getMessage(), Project.MSG_ERR);
+                }
+            } else {
+                for (Resource resource : path) {
+                    final FileProvider provider = resource.as(FileProvider.class);
+                    if (provider != null) {
+                        final File file = provider.getFile();
+                        if (file != null && file.exists()) {
+                            engine.scan(file);
                         }
                     }
+                }
 
+                try {
                     engine.analyzeDependencies();
-                    DatabaseProperties prop = null;
-                    CveDB cve = null;
-                    try {
-                        cve = new CveDB();
-                        cve.open();
-                        prop = cve.getDatabaseProperties();
-                    } catch (DatabaseException ex) {
-                        log("Unable to retrieve DB Properties", ex, Project.MSG_DEBUG);
-                    } finally {
-                        if (cve != null) {
-                            cve.close();
-                        }
+                } catch (ExceptionCollection ex) {
+                    if (this.isFailOnError()) {
+                        throw new BuildException(ex);
                     }
-                    final ReportGenerator reporter = new ReportGenerator(getProjectName(), engine.getDependencies(), engine.getAnalyzers(), prop);
-                    reporter.generateReports(reportOutputDirectory, reportFormat);
+                }
+                DatabaseProperties prop = null;
+                CveDB cve = null;
+                try {
+                    cve = new CveDB();
+                    cve.open();
+                    prop = cve.getDatabaseProperties();
+                } catch (DatabaseException ex) {
+                    log("Unable to retrieve DB Properties", ex, Project.MSG_DEBUG);
+                } finally {
+                    if (cve != null) {
+                        cve.close();
+                    }
+                }
+                final ReportGenerator reporter = new ReportGenerator(getProjectName(), engine.getDependencies(), engine.getAnalyzers(), prop);
+                reporter.generateReports(reportOutputDirectory, reportFormat);
 
-                    if (this.failBuildOnCVSS <= 10) {
-                        checkForFailure(engine.getDependencies());
-                    }
-                    if (this.showSummary) {
-                        showSummary(engine.getDependencies());
-                    }
-                } catch (IOException ex) {
-                    log("Unable to generate dependency-check report", ex, Project.MSG_DEBUG);
-                    throw new BuildException("Unable to generate dependency-check report", ex);
-                } catch (Exception ex) {
-                    log("An exception occurred; unable to continue task", ex, Project.MSG_DEBUG);
-                    throw new BuildException("An exception occurred; unable to continue task", ex);
+                if (this.failBuildOnCVSS <= 10) {
+                    checkForFailure(engine.getDependencies());
+                }
+                if (this.showSummary) {
+                    showSummary(engine.getDependencies());
                 }
             }
         } catch (DatabaseException ex) {
-            log("Unable to connect to the dependency-check database; analysis has stopped", ex, Project.MSG_ERR);
+            final String msg = "Unable to connect to the dependency-check database; analysis has stopped";
+            if (this.isFailOnError()) {
+                throw new BuildException(msg, ex);
+            }
+            log(msg, ex, Project.MSG_ERR);
+        } catch (ReportException ex) {
+            final String msg = "Unable to generate the dependency-check report";
+            if (this.isFailOnError()) {
+                throw new BuildException(msg, ex);
+            }
+            log(msg, ex, Project.MSG_ERR);
         } finally {
             Settings.cleanup(true);
             if (engine != null) {
diff --git a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java
index ce28b0645..5316a44c8 100644
--- a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java
+++ b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java
@@ -71,6 +71,30 @@ public class Purge extends Task {
         this.dataDirectory = dataDirectory;
     }
 
+    /**
+     * Indicates if dependency-check should fail the build if an exception
+     * occurs.
+     */
+    private boolean failOnError = true;
+
+    /**
+     * Get the value of failOnError
+     *
+     * @return the value of failOnError
+     */
+    public boolean isFailOnError() {
+        return failOnError;
+    }
+
+    /**
+     * Set the value of failOnError
+     *
+     * @param failOnError new value of failOnError
+     */
+    public void setFailOnError(boolean failOnError) {
+        this.failOnError = failOnError;
+    }
+
     @Override
     public void execute() throws BuildException {
         populateSettings();
@@ -81,30 +105,49 @@ public class Purge extends Task {
                 if (db.delete()) {
                     log("Database file purged; local copy of the NVD has been removed", Project.MSG_INFO);
                 } else {
-                    log(String.format("Unable to delete '%s'; please delete the file manually", db.getAbsolutePath()), Project.MSG_ERR);
+                    final String msg = String.format("Unable to delete '%s'; please delete the file manually", db.getAbsolutePath());
+                    if (this.failOnError) {
+                        throw new BuildException(msg);
+                    }
+                    log(msg, Project.MSG_ERR);
                 }
             } else {
-                log(String.format("Unable to purge database; the database file does not exists: %s", db.getAbsolutePath()), Project.MSG_ERR);
+                final String msg = String.format("Unable to purge database; the database file does not exists: %s", db.getAbsolutePath());
+                if (this.failOnError) {
+                    throw new BuildException(msg);
+                }
+                log(msg, Project.MSG_ERR);
             }
         } catch (IOException ex) {
-            log("Unable to delete the database", Project.MSG_ERR);
+            final String msg = "Unable to delete the database";
+            if (this.failOnError) {
+                throw new BuildException(msg);
+            }
+            log(msg, Project.MSG_ERR);
         } finally {
             Settings.cleanup(true);
         }
     }
 
     /**
-     * Takes the properties supplied and updates the dependency-check settings. Additionally, this sets the system properties
-     * required to change the proxy server, port, and connection timeout.
+     * Takes the properties supplied and updates the dependency-check settings.
+     * Additionally, this sets the system properties required to change the
+     * proxy server, port, and connection timeout.
+     *
+     * @throws BuildException thrown if the properties file cannot be read.
      */
-    protected void populateSettings() {
+    protected void populateSettings() throws BuildException {
         Settings.initialize();
         InputStream taskProperties = null;
         try {
             taskProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
             Settings.mergeProperties(taskProperties);
         } catch (IOException ex) {
-            log("Unable to load the dependency-check ant task.properties file.", ex, Project.MSG_WARN);
+            final String msg = "Unable to load the dependency-check ant task.properties file.";
+            if (this.failOnError) {
+                throw new BuildException(msg, ex);
+            }
+            log(msg, ex, Project.MSG_WARN);
         } finally {
             if (taskProperties != null) {
                 try {
diff --git a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Update.java b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Update.java
index d121f21c1..5648c7c3e 100644
--- a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Update.java
+++ b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Update.java
@@ -18,14 +18,17 @@
 package org.owasp.dependencycheck.taskdefs;
 
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
 import org.owasp.dependencycheck.Engine;
 import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
+import org.owasp.dependencycheck.data.update.exception.UpdateException;
 import org.owasp.dependencycheck.utils.Settings;
 import org.slf4j.impl.StaticLoggerBinder;
 
 /**
- * An Ant task definition to execute dependency-check update. This will download the latest data from the National Vulnerability
- * Database (NVD) and store a copy in the local database.
+ * An Ant task definition to execute dependency-check update. This will download
+ * the latest data from the National Vulnerability Database (NVD) and store a
+ * copy in the local database.
  *
  * @author Jeremy Long
  */
@@ -381,10 +384,11 @@ public class Update extends Purge {
     }
 
     /**
-     * Executes the update by initializing the settings, downloads the NVD XML data, and then processes the data storing it in the
-     * local database.
+     * Executes the update by initializing the settings, downloads the NVD XML
+     * data, and then processes the data storing it in the local database.
      *
-     * @throws BuildException thrown if a connection to the local database cannot be made.
+     * @throws BuildException thrown if a connection to the local database
+     * cannot be made.
      */
     @Override
     public void execute() throws BuildException {
@@ -392,9 +396,20 @@ public class Update extends Purge {
         Engine engine = null;
         try {
             engine = new Engine(Update.class.getClassLoader());
-            engine.doUpdates();
+            try {
+                engine.doUpdates();
+            } catch (UpdateException ex) {
+                if (this.isFailOnError()) {
+                    throw new BuildException(ex);
+                }
+                log(ex.getMessage(), Project.MSG_ERR);
+            }
         } catch (DatabaseException ex) {
-            throw new BuildException("Unable to connect to the dependency-check database; unable to update the NVD data", ex);
+            final String msg = "Unable to connect to the dependency-check database; unable to update the NVD data";
+            if (this.isFailOnError()) {
+                throw new BuildException(msg, ex);
+            }
+            log(msg, Project.MSG_ERR);
         } finally {
             Settings.cleanup(true);
             if (engine != null) {
@@ -404,8 +419,9 @@ public class Update extends Purge {
     }
 
     /**
-     * Takes the properties supplied and updates the dependency-check settings. Additionally, this sets the system properties
-     * required to change the proxy server, port, and connection timeout.
+     * Takes the properties supplied and updates the dependency-check settings.
+     * Additionally, this sets the system properties required to change the
+     * proxy server, port, and connection timeout.
      *
      * @throws BuildException thrown when an invalid setting is configured.
      */
diff --git a/dependency-check-ant/src/site/markdown/config-purge.md b/dependency-check-ant/src/site/markdown/config-purge.md
index 80c9f5d91..e7026070a 100644
--- a/dependency-check-ant/src/site/markdown/config-purge.md
+++ b/dependency-check-ant/src/site/markdown/config-purge.md
@@ -14,6 +14,7 @@ Configuration: dependency-check-purge Task
 --------------------
 The following properties can be set on the dependency-check-purge task.
 
-Property              | Description                                                    | Default Value
-----------------------|----------------------------------------------------------------|------------------
-dataDirectory         | Data directory that is used to store the local copy of the NVD | data
+Property              | Description                                                            | Default Value
+----------------------|------------------------------------------------------------------------|------------------
+dataDirectory         | Data directory that is used to store the local copy of the NVD         | data
+failOnError           | Whether the build should fail if there is an error executing the purge | true
diff --git a/dependency-check-ant/src/site/markdown/config-update.md b/dependency-check-ant/src/site/markdown/config-update.md
index dd62e3dbe..87c772b80 100644
--- a/dependency-check-ant/src/site/markdown/config-update.md
+++ b/dependency-check-ant/src/site/markdown/config-update.md
@@ -24,6 +24,7 @@ proxyPort             | The Proxy Port.                    |  
 proxyUsername         | Defines the proxy user name.       |  
 proxyPassword         | Defines the proxy password.        |  
 connectionTimeout     | The URL Connection Timeout.        |  
+failOnError           | Whether the build should fail if there is an error executing the update | true
 
 Advanced Configuration
 ====================
diff --git a/dependency-check-ant/src/site/markdown/configuration.md b/dependency-check-ant/src/site/markdown/configuration.md
index e2bf57a24..a711cd013 100644
--- a/dependency-check-ant/src/site/markdown/configuration.md
+++ b/dependency-check-ant/src/site/markdown/configuration.md
@@ -34,6 +34,7 @@ Property              | Description
 autoUpdate            | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false.                                                                                 | true
 cveValidForHours      | Sets the number of hours to wait before checking for new updates from the NVD                                                                                                                      | 4
 failBuildOnCVSS       | Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail. | 11
+failOnError           | Whether the build should fail if there is an error executing the dependency-check analysis                                                                                                         | true
 projectName           | The name of the project being scanned.                                                                                                                                                             | Dependency-Check
 reportFormat          | The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the Site plugin unless the externalReport is set to true.                   | HTML
 reportOutputDirectory | The location to write the report(s). Note, this is not used if generating the report as part of a `mvn site` build                                                                                 | 'target'
diff --git a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java
index c8bc71cd6..6e1d0f8dd 100644
--- a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java
+++ b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java
@@ -37,6 +37,11 @@ import org.owasp.dependencycheck.utils.Settings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import ch.qos.logback.core.FileAppender;
+import java.util.logging.Level;
+import org.owasp.dependencycheck.data.update.exception.UpdateException;
+import org.owasp.dependencycheck.exception.ExceptionCollection;
+import org.owasp.dependencycheck.exception.ReportException;
+import org.owasp.dependencycheck.utils.InvalidSettingException;
 import org.slf4j.impl.StaticLoggerBinder;
 
 /**
@@ -57,13 +62,15 @@ public class App {
      * @param args the command line arguments
      */
     public static void main(String[] args) {
+        int exitCode = 0;
         try {
             Settings.initialize();
             final App app = new App();
-            app.run(args);
+            exitCode = app.run(args);
         } finally {
             Settings.cleanup(true);
         }
+        System.exit(exitCode);
     }
 
     /**
@@ -71,7 +78,8 @@ public class App {
      *
      * @param args the command line arguments
      */
-    public void run(String[] args) {
+    public int run(String[] args) {
+        int exitCode = 0;
         final CliParser cli = new CliParser();
 
         try {
@@ -79,11 +87,11 @@ public class App {
         } catch (FileNotFoundException ex) {
             System.err.println(ex.getMessage());
             cli.printHelp();
-            return;
+            return -1;
         } catch (ParseException ex) {
             System.err.println(ex.getMessage());
             cli.printHelp();
-            return;
+            return -2;
         }
 
         if (cli.getVerboseLog() != null) {
@@ -93,8 +101,15 @@ public class App {
         if (cli.isPurge()) {
             if (cli.getConnectionString() != null) {
                 LOGGER.error("Unable to purge the database when using a non-default connection string");
+                exitCode = -3;
             } else {
-                populateSettings(cli);
+                try {
+                    populateSettings(cli);
+                } catch (InvalidSettingException ex) {
+                    LOGGER.error(ex.getMessage());
+                    LOGGER.debug("Error loading properties file", ex);
+                    exitCode = -4;
+                }
                 File db;
                 try {
                     db = new File(Settings.getDataDirectory(), "dc.h2.db");
@@ -103,46 +118,96 @@ public class App {
                             LOGGER.info("Database file purged; local copy of the NVD has been removed");
                         } else {
                             LOGGER.error("Unable to delete '{}'; please delete the file manually", db.getAbsolutePath());
+                            exitCode = -5;
                         }
                     } else {
                         LOGGER.error("Unable to purge database; the database file does not exists: {}", db.getAbsolutePath());
+                        exitCode = -6;
                     }
                 } catch (IOException ex) {
                     LOGGER.error("Unable to delete the database");
+                    exitCode = -7;
                 }
             }
         } else if (cli.isGetVersion()) {
             cli.printVersionInfo();
         } else if (cli.isUpdateOnly()) {
-            populateSettings(cli);
-            runUpdateOnly();
+            try {
+                populateSettings(cli);
+            } catch (InvalidSettingException ex) {
+                LOGGER.error(ex.getMessage());
+                LOGGER.debug("Error loading properties file", ex);
+                exitCode = -4;
+            }
+            try {
+                runUpdateOnly();
+            } catch (UpdateException ex) {
+                LOGGER.error(ex.getMessage());
+                exitCode = -8;
+            } catch (DatabaseException ex) {
+                LOGGER.error(ex.getMessage());
+                exitCode = -9;
+            }
         } else if (cli.isRunScan()) {
-            populateSettings(cli);
+            try {
+                populateSettings(cli);
+            } catch (InvalidSettingException ex) {
+                LOGGER.error(ex.getMessage());
+                LOGGER.debug("Error loading properties file", ex);
+                exitCode = -4;
+            }
             try {
                 runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getProjectName(), cli.getScanFiles(),
                         cli.getExcludeList(), cli.getSymLinkDepth());
             } catch (InvalidScanPathException ex) {
                 LOGGER.error("An invalid scan path was detected; unable to scan '//*' paths");
+                exitCode = -10;
+            } catch (DatabaseException ex) {
+                LOGGER.error(ex.getMessage());
+                exitCode = -11;
+            } catch (ReportException ex) {
+                LOGGER.error(ex.getMessage());
+                exitCode = -12;
+            } catch (ExceptionCollection ex) {
+                if (ex.isFatal()) {
+                    exitCode =-13;
+                    LOGGER.error("One or more fatal errors occured");
+                } else {
+                    exitCode =-14;
+                }                
+                for (Throwable e : ex.getExceptions()) {
+                    LOGGER.error(e.getMessage());    
+                }
             }
         } else {
             cli.printHelp();
         }
+        return exitCode;
     }
 
     /**
-     * Scans the specified directories and writes the dependency reports to the reportDirectory.
+     * Scans the specified directories and writes the dependency reports to the
+     * reportDirectory.
      *
-     * @param reportDirectory the path to the directory where the reports will be written
+     * @param reportDirectory the path to the directory where the reports will
+     * be written
      * @param outputFormat the output format of the report
      * @param applicationName the application name for the report
      * @param files the files/directories to scan
      * @param excludes the patterns for files/directories to exclude
      * @param symLinkDepth the depth that symbolic links will be followed
      *
-     * @throws InvalidScanPathException thrown if the path to scan starts with "//"
+     * @throws InvalidScanPathException thrown if the path to scan starts with
+     * "//"
+     * @throws ReportException thrown when the report cannot be generated
+     * @throws DatabaseException thrown when there is an error connecting to the
+     * database
+     * @throws ExceptionCollection thrown when an exception occurs during
+     * analysis; there may be multiple exceptions contained within the
+     * collection.
      */
     private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files,
-            String[] excludes, int symLinkDepth) throws InvalidScanPathException {
+            String[] excludes, int symLinkDepth) throws InvalidScanPathException, DatabaseException, ExceptionCollection, ReportException {
         Engine engine = null;
         try {
             engine = new Engine();
@@ -174,8 +239,6 @@ public class App {
                         include = "**/*";
                     }
                 }
-                //LOGGER.debug("baseDir: {}", baseDir);
-                //LOGGER.debug("include: {}", include);
                 scanner.setBasedir(baseDir);
                 final String[] includes = {include};
                 scanner.setIncludes(includes);
@@ -197,7 +260,15 @@ public class App {
             }
             engine.scan(paths);
 
-            engine.analyzeDependencies();
+            ExceptionCollection exCol = null;
+            try {
+                engine.analyzeDependencies();
+            } catch (ExceptionCollection ex) {
+                if (ex.isFatal()) {
+                    throw ex;
+                }
+                exCol = ex;
+            }
             final List dependencies = engine.getDependencies();
             DatabaseProperties prop = null;
             CveDB cve = null;
@@ -205,8 +276,6 @@ public class App {
                 cve = new CveDB();
                 cve.open();
                 prop = cve.getDatabaseProperties();
-            } catch (DatabaseException ex) {
-                LOGGER.debug("Unable to retrieve DB Properties", ex);
             } finally {
                 if (cve != null) {
                     cve.close();
@@ -215,16 +284,14 @@ public class App {
             final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop);
             try {
                 report.generateReports(reportDirectory, outputFormat);
-            } catch (IOException ex) {
-                LOGGER.error("There was an IO error while attempting to generate the report.");
-                LOGGER.debug("", ex);
-            } catch (Throwable ex) {
-                LOGGER.error("There was an error while attempting to generate the report.");
-                LOGGER.debug("", ex);
+            } catch (ReportException ex) {
+                if (exCol != null) {
+                    exCol.addException(ex);
+                    throw exCol;
+                } else {
+                    throw ex;
+                }
             }
-        } catch (DatabaseException ex) {
-            LOGGER.error("Unable to connect to the dependency-check database; analysis has stopped");
-            LOGGER.debug("", ex);
         } finally {
             if (engine != null) {
                 engine.cleanup();
@@ -235,14 +302,11 @@ public class App {
     /**
      * Only executes the update phase of dependency-check.
      */
-    private void runUpdateOnly() {
+    private void runUpdateOnly() throws UpdateException, DatabaseException {
         Engine engine = null;
         try {
             engine = new Engine();
             engine.doUpdates();
-        } catch (DatabaseException ex) {
-            LOGGER.error("Unable to connect to the dependency-check database; analysis has stopped");
-            LOGGER.debug("", ex);
         } finally {
             if (engine != null) {
                 engine.cleanup();
@@ -253,11 +317,13 @@ public class App {
     /**
      * Updates the global Settings.
      *
-     * @param cli a reference to the CLI Parser that contains the command line arguments used to set the corresponding settings in
-     * the core engine.
+     * @param cli a reference to the CLI Parser that contains the command line
+     * arguments used to set the corresponding settings in the core engine.
+     *
+     * @throws InvalidSettingException thrown when a user defined properties
+     * file is unable to be loaded.
      */
-    private void populateSettings(CliParser cli) {
-
+    private void populateSettings(CliParser cli) throws InvalidSettingException {
         final boolean autoUpdate = cli.isAutoUpdate();
         final String connectionTimeout = cli.getConnectionTimeout();
         final String proxyServer = cli.getProxyServer();
@@ -286,11 +352,9 @@ public class App {
             try {
                 Settings.mergeProperties(propertiesFile);
             } catch (FileNotFoundException ex) {
-                LOGGER.error("Unable to load properties file '{}'", propertiesFile.getPath());
-                LOGGER.debug("", ex);
+                throw new InvalidSettingException("Unable to find properties file '" + propertiesFile.getPath() + "'", ex);
             } catch (IOException ex) {
-                LOGGER.error("Unable to find properties file '{}'", propertiesFile.getPath());
-                LOGGER.debug("", ex);
+                throw new InvalidSettingException("Error reading properties file '" + propertiesFile.getPath() + "'", ex);
             }
         }
         // We have to wait until we've merged the properties before attempting to set whether we use
@@ -385,15 +449,16 @@ public class App {
     }
 
     /**
-     * Takes a path and resolves it to be a canonical & absolute path. The caveats are that this method will take an Ant style
-     * file selector path (../someDir/**\/*.jar) and convert it to an absolute/canonical path (at least to the left of the first *
-     * or ?).
+     * Takes a path and resolves it to be a canonical & absolute path. The
+     * caveats are that this method will take an Ant style file selector path
+     * (../someDir/**\/*.jar) and convert it to an absolute/canonical path (at
+     * least to the left of the first * or ?).
      *
      * @param path the path to canonicalize
      * @return the canonical path
      */
     protected String ensureCanonicalPath(String path) {
-        String basePath = null;
+        String basePath;
         String wildCards = null;
         final String file = path.replace('\\', '/');
         if (file.contains("*") || file.contains("?")) {
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java
index 824f5103a..82e60467b 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java
@@ -359,12 +359,12 @@ public class Engine implements FileFilter {
             LOGGER.error("{}\n\nUnable to continue dependency-check analysis.", ex.getMessage());
             LOGGER.debug("", ex);
             exceptions.add(ex);
-            throw new ExceptionCollection(exceptions, true);
+            throw new ExceptionCollection("Unable to continue dependency-check analysis.",exceptions, true);
         } catch (DatabaseException ex) {
             LOGGER.error("{}\n\nUnable to continue dependency-check analysis.", ex.getMessage());
             LOGGER.debug("", ex);
             exceptions.add(ex);
-            throw new ExceptionCollection(exceptions, true);
+            throw new ExceptionCollection("Unable to connect to the dependency-check database", exceptions, true);
         }
 
         LOGGER.debug("\n----------------------------------------------------\nBEGIN ANALYSIS\n----------------------------------------------------");
@@ -424,7 +424,7 @@ public class Engine implements FileFilter {
         LOGGER.debug("\n----------------------------------------------------\nEND ANALYSIS\n----------------------------------------------------");
         LOGGER.info("Analysis Complete ({} ms)", System.currentTimeMillis() - analysisStart);
         if (exceptions.size() > 0) {
-            throw new ExceptionCollection(exceptions);
+            throw new ExceptionCollection("One or more exceptions occured during dependency-check analysis", exceptions);
         }
     }
 
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java
index 67e426a0d..1d7c65afc 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java
@@ -17,6 +17,8 @@
  */
 package org.owasp.dependencycheck.exception;
 
+import java.io.PrintStream;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -36,6 +38,18 @@ public class ExceptionCollection extends Exception {
         super();
         this.exceptions = exceptions;
     }
+
+    /**
+     * Instantiates a new exception collection.
+     *
+     * @param msg the exception message
+     * @param exceptions a list of exceptions
+     */
+    public ExceptionCollection(String msg, List exceptions) {
+        super(msg);
+        this.exceptions = exceptions;
+    }
+
     /**
      * Instantiates a new exception collection.
      *
@@ -48,7 +62,22 @@ public class ExceptionCollection extends Exception {
         this.exceptions = exceptions;
         this.fatal = fatal;
     }
-        /**
+
+    /**
+     * Instantiates a new exception collection.
+     *
+     * @param msg the exception message
+     * @param exceptions a list of exceptions
+     * @param fatal indicates if the exception that occurred is fatal - meaning
+     * that no analysis was performed.
+     */
+    public ExceptionCollection(String msg, List exceptions, boolean fatal) {
+        super(msg);
+        this.exceptions = exceptions;
+        this.fatal = fatal;
+    }
+
+    /**
      * Instantiates a new exception collection.
      *
      * @param exceptions a list of exceptions
@@ -60,6 +89,18 @@ public class ExceptionCollection extends Exception {
         this.exceptions.add(exceptions);
         this.fatal = fatal;
     }
+        /**
+     * Instantiates a new exception collection.
+     *
+     * @param msg the exception message
+     * @param exception a list of exceptions
+     */
+    public ExceptionCollection(String msg, Throwable exception) {
+        super(msg);
+        this.exceptions.add(exception);
+        this.fatal = false;
+    }
+
     /**
      * Instantiates a new exception collection.
      */
@@ -94,7 +135,8 @@ public class ExceptionCollection extends Exception {
     public void addException(Throwable ex) {
         this.exceptions.add(ex);
     }
-        /**
+
+    /**
      * Adds an exception to the collection.
      *
      * @param ex the exception to add
@@ -105,8 +147,8 @@ public class ExceptionCollection extends Exception {
     }
 
     /**
-     * Flag indicating if a fatal exception occurred that would prevent the attempt
-     * at completing the analysis even if exceptions occurred.
+     * Flag indicating if a fatal exception occurred that would prevent the
+     * attempt at completing the analysis even if exceptions occurred.
      */
     private boolean fatal = false;
 
@@ -128,4 +170,42 @@ public class ExceptionCollection extends Exception {
         this.fatal = fatal;
     }
 
+    /**
+     * Prints the stack trace.
+     *
+     * @param s the writer to print to
+     */
+    @Override
+    public void printStackTrace(PrintWriter s) {
+        s.println("Multiple Exceptions Occured");
+        super.printStackTrace(s);
+        for (Throwable t : this.exceptions) {
+            s.println("Next Exception:");
+            t.printStackTrace(s);
+        }
+    }
+
+    /**
+     * Prints the stack trace.
+     *
+     * @param s the stream to write the stack trace to
+     */
+    @Override
+    public void printStackTrace(PrintStream s) {
+        s.println("Multiple Exceptions Occured");
+        super.printStackTrace(s);
+        for (Throwable t : this.exceptions) {
+            s.println("Next Exception:");
+            t.printStackTrace(s);
+        }
+    }
+
+    /**
+     * Prints the stack trace to standard error.
+     */
+    @Override
+    public void printStackTrace() {
+        this.printStackTrace(System.err);
+    }
+
 }
diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java
index f801f000d..4b1d35b42 100644
--- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java
+++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java
@@ -25,6 +25,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Set;
+import org.apache.maven.MavenExecutionException;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugins.annotations.LifecyclePhase;
@@ -36,11 +37,13 @@ import org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer;
 import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
 import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
 import org.owasp.dependencycheck.dependency.Dependency;
+import org.owasp.dependencycheck.exception.ExceptionCollection;
+import org.owasp.dependencycheck.exception.ReportException;
 import org.owasp.dependencycheck.utils.Settings;
 
 /**
- * Maven Plugin that checks project dependencies and the dependencies of all child modules to see if they have any known published
- * vulnerabilities.
+ * Maven Plugin that checks project dependencies and the dependencies of all
+ * child modules to see if they have any known published vulnerabilities.
  *
  * @author Jeremy Long
  */
@@ -55,18 +58,27 @@ import org.owasp.dependencycheck.utils.Settings;
 public class AggregateMojo extends BaseDependencyCheckMojo {
 
     /**
-     * Executes the aggregate dependency-check goal. This runs dependency-check and generates the subsequent reports.
+     * The key to store aggregate exception in the root Maven execution context.
+     */
+    private static final String AGGREGATE_EXCEPTIONS = "AggregateExceptions";
+
+    /**
+     * Executes the aggregate dependency-check goal. This runs dependency-check
+     * and generates the subsequent reports.
      *
-     * @throws MojoExecutionException thrown if there is ane exception running the mojo
-     * @throws MojoFailureException thrown if dependency-check is configured to fail the build
+     * @throws MojoExecutionException thrown if there is ane exception running
+     * the mojo
+     * @throws MojoFailureException thrown if dependency-check is configured to
+     * fail the build
      */
     @Override
     public void runCheck() throws MojoExecutionException, MojoFailureException {
-        final Engine engine = generateDataFile();
+        final MavenEngine engine = generateDataFile();
+        if (engine == null) {
+            return;
+        }
 
-        //if (getProject() == getReactorProjects().get(getReactorProjects().size() - 1)) {
         if (getProject() == getLastProject()) {
-
             //ensure that the .ser file was created for each.
             for (MavenProject current : getReactorProjects()) {
                 final File dataFile = getDataFile(current);
@@ -76,7 +88,6 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
                     generateDataFile(engine, current);
                 }
             }
-
             for (MavenProject current : getReactorProjects()) {
                 List dependencies = readDataFile(current);
                 if (dependencies == null) {
@@ -90,10 +101,8 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
                             getLog().debug(String.format("Adding %d dependencies from %s", childDeps.size(), reportOn.getName()));
                         }
                         dependencies.addAll(childDeps);
-                    } else {
-                        if (getLog().isDebugEnabled()) {
-                            getLog().debug(String.format("No dependencies read for %s", reportOn.getName()));
-                        }
+                    } else if (getLog().isDebugEnabled()) {
+                        getLog().debug(String.format("No dependencies read for %s", reportOn.getName()));
                     }
                 }
                 engine.getDependencies().clear();
@@ -118,7 +127,21 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
                     //we shouldn't write this because nothing is configured to generate this report.
                     outputDir = new File(current.getBuild().getDirectory());
                 }
-                writeReports(engine, current, outputDir);
+                try {
+                    writeReports(engine, current, outputDir);
+                } catch (ReportException ex) {
+                    ExceptionCollection exCol =  (ExceptionCollection) engine.getExecutionRoot().getContextValue(AGGREGATE_EXCEPTIONS);
+                    if (exCol == null) {
+                        exCol = new ExceptionCollection("Error writing aggregate report",ex);
+                    } else {
+                        exCol.addException(ex);
+                    }
+                    if (this.isFailOnError()) {
+                        throw new MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol);
+                    } else {
+                        getLog().debug("One or more exceptions occured during dependency-check analysis", exCol);
+                    }
+                }
             }
         }
         engine.cleanup();
@@ -126,7 +149,8 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
     }
 
     /**
-     * Gets the last project in the reactor - taking into account skipped projects.
+     * Gets the last project in the reactor - taking into account skipped
+     * projects.
      *
      * @return the last project in the reactor
      */
@@ -152,7 +176,8 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
     }
 
     /**
-     * Returns a set containing all the descendant projects of the given project.
+     * Returns a set containing all the descendant projects of the given
+     * project.
      *
      * @param project the project for which all descendants will be returned
      * @return the set of descendant projects
@@ -232,49 +257,85 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
      * Test if the project has pom packaging
      *
      * @param mavenProject Project to test
-     * @return true if it has a pom packaging; otherwise false
+     * @return true if it has a pom packaging; otherwise
+     * false
      */
     protected boolean isMultiModule(MavenProject mavenProject) {
         return "pom".equals(mavenProject.getPackaging());
     }
 
     /**
-     * Initializes the engine, runs a scan, and writes the serialized dependencies to disk.
+     * Initializes the engine, runs a scan, and writes the serialized
+     * dependencies to disk.
      *
-     * @return the Engine used to execute dependency-check
-     * @throws MojoExecutionException thrown if there is an exception running the mojo
-     * @throws MojoFailureException thrown if dependency-check is configured to fail the build if severe CVEs are identified.
+     * @return the MavenEngine used to execute dependency-check
+     * @throws MojoExecutionException thrown if there is an exception running
+     * the mojo
+     * @throws MojoFailureException thrown if dependency-check is configured to
+     * fail the build if severe CVEs are identified.
      */
-    protected Engine generateDataFile() throws MojoExecutionException, MojoFailureException {
-        final Engine engine;
+    protected MavenEngine generateDataFile() throws MojoExecutionException, MojoFailureException {
+        MavenEngine engine = null;
         try {
             engine = initializeEngine();
         } catch (DatabaseException ex) {
             if (getLog().isDebugEnabled()) {
                 getLog().debug("Database connection error", ex);
             }
-            throw new MojoExecutionException("An exception occured connecting to the local database. Please see the log file for more details.", ex);
+            final String msg = "An exception occured connecting to the local database. Please see the log file for more details.";
+            if (this.isFailOnError()) {
+                throw new MojoExecutionException(msg, ex);
+            }
+            getLog().error(msg, ex);
+            return null;
         }
         return generateDataFile(engine, getProject());
     }
 
     /**
-     * Runs dependency-check's Engine and writes the serialized dependencies to disk.
+     * Runs dependency-check's MavenEngine and writes the serialized
+     * dependencies to disk.
      *
-     * @param engine the Engine to use when scanning.
+     * @param engine the MavenEngine to use when scanning.
      * @param project the project to scan and generate the data file for
-     * @return the Engine used to execute dependency-check
-     * @throws MojoExecutionException thrown if there is an exception running the mojo
-     * @throws MojoFailureException thrown if dependency-check is configured to fail the build if severe CVEs are identified.
+     * @return the MavenEngine used to execute dependency-check
+     * @throws MojoExecutionException thrown if there is an exception running
+     * the mojo
+     * @throws MojoFailureException thrown if dependency-check is configured to
+     * fail the build if severe CVEs are identified.
      */
-    protected Engine generateDataFile(Engine engine, MavenProject project) throws MojoExecutionException, MojoFailureException {
+    protected MavenEngine generateDataFile(MavenEngine engine, MavenProject project) throws MojoExecutionException, MojoFailureException {
         if (getLog().isDebugEnabled()) {
             getLog().debug(String.format("Begin Scanning: %s", project.getName()));
         }
         engine.getDependencies().clear();
         engine.resetFileTypeAnalyzers();
         scanArtifacts(project, engine);
-        engine.analyzeDependencies();
+        try {
+            engine.analyzeDependencies();
+        } catch (ExceptionCollection ex) {
+            ExceptionCollection col = (ExceptionCollection) engine.getExecutionRoot().getContextValue(AGGREGATE_EXCEPTIONS);
+            if (col == null) {
+                col = ex;
+            } else if (ex.isFatal()) {
+                col.setFatal(true);
+                col.getExceptions().addAll(ex.getExceptions());
+            }
+            if (col.isFatal()) {
+                final String msg = String.format("Fatal exception(s) analyzing %s", project.getName());
+                if (this.isFailOnError()) {
+                    throw new MojoExecutionException(msg, ex);
+                }
+                getLog().error(msg, col);
+                return null;
+            } else {
+                final String msg = String.format("Exception(s) analyzing %s", project.getName());
+                if (getLog().isDebugEnabled()) {
+                    getLog().debug(msg, ex);
+                }
+                engine.getExecutionRoot().setContextValue(AGGREGATE_EXCEPTIONS, col);
+            }
+        }
         final File target = new File(project.getBuild().getDirectory());
         writeDataFile(project, target, engine.getDependencies());
         showSummary(project, engine.getDependencies());
@@ -306,7 +367,8 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
     }
 
     /**
-     * Gets the description of the Dependency-Check report to be displayed in the Maven Generated Reports page.
+     * Gets the description of the Dependency-Check report to be displayed in
+     * the Maven Generated Reports page.
      *
      * @param locale The Locale to get the description for
      * @return the description
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 aff052420..8869a35ed 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
@@ -47,6 +47,7 @@ import org.owasp.dependencycheck.dependency.Confidence;
 import org.owasp.dependencycheck.dependency.Dependency;
 import org.owasp.dependencycheck.dependency.Identifier;
 import org.owasp.dependencycheck.dependency.Vulnerability;
+import org.owasp.dependencycheck.exception.ReportException;
 import org.owasp.dependencycheck.reporting.ReportGenerator;
 import org.owasp.dependencycheck.utils.ExpectedOjectInputStream;
 import org.owasp.dependencycheck.utils.Settings;
@@ -69,14 +70,27 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
      * System specific new line character.
      */
     private static final String NEW_LINE = System.getProperty("line.separator", "\n").intern();
+    //
+    // 
     /**
      * Sets whether or not the external report format should be used.
      */
     @Parameter(property = "metaFileName", defaultValue = "dependency-check.ser", required = true)
     private String dataFileName;
+    /**
+     * Sets whether or not the external report format should be used.
+     */
+    @Parameter(property = "failOnError", defaultValue = "true", required = true)
+    private boolean failOnError;
 
-    //
-    // 
+    /**
+     * Returns if the mojo should fail the build if an exception occurs.
+     * @return whether or not the mojo should fail the build
+     */
+    protected boolean isFailOnError() {
+        return failOnError;
+    }
+    
     /**
      * The Maven Project Object.
      */
@@ -111,13 +125,11 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
      * Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not
      * recommended that this be turned to false. Default is true.
      */
-    @SuppressWarnings("CanBeFinal")
     @Parameter(property = "autoUpdate")
     private Boolean autoUpdate;
     /**
      * Sets whether Experimental analyzers are enabled. Default is false.
      */
-    @SuppressWarnings("CanBeFinal")
     @Parameter(property = "enableExperimental")
     private Boolean enableExperimental;
     /**
@@ -145,7 +157,6 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
     /**
      * The maven settings proxy id.
      */
-    @SuppressWarnings("CanBeFinal")
     @Parameter(property = "mavenSettingsProxyId", required = false)
     private String mavenSettingsProxyId;
 
@@ -162,6 +173,7 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
     /**
      * Flag indicating whether or not to show a summary in the output.
      */
+    @SuppressWarnings("CanBeFinal")
     @Parameter(property = "showSummary", defaultValue = "true", required = false)
     private boolean showSummary = true;
 
@@ -541,7 +553,7 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
      * @param project the project to scan the dependencies of
      * @param engine the engine to use to scan the dependencies
      */
-    protected void scanArtifacts(MavenProject project, Engine engine) {
+    protected void scanArtifacts(MavenProject project, MavenEngine engine) {
         for (Artifact a : project.getArtifacts()) {
             if (excludeFromScan(a)) {
                 continue;
@@ -649,14 +661,14 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
     //
 
     /**
-     * Initializes a new Engine that can be used for scanning.
+     * Initializes a new MavenEngine that can be used for scanning.
      *
-     * @return a newly instantiated Engine
+     * @return a newly instantiated MavenEngine
      * @throws DatabaseException thrown if there is a database exception
      */
-    protected Engine initializeEngine() throws DatabaseException {
+    protected MavenEngine initializeEngine() throws DatabaseException {
         populateSettings();
-        return new Engine(this.project,
+        return new MavenEngine(this.project,
                 this.reactorProjects);
     }
 
@@ -875,10 +887,11 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
      * Generates the reports for a given dependency-check engine.
      *
      * @param engine a dependency-check engine
-     * @param p the maven project
-     * @param outputDir the directory path to write the report(s).
+     * @param p the Maven project
+     * @param outputDir the directory path to write the report(s)
+     * @throws ReportException thrown if there is an error writing the report
      */
-    protected void writeReports(Engine engine, MavenProject p, File outputDir) {
+    protected void writeReports(MavenEngine engine, MavenProject p, File outputDir) throws ReportException {
         DatabaseProperties prop = null;
         CveDB cve = null;
         try {
@@ -897,19 +910,11 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
         final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop);
         try {
             r.generateReports(outputDir.getAbsolutePath(), format);
-        } catch (IOException ex) {
-            getLog().error(
-                    "Unexpected exception occurred during analysis; please see the verbose error log for more details.");
-            if (getLog().isDebugEnabled()) {
-                getLog().debug("", ex);
-            }
-        } catch (Throwable ex) {
-            getLog().error(
-                    "Unexpected exception occurred during analysis; please see the verbose error log for more details.");
-            if (getLog().isDebugEnabled()) {
-                getLog().debug("", ex);
-            }
+        } catch (ReportException ex) {
+            final String msg = String.format("Error generating the report for %s", p.getName());
+            throw new ReportException(msg, ex);
         }
+
     }
 
     //
@@ -1074,7 +1079,7 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
      * scan data between the "check" and "aggregate" phase.
      *
      * @param project the Maven project to read the data file from
-     * @return a Engine object populated with dependencies if the
+     * @return a MavenEngine object populated with dependencies if the
      * serialized data file exists; otherwise null is returned
      */
     protected List readDataFile(MavenProject project) {
diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java
index 17ba52bf1..270ceba39 100644
--- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java
+++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java
@@ -26,10 +26,13 @@ import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
+import org.owasp.dependencycheck.exception.ExceptionCollection;
+import org.owasp.dependencycheck.exception.ReportException;
 import org.owasp.dependencycheck.utils.Settings;
 
 /**
- * Maven Plugin that checks the project dependencies to see if they have any known published vulnerabilities.
+ * Maven Plugin that checks the project dependencies to see if they have any
+ * known published vulnerabilities.
  *
  * @author Jeremy Long
  */
@@ -45,7 +48,8 @@ public class CheckMojo extends BaseDependencyCheckMojo {
     /**
      * Returns whether or not a the report can be generated.
      *
-     * @return true if the report can be generated; otherwise false
+     * @return true if the report can be generated; otherwise
+     * false
      */
     @Override
     public boolean canGenerateReport() {
@@ -60,33 +64,65 @@ public class CheckMojo extends BaseDependencyCheckMojo {
     }
 
     /**
-     * Executes the dependency-check engine on the project's dependencies and generates the report.
+     * Executes the dependency-check engine on the project's dependencies and
+     * generates the report.
      *
-     * @throws MojoExecutionException thrown if there is an exception executing the goal
-     * @throws MojoFailureException thrown if dependency-check is configured to fail the build
+     * @throws MojoExecutionException thrown if there is an exception executing
+     * the goal
+     * @throws MojoFailureException thrown if dependency-check is configured to
+     * fail the build
      */
     @Override
     public void runCheck() throws MojoExecutionException, MojoFailureException {
-        final Engine engine;
+        MavenEngine engine = null;
         try {
             engine = initializeEngine();
         } catch (DatabaseException ex) {
             if (getLog().isDebugEnabled()) {
                 getLog().debug("Database connection error", ex);
             }
-            throw new MojoExecutionException("An exception occured connecting to the local database. Please see the log file for more details.", ex);
+            final String msg = "An exception occured connecting to the local database. Please see the log file for more details.";
+            if (this.isFailOnError()) {
+                throw new MojoExecutionException(msg, ex);
+            }
+            getLog().error(msg);
         }
-        scanArtifacts(getProject(), engine);
-        if (engine.getDependencies().isEmpty()) {
-            getLog().info("No dependencies were identified that could be analyzed by dependency-check");
-        } else {
-            engine.analyzeDependencies();
-            writeReports(engine, getProject(), getCorrectOutputDirectory());
-            writeDataFile(getProject(), null, engine.getDependencies());
-            showSummary(getProject(), engine.getDependencies());
-            checkForFailure(engine.getDependencies());
+        if (engine != null) {
+            scanArtifacts(getProject(), engine);
+            if (engine.getDependencies().isEmpty()) {
+                getLog().info("No dependencies were identified that could be analyzed by dependency-check");
+            } else {
+                ExceptionCollection exCol = null;
+                try {
+                    engine.analyzeDependencies();
+                } catch (ExceptionCollection ex) {
+                    if (this.isFailOnError() && ex.isFatal()) {
+                        throw new MojoExecutionException("One or more exceptions occured during analysis", ex);
+                    }
+                    exCol = ex;
+                }
+                if (exCol == null || !exCol.isFatal()) {
+                    try {
+                        writeReports(engine, getProject(), getCorrectOutputDirectory());
+                    } catch (ReportException ex) {
+                        if (this.isFailOnError()) {
+                            if (exCol!= null) {
+                                exCol.addException(ex);
+                            } else {
+                                exCol = new ExceptionCollection("Unable to write the dependency-check report", ex);
+                            }
+                        }
+                    }
+                    writeDataFile(getProject(), null, engine.getDependencies());
+                    showSummary(getProject(), engine.getDependencies());
+                    checkForFailure(engine.getDependencies());
+                    if (exCol != null && this.isFailOnError()) {
+                        throw new MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol);
+                    }
+                }
+            }
+            engine.cleanup();
         }
-        engine.cleanup();
         Settings.cleanup();
     }
 
@@ -109,7 +145,8 @@ public class CheckMojo extends BaseDependencyCheckMojo {
     }
 
     /**
-     * Gets the description of the Dependency-Check report to be displayed in the Maven Generated Reports page.
+     * Gets the description of the Dependency-Check report to be displayed in
+     * the Maven Generated Reports page.
      *
      * @param locale The Locale to get the description for
      * @return the description
diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/Engine.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/MavenEngine.java
similarity index 96%
rename from dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/Engine.java
rename to dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/MavenEngine.java
index b691ccde5..9edf53ae4 100644
--- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/Engine.java
+++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/MavenEngine.java
@@ -36,12 +36,12 @@ import org.slf4j.LoggerFactory;
  *
  * @author Jeremy Long
  */
-public class Engine extends org.owasp.dependencycheck.Engine {
+public class MavenEngine extends org.owasp.dependencycheck.Engine {
 
     /**
      * The logger.
      */
-    private static final transient Logger LOGGER = LoggerFactory.getLogger(Engine.class);
+    private static final transient Logger LOGGER = LoggerFactory.getLogger(MavenEngine.class);
     /**
      * A key used to persist an object in the MavenProject.
      */
@@ -69,7 +69,7 @@ public class Engine extends org.owasp.dependencycheck.Engine {
      * @throws DatabaseException thrown if there is an issue connecting to the
      * database
      */
-    public Engine(MavenProject project, List reactorProjects) throws DatabaseException {
+    public MavenEngine(MavenProject project, List reactorProjects) throws DatabaseException {
         this.currentProject = project;
         this.reactorProjects = reactorProjects;
         initializeEngine();
@@ -117,7 +117,7 @@ public class Engine extends org.owasp.dependencycheck.Engine {
      * @throws DatabaseException thrown if there is an issue connecting to the
      * database
      */
-    private Engine() throws DatabaseException {
+    private MavenEngine() throws DatabaseException {
     }
 
     /**
@@ -208,7 +208,7 @@ public class Engine extends org.owasp.dependencycheck.Engine {
      *
      * @return the root Maven Project
      */
-    private MavenProject getExecutionRoot() {
+    MavenProject getExecutionRoot() {
         if (reactorProjects == null) {
             return null;
         }
diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/PurgeMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/PurgeMojo.java
index 2075a2c0c..62c14a0dd 100644
--- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/PurgeMojo.java
+++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/PurgeMojo.java
@@ -54,14 +54,20 @@ public class PurgeMojo extends BaseDependencyCheckMojo {
     /**
      * Purges the local copy of the NVD.
      *
-     * @throws MojoExecutionException thrown if there is an exception executing the goal
-     * @throws MojoFailureException thrown if dependency-check is configured to fail the build
+     * @throws MojoExecutionException thrown if there is an exception executing
+     * the goal
+     * @throws MojoFailureException thrown if dependency-check is configured to
+     * fail the build
      */
     @Override
     public void runCheck() throws MojoExecutionException, MojoFailureException {
 
         if (getConnectionString() != null && !getConnectionString().isEmpty()) {
-            getLog().error("Unable to purge the local NVD when using a non-default connection string");
+            final String msg = "Unable to purge the local NVD when using a non-default connection string";
+            if (this.isFailOnError()) {
+                throw new MojoFailureException(msg);
+            }
+            getLog().error(msg);
         } else {
             populateSettings();
             File db;
@@ -71,13 +77,25 @@ public class PurgeMojo extends BaseDependencyCheckMojo {
                     if (db.delete()) {
                         getLog().info("Database file purged; local copy of the NVD has been removed");
                     } else {
-                        getLog().error(String.format("Unable to delete '%s'; please delete the file manually", db.getAbsolutePath()));
+                        final String msg = String.format("Unable to delete '%s'; please delete the file manually", db.getAbsolutePath());
+                        if (this.isFailOnError()) {
+                            throw new MojoFailureException(msg);
+                        }
+                        getLog().error(msg);
                     }
                 } else {
-                    getLog().error(String.format("Unable to purge database; the database file does not exists: %s", db.getAbsolutePath()));
+                    final String msg = String.format("Unable to purge database; the database file does not exists: %s", db.getAbsolutePath());
+                    if (this.isFailOnError()) {
+                        throw new MojoFailureException(msg);
+                    }
+                    getLog().error(msg);
                 }
             } catch (IOException ex) {
-                getLog().error("Unable to delete the database");
+                final String msg = "Unable to delete the database";
+                if (this.isFailOnError()) {
+                    throw new MojoExecutionException(msg, ex);
+                }
+                getLog().error(msg);
             }
             Settings.cleanup();
         }
@@ -95,7 +113,8 @@ public class PurgeMojo extends BaseDependencyCheckMojo {
     }
 
     /**
-     * Gets the description of the Dependency-Check report to be displayed in the Maven Generated Reports page.
+     * Gets the description of the Dependency-Check report to be displayed in
+     * the Maven Generated Reports page.
      *
      * @param locale The Locale to get the description for
      * @return the description
diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/UpdateMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/UpdateMojo.java
index 8bb457b9b..33f8f172d 100644
--- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/UpdateMojo.java
+++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/UpdateMojo.java
@@ -24,10 +24,12 @@ import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
+import org.owasp.dependencycheck.data.update.exception.UpdateException;
 import org.owasp.dependencycheck.utils.Settings;
 
 /**
- * Maven Plugin that checks the project dependencies to see if they have any known published vulnerabilities.
+ * Maven Plugin that checks the project dependencies to see if they have any
+ * known published vulnerabilities.
  *
  * @author Jeremy Long
  */
@@ -51,14 +53,17 @@ public class UpdateMojo extends BaseDependencyCheckMojo {
     }
 
     /**
-     * Executes the dependency-check engine on the project's dependencies and generates the report.
+     * Executes the dependency-check engine on the project's dependencies and
+     * generates the report.
      *
-     * @throws MojoExecutionException thrown if there is an exception executing the goal
-     * @throws MojoFailureException thrown if dependency-check is configured to fail the build
+     * @throws MojoExecutionException thrown if there is an exception executing
+     * the goal
+     * @throws MojoFailureException thrown if dependency-check is configured to
+     * fail the build
      */
     @Override
     public void runCheck() throws MojoExecutionException, MojoFailureException {
-        final Engine engine;
+        MavenEngine engine = null;
         try {
             engine = initializeEngine();
             engine.update();
@@ -66,9 +71,21 @@ public class UpdateMojo extends BaseDependencyCheckMojo {
             if (getLog().isDebugEnabled()) {
                 getLog().debug("Database connection error", ex);
             }
-            throw new MojoExecutionException("An exception occured connecting to the local database. Please see the log file for more details.", ex);
+            final String msg = "An exception occured connecting to the local database. Please see the log file for more details.";
+            if (this.isFailOnError()) {
+                throw new MojoExecutionException(msg, ex);
+            }
+            getLog().error(msg);
+        } catch (UpdateException ex) {
+            final String msg = "An exception occured while downloading updates. Please see the log file for more details.";
+            if (this.isFailOnError()) {
+                throw new MojoExecutionException(msg, ex);
+            }
+            getLog().error(msg);
+        }
+        if (engine != null) {
+            engine.cleanup();
         }
-        engine.cleanup();
         Settings.cleanup();
     }
 
@@ -84,7 +101,8 @@ public class UpdateMojo extends BaseDependencyCheckMojo {
     }
 
     /**
-     * Gets the description of the Dependency-Check report to be displayed in the Maven Generated Reports page.
+     * Gets the description of the Dependency-Check report to be displayed in
+     * the Maven Generated Reports page.
      *
      * @param locale The Locale to get the description for
      * @return the description
@@ -93,5 +111,5 @@ public class UpdateMojo extends BaseDependencyCheckMojo {
     public String getDescription(Locale locale) {
         return "Updates the local cache of the NVD data from NIST.";
     }
-
+    
 }
diff --git a/dependency-check-maven/src/site/markdown/configuration.md b/dependency-check-maven/src/site/markdown/configuration.md
index 44b68a512..2707e091c 100644
--- a/dependency-check-maven/src/site/markdown/configuration.md
+++ b/dependency-check-maven/src/site/markdown/configuration.md
@@ -17,6 +17,7 @@ Property             | Description                        | Default Value
 autoUpdate           | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. | true
 cveValidForHours     | Sets the number of hours to wait before checking for new updates from the NVD.                                     | 4
 failBuildOnCVSS      | Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail.         | 11
+failOnError          | Whether the build should fail if there is an error executing the dependency-check analysis | true
 format               | The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the Site plugin unless the externalReport is set to true. | HTML
 name                 | The name of the report in the site | dependency-check or dependency-check:aggregate
 outputDirectory      | The location to write the report(s). Note, this is not used if generating the report as part of a `mvn site` build | 'target'
diff --git a/dependency-check-maven/src/test/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.java b/dependency-check-maven/src/test/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.java
index f66e34939..d103d0d9e 100644
--- a/dependency-check-maven/src/test/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.java
+++ b/dependency-check-maven/src/test/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.java
@@ -90,7 +90,7 @@ public class BaseDependencyCheckMojoTest extends BaseTest {
 
             boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
             Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
-            Engine engine = new Engine(null, null);
+            MavenEngine engine = new MavenEngine(null, null);
             Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
 
             assertTrue(engine.getDependencies().isEmpty());

From 57fcf6fde31314f0f9f10f221eb2dbeeb265f1e9 Mon Sep 17 00:00:00 2001
From: Jeremy Long 
Date: Sun, 17 Jul 2016 08:18:47 -0400
Subject: [PATCH 03/30] testing connection errors

---
 .../main/java/org/owasp/dependencycheck/utils/Downloader.java | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Downloader.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Downloader.java
index 850a302e7..7709f2d83 100644
--- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Downloader.java
+++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Downloader.java
@@ -262,9 +262,9 @@ public final class Downloader {
                 throw new DownloadFailedException(format("Error creating URL Connection for HTTP %s request.", httpMethod), ex);
             } catch (IOException ex) {
                 checkForSslExceptionn(ex);
-                LOGGER.debug("IO Exception: " + ex.getMessage(), ex);
+                LOGGER.error("IO Exception: " + ex.getMessage(), ex);
                 if (ex.getCause() != null) {
-                    LOGGER.debug("IO Exception cause: " + ex.getCause().getMessage(), ex.getCause());
+                    LOGGER.error("IO Exception cause: " + ex.getCause().getMessage(), ex.getCause());
                 }
                 try {
                     //retry

From af12a2161c5af0d44316ecda15010f6b34fbb7b0 Mon Sep 17 00:00:00 2001
From: Jeremy Long 
Date: Tue, 19 Jul 2016 06:54:25 -0400
Subject: [PATCH 04/30] testing fix to resolve connection issues with NVD

---
 .../utils/SSLSocketFactoryEx.java             | 243 ++++++++++++++++++
 .../utils/URLConnectionFactory.java           |  41 ++-
 2 files changed, 278 insertions(+), 6 deletions(-)
 create mode 100644 dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java

diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java
new file mode 100644
index 000000000..a8f9ec724
--- /dev/null
+++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java
@@ -0,0 +1,243 @@
+package org.owasp.dependencycheck.utils;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+
+/**
+ * The following code was copied from
+ * http://stackoverflow.com/questions/1037590/which-cipher-suites-to-enable-for-ssl-socket/23365536#23365536
+ *
+ */
+class SSLSocketFactoryEx extends SSLSocketFactory {
+
+    public SSLSocketFactoryEx() throws NoSuchAlgorithmException, KeyManagementException {
+        initSSLSocketFactoryEx(null, null, null);
+    }
+
+    public SSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random) throws NoSuchAlgorithmException, KeyManagementException {
+        initSSLSocketFactoryEx(km, tm, random);
+    }
+
+    public SSLSocketFactoryEx(SSLContext ctx) throws NoSuchAlgorithmException, KeyManagementException {
+        initSSLSocketFactoryEx(ctx);
+    }
+
+    @Override
+    public String[] getDefaultCipherSuites() {
+        return m_ciphers;
+    }
+
+    @Override
+    public String[] getSupportedCipherSuites() {
+        return m_ciphers;
+    }
+
+    public String[] getDefaultProtocols() {
+        return m_protocols;
+    }
+
+    public String[] getSupportedProtocols() {
+        return m_protocols;
+    }
+
+    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
+        SSLSocketFactory factory = m_ctx.getSocketFactory();
+        SSLSocket ss = (SSLSocket) factory.createSocket(s, host, port, autoClose);
+
+        ss.setEnabledProtocols(m_protocols);
+        ss.setEnabledCipherSuites(m_ciphers);
+
+        return ss;
+    }
+
+    @Override
+    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
+        SSLSocketFactory factory = m_ctx.getSocketFactory();
+        SSLSocket ss = (SSLSocket) factory.createSocket(address, port, localAddress, localPort);
+
+        ss.setEnabledProtocols(m_protocols);
+        ss.setEnabledCipherSuites(m_ciphers);
+
+        return ss;
+    }
+
+    @Override
+    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
+        SSLSocketFactory factory = m_ctx.getSocketFactory();
+        SSLSocket ss = (SSLSocket) factory.createSocket(host, port, localHost, localPort);
+
+        ss.setEnabledProtocols(m_protocols);
+        ss.setEnabledCipherSuites(m_ciphers);
+
+        return ss;
+    }
+
+    @Override
+    public Socket createSocket(InetAddress host, int port) throws IOException {
+        SSLSocketFactory factory = m_ctx.getSocketFactory();
+        SSLSocket ss = (SSLSocket) factory.createSocket(host, port);
+
+        ss.setEnabledProtocols(m_protocols);
+        ss.setEnabledCipherSuites(m_ciphers);
+
+        return ss;
+    }
+
+    @Override
+    public Socket createSocket(String host, int port) throws IOException {
+        SSLSocketFactory factory = m_ctx.getSocketFactory();
+        SSLSocket ss = (SSLSocket) factory.createSocket(host, port);
+
+        ss.setEnabledProtocols(m_protocols);
+        ss.setEnabledCipherSuites(m_ciphers);
+
+        return ss;
+    }
+
+    private void initSSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random)
+            throws NoSuchAlgorithmException, KeyManagementException {
+        m_ctx = SSLContext.getInstance("TLS");
+        m_ctx.init(km, tm, random);
+
+        m_protocols = GetProtocolList();
+        m_ciphers = GetCipherList();
+    }
+
+    private void initSSLSocketFactoryEx(SSLContext ctx)
+            throws NoSuchAlgorithmException, KeyManagementException {
+        m_ctx = ctx;
+
+        m_protocols = GetProtocolList();
+        m_ciphers = GetCipherList();
+    }
+
+    protected String[] GetProtocolList() {
+        String[] preferredProtocols = {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"};
+        String[] availableProtocols = null;
+
+        SSLSocket socket = null;
+
+        try {
+            SSLSocketFactory factory = m_ctx.getSocketFactory();
+            socket = (SSLSocket) factory.createSocket();
+
+            availableProtocols = socket.getSupportedProtocols();
+            Arrays.sort(availableProtocols);
+        } catch (Exception e) {
+            return new String[]{"TLSv1"};
+        } finally {
+            if (socket != null) {
+                try {
+                    socket.close();
+                } catch (IOException ex) {
+                    //ignore
+                }
+            }
+        }
+
+        List aa = new ArrayList();
+        for (String preferredProtocol : preferredProtocols) {
+            int idx = Arrays.binarySearch(availableProtocols, preferredProtocol);
+            if (idx >= 0) {
+                aa.add(preferredProtocol);
+            }
+        }
+
+        return aa.toArray(new String[0]);
+    }
+
+    protected String[] GetCipherList() {
+        String[] preferredCiphers = {
+            // *_CHACHA20_POLY1305 are 3x to 4x faster than existing cipher suites.
+            //   http://googleonlinesecurity.blogspot.com/2014/04/speeding-up-and-strengthening-https.html
+            // Use them if available. Normative names can be found at (TLS spec depends on IPSec spec):
+            //   http://tools.ietf.org/html/draft-nir-ipsecme-chacha20-poly1305-01
+            //   http://tools.ietf.org/html/draft-mavrogiannopoulos-chacha-tls-02
+            "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
+            "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
+            "TLS_ECDHE_ECDSA_WITH_CHACHA20_SHA",
+            "TLS_ECDHE_RSA_WITH_CHACHA20_SHA",
+            "TLS_DHE_RSA_WITH_CHACHA20_POLY1305",
+            "TLS_RSA_WITH_CHACHA20_POLY1305",
+            "TLS_DHE_RSA_WITH_CHACHA20_SHA",
+            "TLS_RSA_WITH_CHACHA20_SHA",
+            // Done with bleeding edge, back to TLS v1.2 and below
+            "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
+            "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
+            "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
+            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
+            "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+            "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
+            "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+            "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
+            // TLS v1.0 (with some SSLv3 interop)
+            "TLS_DHE_RSA_WITH_AES_256_CBC_SHA384",
+            "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
+            "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+            "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+            "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
+            "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
+            "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA",
+            "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA",
+            // RSA key transport sucks, but they are needed as a fallback.
+            // For example, microsoft.com fails under all versions of TLS
+            // if they are not included. If only TLS 1.0 is available at
+            // the client, then google.com will fail too. TLS v1.3 is
+            // trying to deprecate them, so it will be interesteng to see
+            // what happens.
+            "TLS_RSA_WITH_AES_256_CBC_SHA256",
+            "TLS_RSA_WITH_AES_256_CBC_SHA",
+            "TLS_RSA_WITH_AES_128_CBC_SHA256",
+            "TLS_RSA_WITH_AES_128_CBC_SHA"
+        };
+
+        String[] availableCiphers = null;
+
+        try {
+            SSLSocketFactory factory = m_ctx.getSocketFactory();
+            availableCiphers = factory.getSupportedCipherSuites();
+            Arrays.sort(availableCiphers);
+        } catch (Exception e) {
+            return new String[]{
+                "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+                "TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
+                "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+                "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
+                "TLS_RSA_WITH_AES_256_CBC_SHA256",
+                "TLS_RSA_WITH_AES_256_CBC_SHA",
+                "TLS_RSA_WITH_AES_128_CBC_SHA256",
+                "TLS_RSA_WITH_AES_128_CBC_SHA",
+                "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"
+            };
+        }
+
+        List aa = new ArrayList();
+        for (String preferredCipher : preferredCiphers) {
+            int idx = Arrays.binarySearch(availableCiphers, preferredCipher);
+            if (idx >= 0) {
+                aa.add(preferredCipher);
+            }
+        }
+
+        aa.add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV");
+
+        return aa.toArray(new String[0]);
+    }
+
+    private SSLContext m_ctx;
+
+    private String[] m_ciphers;
+    private String[] m_protocols;
+}
diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java
index cbeb00a64..dca5f0de9 100644
--- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java
+++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java
@@ -28,15 +28,26 @@ import java.net.PasswordAuthentication;
 import java.net.Proxy;
 import java.net.SocketAddress;
 import java.net.URL;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import javax.net.ssl.HttpsURLConnection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
- * A URLConnection Factory to create new connections. This encapsulates several configuration checks to ensure that the connection
- * uses the correct proxy settings.
+ * A URLConnection Factory to create new connections. This encapsulates several
+ * configuration checks to ensure that the connection uses the correct proxy
+ * settings.
  *
  * @author Jeremy Long
  */
 public final class URLConnectionFactory {
 
+    /**
+     * The logger.
+     */
+    private static final Logger LOGGER = LoggerFactory.getLogger(URLConnectionFactory.class);
+
     /**
      * Private constructor for this factory.
      */
@@ -44,8 +55,9 @@ public final class URLConnectionFactory {
     }
 
     /**
-     * Utility method to create an HttpURLConnection. If the application is configured to use a proxy this method will retrieve
-     * the proxy settings and use them when setting up the connection.
+     * Utility method to create an HttpURLConnection. If the application is
+     * configured to use a proxy this method will retrieve the proxy settings
+     * and use them when setting up the connection.
      *
      * @param url the url to connect to
      * @return an HttpURLConnection
@@ -140,8 +152,10 @@ public final class URLConnectionFactory {
     }
 
     /**
-     * Utility method to create an HttpURLConnection. The use of a proxy here is optional as there may be cases where a proxy is
-     * configured but we don't want to use it (for example, if there's an internal repository configured)
+     * Utility method to create an HttpURLConnection. The use of a proxy here is
+     * optional as there may be cases where a proxy is configured but we don't
+     * want to use it (for example, if there's an internal repository
+     * configured)
      *
      * @param url the URL to connect to
      * @param proxy whether to use the proxy (if configured)
@@ -161,6 +175,21 @@ public final class URLConnectionFactory {
         } catch (IOException ioe) {
             throw new URLConnectionFailureException("Error getting connection.", ioe);
         }
+        ConfigureTLS(url, conn);
         return conn;
     }
+
+    private static void ConfigureTLS(URL url, HttpURLConnection conn) {
+        if ("https".equals(url.getProtocol())) {
+            try {
+                HttpsURLConnection secCon = (HttpsURLConnection) conn;
+                SSLSocketFactoryEx factory = new SSLSocketFactoryEx();
+                secCon.setSSLSocketFactory(factory);
+            } catch (NoSuchAlgorithmException ex) {
+                LOGGER.debug("Unsupported algorithm in SSLSocketFactoryEx", ex);
+            } catch (KeyManagementException ex) {
+                LOGGER.debug("Key mnagement eception in SSLSocketFactoryEx", ex);
+            }
+        }
+    }
 }

From 034bd4dba045bc03913c0b8c98e20b77ee7a4686 Mon Sep 17 00:00:00 2001
From: Jeremy Long 
Date: Tue, 19 Jul 2016 07:04:24 -0400
Subject: [PATCH 05/30] testing fix to resolve connection issues with NVD

---
 .../org/owasp/dependencycheck/utils/URLConnectionFactory.java    | 1 +
 1 file changed, 1 insertion(+)

diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java
index dca5f0de9..84d6e18e6 100644
--- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java
+++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java
@@ -107,6 +107,7 @@ public final class URLConnectionFactory {
             }
             throw new URLConnectionFailureException("Error getting connection.", ex);
         }
+        ConfigureTLS(url, conn);
         return conn;
     }
 

From 7cf040653f4087740fa0ab6786b67be960af8f3c Mon Sep 17 00:00:00 2001
From: Jeremy Long 
Date: Fri, 22 Jul 2016 06:29:01 -0400
Subject: [PATCH 06/30] upgraded h2 db version

---
 .../src/main/resources/dependencycheck.properties               | 2 +-
 .../src/test/resources/dependencycheck.properties               | 2 +-
 .../src/test/resources/dependencycheck.properties               | 2 +-
 pom.xml                                                         | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/dependency-check-core/src/main/resources/dependencycheck.properties b/dependency-check-core/src/main/resources/dependencycheck.properties
index def5b8d86..023b7cf1f 100644
--- a/dependency-check-core/src/main/resources/dependencycheck.properties
+++ b/dependency-check-core/src/main/resources/dependencycheck.properties
@@ -24,7 +24,7 @@ data.file_name=dc.h2.db
 ### the gradle PurgeDataExtension.
 data.version=3.0
 
-data.connection_string=jdbc:h2:file:%s;FILE_LOCK=SERIALIZED;AUTOCOMMIT=ON;
+data.connection_string=jdbc:h2:file:%s;FILE_LOCK=FS;AUTOCOMMIT=ON;
 #data.connection_string=jdbc:mysql://localhost:3306/dependencycheck
 
 # user name and password for the database connection. The inherent case is to use H2.
diff --git a/dependency-check-core/src/test/resources/dependencycheck.properties b/dependency-check-core/src/test/resources/dependencycheck.properties
index ed207a3ff..e6b2ca6d4 100644
--- a/dependency-check-core/src/test/resources/dependencycheck.properties
+++ b/dependency-check-core/src/test/resources/dependencycheck.properties
@@ -19,7 +19,7 @@ data.directory=[JAR]/data
 #if the filename has a %s it will be replaced with the current expected version
 data.file_name=dc.h2.db
 data.version=3.0
-data.connection_string=jdbc:h2:file:%s;FILE_LOCK=SERIALIZED;AUTOCOMMIT=ON;
+data.connection_string=jdbc:h2:file:%s;FILE_LOCK=FS;AUTOCOMMIT=ON;
 #data.connection_string=jdbc:mysql://localhost:3306/dependencycheck
 
 # user name and password for the database connection. The inherent case is to use H2.
diff --git a/dependency-check-utils/src/test/resources/dependencycheck.properties b/dependency-check-utils/src/test/resources/dependencycheck.properties
index 49f47d480..61c98f91e 100644
--- a/dependency-check-utils/src/test/resources/dependencycheck.properties
+++ b/dependency-check-utils/src/test/resources/dependencycheck.properties
@@ -18,7 +18,7 @@ engine.version.url=http://jeremylong.github.io/DependencyCheck/current.txt
 data.directory=[JAR]/data
 data.file_name=dc.h2.db
 data.version=3.0
-data.connection_string=jdbc:h2:file:%s;FILE_LOCK=SERIALIZED;AUTOCOMMIT=ON;
+data.connection_string=jdbc:h2:file:%s;FILE_LOCK=FS;AUTOCOMMIT=ON;
 #data.connection_string=jdbc:h2:file:%s;AUTO_SERVER=TRUE;AUTOCOMMIT=ON;
 #data.connection_string=jdbc:mysql://localhost:3306/dependencycheck
 
diff --git a/pom.xml b/pom.xml
index 0576d574c..ea4677b69 100644
--- a/pom.xml
+++ b/pom.xml
@@ -551,7 +551,7 @@ Copyright (c) 2012 - Jeremy Long
             
                 com.h2database
                 h2
-                1.3.176
+                1.4.192
             
             
                 commons-cli

From 4894372eee81f7120e4df412dea7a9e8fad56182 Mon Sep 17 00:00:00 2001
From: Jeremy Long 
Date: Sat, 23 Jul 2016 06:50:11 -0400
Subject: [PATCH 07/30] minor code quality issues corrected

---
 .../utils/SSLSocketFactoryEx.java              | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java
index a8f9ec724..0b471d88f 100644
--- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java
+++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java
@@ -14,14 +14,24 @@ import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSocket;
 import javax.net.ssl.SSLSocketFactory;
 import javax.net.ssl.TrustManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
+ * This class is used to enable additional ciphers used by the SSL Socket. This 
+ * is specifically because the NVD stopped supporting TLS 1.0 and Java 6 and 7
+ * clients by default were unable to connect to download the NVD data feeds.
+ * 
  * The following code was copied from
  * http://stackoverflow.com/questions/1037590/which-cipher-suites-to-enable-for-ssl-socket/23365536#23365536
  *
  */
 class SSLSocketFactoryEx extends SSLSocketFactory {
-
+    /**
+     * The Logger for use throughout the class.
+     */
+    private static final Logger LOGGER = LoggerFactory.getLogger(SSLSocketFactoryEx.class);
+    
     public SSLSocketFactoryEx() throws NoSuchAlgorithmException, KeyManagementException {
         initSSLSocketFactoryEx(null, null, null);
     }
@@ -52,6 +62,7 @@ class SSLSocketFactoryEx extends SSLSocketFactory {
         return m_protocols;
     }
 
+    @Override
     public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
         SSLSocketFactory factory = m_ctx.getSocketFactory();
         SSLSocket ss = (SSLSocket) factory.createSocket(s, host, port, autoClose);
@@ -142,7 +153,7 @@ class SSLSocketFactoryEx extends SSLSocketFactory {
                 try {
                     socket.close();
                 } catch (IOException ex) {
-                    //ignore
+                    LOGGER.trace("Error closing socket", ex);
                 }
             }
         }
@@ -203,13 +214,14 @@ class SSLSocketFactoryEx extends SSLSocketFactory {
             "TLS_RSA_WITH_AES_128_CBC_SHA"
         };
 
-        String[] availableCiphers = null;
+        String[] availableCiphers;
 
         try {
             SSLSocketFactory factory = m_ctx.getSocketFactory();
             availableCiphers = factory.getSupportedCipherSuites();
             Arrays.sort(availableCiphers);
         } catch (Exception e) {
+            LOGGER.debug("Error retrieving ciphers", e);
             return new String[]{
                 "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
                 "TLS_DHE_DSS_WITH_AES_256_CBC_SHA",

From 9ae9c111e30c930689aaf96a93a7ec64a39c3505 Mon Sep 17 00:00:00 2001
From: Jeremy Long 
Date: Sat, 23 Jul 2016 07:13:09 -0400
Subject: [PATCH 08/30] checkstyle corrections

---
 .../utils/SSLSocketFactoryEx.java             | 153 ++++++++++-
 .../owasp/dependencycheck/utils/Settings.java | 245 +++++++++++-------
 .../utils/URLConnectionFactory.java           |  18 +-
 3 files changed, 305 insertions(+), 111 deletions(-)

diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java
index 0b471d88f..767cd6884 100644
--- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java
+++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java
@@ -18,50 +18,106 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * This class is used to enable additional ciphers used by the SSL Socket. This 
+ * This class is used to enable additional ciphers used by the SSL Socket. This
  * is specifically because the NVD stopped supporting TLS 1.0 and Java 6 and 7
  * clients by default were unable to connect to download the NVD data feeds.
- * 
+ *
  * The following code was copied from
  * http://stackoverflow.com/questions/1037590/which-cipher-suites-to-enable-for-ssl-socket/23365536#23365536
  *
  */
-class SSLSocketFactoryEx extends SSLSocketFactory {
+public class SSLSocketFactoryEx extends SSLSocketFactory {
+
     /**
      * The Logger for use throughout the class.
      */
     private static final Logger LOGGER = LoggerFactory.getLogger(SSLSocketFactoryEx.class);
-    
+
+    /**
+     * Constructs a new SSLSocketFactory.
+     *
+     * @throws NoSuchAlgorithmException thrown when an algorithm is not
+     * supported
+     * @throws KeyManagementException thrown if initialization fails
+     */
     public SSLSocketFactoryEx() throws NoSuchAlgorithmException, KeyManagementException {
         initSSLSocketFactoryEx(null, null, null);
     }
 
+    /**
+     * Constructs a new SSLSocketFactory.
+     *
+     * @param km the key manager
+     * @param tm the trust manager
+     * @param random secure random
+     * @throws NoSuchAlgorithmException thrown when an algorithm is not
+     * supported
+     * @throws KeyManagementException thrown if initialization fails
+     */
     public SSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random) throws NoSuchAlgorithmException, KeyManagementException {
         initSSLSocketFactoryEx(km, tm, random);
     }
 
+    /**
+     * Constructs a new SSLSocketFactory.
+     *
+     * @param ctx the SSL context
+     * @throws NoSuchAlgorithmException thrown when an algorithm is not
+     * supported
+     * @throws KeyManagementException thrown if initialization fails
+     */
     public SSLSocketFactoryEx(SSLContext ctx) throws NoSuchAlgorithmException, KeyManagementException {
         initSSLSocketFactoryEx(ctx);
     }
 
+    /**
+     * Returns the default cipher suites.
+     *
+     * @return the default cipher suites
+     */
     @Override
     public String[] getDefaultCipherSuites() {
         return m_ciphers;
     }
 
+    /**
+     * Returns the supported cipher suites.
+     *
+     * @return the supported cipher suites
+     */
     @Override
     public String[] getSupportedCipherSuites() {
         return m_ciphers;
     }
 
+    /**
+     * Returns the default protocols.
+     *
+     * @return the default protocols
+     */
     public String[] getDefaultProtocols() {
         return m_protocols;
     }
 
+    /**
+     * Returns the supported protocols.
+     *
+     * @return the supported protocols
+     */
     public String[] getSupportedProtocols() {
         return m_protocols;
     }
 
+    /**
+     * Creates an SSL Socket.
+     *
+     * @param s the base socket
+     * @param host the host
+     * @param port the port
+     * @param autoClose if the socket should auto-close
+     * @return the SSL Socket
+     * @throws IOException thrown if the creation fails
+     */
     @Override
     public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
         SSLSocketFactory factory = m_ctx.getSocketFactory();
@@ -73,6 +129,16 @@ class SSLSocketFactoryEx extends SSLSocketFactory {
         return ss;
     }
 
+    /**
+     * Creates a new SSL Socket.
+     *
+     * @param address the address to connect to
+     * @param port the port number
+     * @param localAddress the local address
+     * @param localPort the local port
+     * @return the SSL Socket
+     * @throws IOException thrown if the creation fails
+     */
     @Override
     public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
         SSLSocketFactory factory = m_ctx.getSocketFactory();
@@ -84,6 +150,16 @@ class SSLSocketFactoryEx extends SSLSocketFactory {
         return ss;
     }
 
+    /**
+     * Creates a new SSL Socket.
+     *
+     * @param host the host to connect to
+     * @param port the port to connect to
+     * @param localHost the local host
+     * @param localPort the local port
+     * @return the SSL Socket
+     * @throws IOException thrown if the creation fails
+     */
     @Override
     public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
         SSLSocketFactory factory = m_ctx.getSocketFactory();
@@ -95,6 +171,14 @@ class SSLSocketFactoryEx extends SSLSocketFactory {
         return ss;
     }
 
+    /**
+     * Creates a new SSL Socket.
+     *
+     * @param host the host to connect to
+     * @param port the port to connect to
+     * @return the SSL Socket
+     * @throws IOException thrown if the creation fails
+     */
     @Override
     public Socket createSocket(InetAddress host, int port) throws IOException {
         SSLSocketFactory factory = m_ctx.getSocketFactory();
@@ -106,6 +190,14 @@ class SSLSocketFactoryEx extends SSLSocketFactory {
         return ss;
     }
 
+    /**
+     * Creates a new SSL Socket.
+     *
+     * @param host the host to connect to
+     * @param port the port to connect to
+     * @return the SSL Socket
+     * @throws IOException thrown if the creation fails
+     */
     @Override
     public Socket createSocket(String host, int port) throws IOException {
         SSLSocketFactory factory = m_ctx.getSocketFactory();
@@ -117,24 +209,47 @@ class SSLSocketFactoryEx extends SSLSocketFactory {
         return ss;
     }
 
+    /**
+     * Initializes the SSL Socket Factory Extension.
+     *
+     * @param km the key managers
+     * @param tm the trust managers
+     * @param random the secure random number generator
+     * @throws NoSuchAlgorithmException thrown when an algorithm is not
+     * supported
+     * @throws KeyManagementException thrown if initialization fails
+     */
     private void initSSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random)
             throws NoSuchAlgorithmException, KeyManagementException {
         m_ctx = SSLContext.getInstance("TLS");
         m_ctx.init(km, tm, random);
 
-        m_protocols = GetProtocolList();
-        m_ciphers = GetCipherList();
+        m_protocols = getProtocolList();
+        m_ciphers = getCipherList();
     }
 
+    /**
+     * Initializes the SSL Socket Factory Extension.
+     *
+     * @param ctx the SSL context
+     * @throws NoSuchAlgorithmException thrown when an algorithm is not
+     * supported
+     * @throws KeyManagementException thrown if initialization fails
+     */
     private void initSSLSocketFactoryEx(SSLContext ctx)
             throws NoSuchAlgorithmException, KeyManagementException {
         m_ctx = ctx;
 
-        m_protocols = GetProtocolList();
-        m_ciphers = GetCipherList();
+        m_protocols = getProtocolList();
+        m_ciphers = getCipherList();
     }
 
-    protected String[] GetProtocolList() {
+    /**
+     * Returns the protocol list.
+     *
+     * @return the protocol list
+     */
+    protected String[] getProtocolList() {
         String[] preferredProtocols = {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"};
         String[] availableProtocols = null;
 
@@ -146,7 +261,8 @@ class SSLSocketFactoryEx extends SSLSocketFactory {
 
             availableProtocols = socket.getSupportedProtocols();
             Arrays.sort(availableProtocols);
-        } catch (Exception e) {
+        } catch (Exception ex) {
+            LOGGER.debug("Error getting protocol list, using TLSv1", ex);
             return new String[]{"TLSv1"};
         } finally {
             if (socket != null) {
@@ -169,7 +285,12 @@ class SSLSocketFactoryEx extends SSLSocketFactory {
         return aa.toArray(new String[0]);
     }
 
-    protected String[] GetCipherList() {
+    /**
+     * Returns the cipher list.
+     *
+     * @return the cipher list
+     */
+    protected String[] getCipherList() {
         String[] preferredCiphers = {
             // *_CHACHA20_POLY1305 are 3x to 4x faster than existing cipher suites.
             //   http://googleonlinesecurity.blogspot.com/2014/04/speeding-up-and-strengthening-https.html
@@ -248,8 +369,16 @@ class SSLSocketFactoryEx extends SSLSocketFactory {
         return aa.toArray(new String[0]);
     }
 
+    /**
+     * The SSL context.
+     */
     private SSLContext m_ctx;
-
+    /**
+     * The cipher suites.
+     */
     private String[] m_ciphers;
+    /**
+     * The protocols.
+     */
     private String[] m_protocols;
 }
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 6f24387b0..bacc4870a 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
@@ -46,7 +46,8 @@ public final class Settings {
     public static final class KEYS {
 
         /**
-         * private constructor because this is a "utility" class containing constants
+         * private constructor because this is a "utility" class containing
+         * constants
          */
         private KEYS() {
             //do nothing
@@ -60,23 +61,28 @@ public final class Settings {
          */
         public static final String APPLICATION_VERSION = "application.version";
         /**
-         * The key to obtain the URL to retrieve the current release version from.
+         * The key to obtain the URL to retrieve the current release version
+         * from.
          */
         public static final String ENGINE_VERSION_CHECK_URL = "engine.version.url";
         /**
-         * The properties key indicating whether or not the cached data sources should be updated.
+         * The properties key indicating whether or not the cached data sources
+         * should be updated.
          */
         public static final String AUTO_UPDATE = "autoupdate";
         /**
-         * The database driver class name. If this is not in the properties file the embedded database is used.
+         * The database driver class name. If this is not in the properties file
+         * the embedded database is used.
          */
         public static final String DB_DRIVER_NAME = "data.driver_name";
         /**
-         * The database driver class name. If this is not in the properties file the embedded database is used.
+         * The database driver class name. If this is not in the properties file
+         * the embedded database is used.
          */
         public static final String DB_DRIVER_PATH = "data.driver_path";
         /**
-         * The database connection string. If this is not in the properties file the embedded database is used.
+         * The database connection string. If this is not in the properties file
+         * the embedded database is used.
          */
         public static final String DB_CONNECTION_STRING = "data.connection_string";
         /**
@@ -101,36 +107,41 @@ public final class Settings {
         public static final String DB_VERSION = "data.version";
         /**
          * The starts with filter used to exclude CVE entries from the database.
-         * By default this is set to 'cpe:/a:' which limits the CVEs imported to 
-         * just those that are related to applications. If this were set to just 
-         * 'cpe:' the OS, hardware, and application related CVEs would be imported.
+         * By default this is set to 'cpe:/a:' which limits the CVEs imported to
+         * just those that are related to applications. If this were set to just
+         * 'cpe:' the OS, hardware, and application related CVEs would be
+         * imported.
          */
         public static final String CVE_CPE_STARTS_WITH_FILTER = "cve.cpe.startswith.filter";
         /**
-         * The properties key for the URL to retrieve the "meta" data from about the CVE entries.
+         * The properties key for the URL to retrieve the "meta" data from about
+         * the CVE entries.
          */
         public static final String CVE_META_URL = "cve.url.meta";
         /**
-         * The properties key for the URL to retrieve the recently modified and added CVE entries (last 8 days) using the 2.0
-         * schema.
+         * The properties key for the URL to retrieve the recently modified and
+         * added CVE entries (last 8 days) using the 2.0 schema.
          */
         public static final String CVE_MODIFIED_20_URL = "cve.url-2.0.modified";
         /**
-         * The properties key for the URL to retrieve the recently modified and added CVE entries (last 8 days) using the 1.2
-         * schema.
+         * The properties key for the URL to retrieve the recently modified and
+         * added CVE entries (last 8 days) using the 1.2 schema.
          */
         public static final String CVE_MODIFIED_12_URL = "cve.url-1.2.modified";
         /**
-         * The properties key for the URL to retrieve the recently modified and added CVE entries (last 8 days).
+         * The properties key for the URL to retrieve the recently modified and
+         * added CVE entries (last 8 days).
          */
         public static final String CVE_MODIFIED_VALID_FOR_DAYS = "cve.url.modified.validfordays";
         /**
-         * The properties key to control the skipping of the check for CVE updates.
+         * The properties key to control the skipping of the check for CVE
+         * updates.
          */
         public static final String CVE_CHECK_VALID_FOR_HOURS = "cve.check.validforhours";
         /**
-         * The properties key for the telling us how many cve.url.* URLs exists. This is used in combination with CVE_BASE_URL to
-         * be able to retrieve the URLs for all of the files that make up the NVD CVE listing.
+         * The properties key for the telling us how many cve.url.* URLs exists.
+         * This is used in combination with CVE_BASE_URL to be able to retrieve
+         * the URLs for all of the files that make up the NVD CVE listing.
          */
         public static final String CVE_START_YEAR = "cve.startyear";
         /**
@@ -142,7 +153,8 @@ public final class Settings {
          */
         public static final String CVE_SCHEMA_2_0 = "cve.url-2.0.base";
         /**
-         * The properties key that indicates how often the CPE data needs to be updated.
+         * The properties key that indicates how often the CPE data needs to be
+         * updated.
          */
         public static final String CPE_MODIFIED_VALID_FOR_DAYS = "cpe.validfordays";
         /**
@@ -152,7 +164,9 @@ public final class Settings {
         /**
          * The properties key for the proxy server.
          *
-         * @deprecated use {@link org.owasp.dependencycheck.utils.Settings.KEYS#PROXY_SERVER} instead.
+         * @deprecated use
+         * {@link org.owasp.dependencycheck.utils.Settings.KEYS#PROXY_SERVER}
+         * instead.
          */
         @Deprecated
         public static final String PROXY_URL = "proxy.server";
@@ -161,7 +175,8 @@ public final class Settings {
          */
         public static final String PROXY_SERVER = "proxy.server";
         /**
-         * The properties key for the proxy port - this must be an integer value.
+         * The properties key for the proxy port - this must be an integer
+         * value.
          */
         public static final String PROXY_PORT = "proxy.port";
         /**
@@ -209,19 +224,23 @@ public final class Settings {
          */
         public static final String ANALYZER_ARCHIVE_ENABLED = "analyzer.archive.enabled";
         /**
-         * The properties key for whether the node.js package analyzer is enabled.
+         * The properties key for whether the node.js package analyzer is
+         * enabled.
          */
         public static final String ANALYZER_NODE_PACKAGE_ENABLED = "analyzer.node.package.enabled";
         /**
-         * The properties key for whether the composer lock file analyzer is enabled.
+         * The properties key for whether the composer lock file analyzer is
+         * enabled.
          */
         public static final String ANALYZER_COMPOSER_LOCK_ENABLED = "analyzer.composer.lock.enabled";
         /**
-         * The properties key for whether the Python Distribution analyzer is enabled.
+         * The properties key for whether the Python Distribution analyzer is
+         * enabled.
          */
         public static final String ANALYZER_PYTHON_DISTRIBUTION_ENABLED = "analyzer.python.distribution.enabled";
         /**
-         * The properties key for whether the Python Package analyzer is enabled.
+         * The properties key for whether the Python Package analyzer is
+         * enabled.
          */
         public static final String ANALYZER_PYTHON_PACKAGE_ENABLED = "analyzer.python.package.enabled";
         /**
@@ -237,7 +256,8 @@ public final class Settings {
          */
         public static final String ANALYZER_CMAKE_ENABLED = "analyzer.cmake.enabled";
         /**
-         * The properties key for whether the Ruby Bundler Audit analyzer is enabled.
+         * The properties key for whether the Ruby Bundler Audit analyzer is
+         * enabled.
          */
         public static final String ANALYZER_BUNDLE_AUDIT_ENABLED = "analyzer.bundle.audit.enabled";
         /**
@@ -331,7 +351,8 @@ public final class Settings {
     private Properties props = null;
 
     /**
-     * Private constructor for the Settings class. This class loads the properties files.
+     * Private constructor for the Settings class. This class loads the
+     * properties files.
      *
      * @param propertiesFilePath the path to the base properties file to load
      */
@@ -357,16 +378,18 @@ public final class Settings {
     }
 
     /**
-     * Initializes the thread local settings object. Note, to use the settings object you must call this method. However, you must
-     * also call Settings.cleanup() to properly release resources.
+     * Initializes the thread local settings object. Note, to use the settings
+     * object you must call this method. However, you must also call
+     * Settings.cleanup() to properly release resources.
      */
     public static void initialize() {
         LOCAL_SETTINGS.set(new Settings(PROPERTIES_FILE));
     }
 
     /**
-     * Initializes the thread local settings object. Note, to use the settings object you must call this method. However, you must
-     * also call Settings.cleanup() to properly release resources.
+     * Initializes the thread local settings object. Note, to use the settings
+     * object you must call this method. However, you must also call
+     * Settings.cleanup() to properly release resources.
      *
      * @param propertiesFilePath the path to the base properties file to load
      */
@@ -385,7 +408,8 @@ public final class Settings {
     /**
      * Cleans up resources to prevent memory leaks.
      *
-     * @param deleteTemporary flag indicating whether any temporary directories generated should be removed
+     * @param deleteTemporary flag indicating whether any temporary directories
+     * generated should be removed
      */
     public static void cleanup(boolean deleteTemporary) {
         if (deleteTemporary && tempDirectory != null && tempDirectory.exists()) {
@@ -425,7 +449,8 @@ public final class Settings {
     }
 
     /**
-     * Logs the properties. This will not log any properties that contain 'password' in the key.
+     * Logs the properties. This will not log any properties that contain
+     * 'password' in the key.
      *
      * @param header the header to print with the log message
      * @param properties the properties to log
@@ -541,13 +566,16 @@ public final class Settings {
     }
 
     /**
-     * Merges a new properties file into the current properties. This method allows for the loading of a user provided properties
-     * file.

- * Note: even if using this method - system properties will be loaded before properties loaded from files. + * Merges a new properties file into the current properties. This method + * allows for the loading of a user provided properties file.

+ * Note: even if using this method - system properties will be loaded + * before properties loaded from files. * * @param filePath the path to the properties file to merge. - * @throws FileNotFoundException is thrown when the filePath points to a non-existent file - * @throws IOException is thrown when there is an exception loading/merging the properties + * @throws FileNotFoundException is thrown when the filePath points to a + * non-existent file + * @throws IOException is thrown when there is an exception loading/merging + * the properties */ public static void mergeProperties(File filePath) throws FileNotFoundException, IOException { FileInputStream fis = null; @@ -566,13 +594,16 @@ public final class Settings { } /** - * Merges a new properties file into the current properties. This method allows for the loading of a user provided properties - * file.

- * Note: even if using this method - system properties will be loaded before properties loaded from files. + * Merges a new properties file into the current properties. This method + * allows for the loading of a user provided properties file.

+ * Note: even if using this method - system properties will be loaded before + * properties loaded from files. * * @param filePath the path to the properties file to merge. - * @throws FileNotFoundException is thrown when the filePath points to a non-existent file - * @throws IOException is thrown when there is an exception loading/merging the properties + * @throws FileNotFoundException is thrown when the filePath points to a + * non-existent file + * @throws IOException is thrown when there is an exception loading/merging + * the properties */ public static void mergeProperties(String filePath) throws FileNotFoundException, IOException { FileInputStream fis = null; @@ -591,12 +622,14 @@ public final class Settings { } /** - * Merges a new properties file into the current properties. This method allows for the loading of a user provided properties - * file.

- * Note: even if using this method - system properties will be loaded before properties loaded from files. + * Merges a new properties file into the current properties. This method + * allows for the loading of a user provided properties file.

+ * Note: even if using this method - system properties will be loaded + * before properties loaded from files. * * @param stream an Input Stream pointing at a properties file to merge - * @throws IOException is thrown when there is an exception loading/merging the properties + * @throws IOException is thrown when there is an exception loading/merging + * the properties */ public static void mergeProperties(InputStream stream) throws IOException { LOCAL_SETTINGS.get().props.load(stream); @@ -604,9 +637,10 @@ public final class Settings { } /** - * Returns a value from the properties file as a File object. If the value was specified as a system property or passed in via - * the -Dprop=value argument - this method will return the value from the system properties before the values in the contained - * configuration file. + * Returns a value from the properties file as a File object. If the value + * was specified as a system property or passed in via the -Dprop=value + * argument - this method will return the value from the system properties + * before the values in the contained configuration file. * * @param key the key to lookup within the properties file * @return the property from the properties file converted to a File object @@ -620,13 +654,15 @@ public final class Settings { } /** - * Returns a value from the properties file as a File object. If the value was specified as a system property or passed in via - * the -Dprop=value argument - this method will return the value from the system properties before the values in the contained - * configuration file. + * Returns a value from the properties file as a File object. If the value + * was specified as a system property or passed in via the -Dprop=value + * argument - this method will return the value from the system properties + * before the values in the contained configuration file. * - * This method will check the configured base directory and will use this as the base of the file path. Additionally, if the - * base directory begins with a leading "[JAR]\" sequence with the path to the folder containing the JAR file containing this - * class. + * This method will check the configured base directory and will use this as + * the base of the file path. Additionally, if the base directory begins + * with a leading "[JAR]\" sequence with the path to the folder containing + * the JAR file containing this class. * * @param key the key to lookup within the properties file * @return the property from the properties file converted to a File object @@ -649,7 +685,8 @@ public final class Settings { } /** - * Attempts to retrieve the folder containing the Jar file containing the Settings class. + * Attempts to retrieve the folder containing the Jar file containing the + * Settings class. * * @return a File object */ @@ -671,9 +708,10 @@ public final class Settings { } /** - * Returns a value from the properties file. If the value was specified as a system property or passed in via the -Dprop=value - * argument - this method will return the value from the system properties before the values in the contained configuration - * file. + * Returns a value from the properties file. If the value was specified as a + * system property or passed in via the -Dprop=value argument - this method + * will return the value from the system properties before the values in the + * contained configuration file. * * @param key the key to lookup within the properties file * @param defaultValue the default value for the requested property @@ -685,7 +723,8 @@ public final class Settings { } /** - * A reference to the temporary directory; used incase it needs to be deleted during cleanup. + * A reference to the temporary directory; used incase it needs to be + * deleted during cleanup. */ private static File tempDirectory = null; @@ -693,7 +732,8 @@ public final class Settings { * Returns the temporary directory. * * @return the temporary directory - * @throws java.io.IOException thrown if the temporary directory does not exist and cannot be created + * @throws java.io.IOException thrown if the temporary directory does not + * exist and cannot be created */ public static File getTempDirectory() throws IOException { final File tmpDir = new File(Settings.getString(Settings.KEYS.TEMP_DIRECTORY, System.getProperty("java.io.tmpdir")), "dctemp"); @@ -706,9 +746,10 @@ public final class Settings { } /** - * Returns a value from the properties file. If the value was specified as a system property or passed in via the -Dprop=value - * argument - this method will return the value from the system properties before the values in the contained configuration - * file. + * Returns a value from the properties file. If the value was specified as a + * system property or passed in via the -Dprop=value argument - this method + * will return the value from the system properties before the values in the + * contained configuration file. * * @param key the key to lookup within the properties file * @return the property from the properties file @@ -718,7 +759,8 @@ public final class Settings { } /** - * Removes a property from the local properties collection. This is mainly used in test cases. + * Removes a property from the local properties collection. This is mainly + * used in test cases. * * @param key the property key to remove */ @@ -727,13 +769,15 @@ public final class Settings { } /** - * Returns an int value from the properties file. If the value was specified as a system property or passed in via the - * -Dprop=value argument - this method will return the value from the system properties before the values in the contained - * configuration file. + * Returns an int value from the properties file. If the value was specified + * as a system property or passed in via the -Dprop=value argument - this + * method will return the value from the system properties before the values + * in the contained configuration file. * * @param key the key to lookup within the properties file * @return the property from the properties file - * @throws InvalidSettingException is thrown if there is an error retrieving the setting + * @throws InvalidSettingException is thrown if there is an error retrieving + * the setting */ public static int getInt(String key) throws InvalidSettingException { try { @@ -744,14 +788,15 @@ public final class Settings { } /** - * Returns an int value from the properties file. If the value was specified as a system property or passed in via the - * -Dprop=value argument - this method will return the value from the system properties before the values in the contained - * configuration file. + * Returns an int value from the properties file. If the value was specified + * as a system property or passed in via the -Dprop=value argument - this + * method will return the value from the system properties before the values + * in the contained configuration file. * * @param key the key to lookup within the properties file * @param defaultValue the default value to return - * @return the property from the properties file or the defaultValue if the property does not exist or cannot be converted to - * an integer + * @return the property from the properties file or the defaultValue if the + * property does not exist or cannot be converted to an integer */ public static int getInt(String key, int defaultValue) { int value; @@ -767,13 +812,15 @@ public final class Settings { } /** - * Returns a long value from the properties file. If the value was specified as a system property or passed in via the - * -Dprop=value argument - this method will return the value from the system properties before the values in the contained - * configuration file. + * Returns a long value from the properties file. If the value was specified + * as a system property or passed in via the -Dprop=value argument - this + * method will return the value from the system properties before the values + * in the contained configuration file. * * @param key the key to lookup within the properties file * @return the property from the properties file - * @throws InvalidSettingException is thrown if there is an error retrieving the setting + * @throws InvalidSettingException is thrown if there is an error retrieving + * the setting */ public static long getLong(String key) throws InvalidSettingException { try { @@ -784,38 +831,47 @@ public final class Settings { } /** - * Returns a boolean value from the properties file. If the value was specified as a system property or passed in via the - * -Dprop=value argument this method will return the value from the system properties before the values in the - * contained configuration file. + * Returns a boolean value from the properties file. If the value was + * specified as a system property or passed in via the + * -Dprop=value argument this method will return the value from + * the system properties before the values in the contained configuration + * file. * * @param key the key to lookup within the properties file * @return the property from the properties file - * @throws InvalidSettingException is thrown if there is an error retrieving the setting + * @throws InvalidSettingException is thrown if there is an error retrieving + * the setting */ public static boolean getBoolean(String key) throws InvalidSettingException { return Boolean.parseBoolean(Settings.getString(key)); } /** - * Returns a boolean value from the properties file. If the value was specified as a system property or passed in via the - * -Dprop=value argument this method will return the value from the system properties before the values in the - * contained configuration file. + * Returns a boolean value from the properties file. If the value was + * specified as a system property or passed in via the + * -Dprop=value argument this method will return the value from + * the system properties before the values in the contained configuration + * file. * * @param key the key to lookup within the properties file - * @param defaultValue the default value to return if the setting does not exist + * @param defaultValue the default value to return if the setting does not + * exist * @return the property from the properties file - * @throws InvalidSettingException is thrown if there is an error retrieving the setting + * @throws InvalidSettingException is thrown if there is an error retrieving + * the setting */ public static boolean getBoolean(String key, boolean defaultValue) throws InvalidSettingException { return Boolean.parseBoolean(Settings.getString(key, Boolean.toString(defaultValue))); } /** - * Returns a connection string from the configured properties. If the connection string contains a %s, this method will - * determine the 'data' directory and replace the %s with the path to the data directory. If the data directory does not - * exists it will be created. + * Returns a connection string from the configured properties. If the + * connection string contains a %s, this method will determine the 'data' + * directory and replace the %s with the path to the data directory. If the + * data directory does not exists it will be created. * - * @param connectionStringKey the property file key for the connection string + * @param connectionStringKey the property file key for the connection + * string * @param dbFileNameKey the settings key for the db filename * @return the connection string * @throws IOException thrown the data directory cannot be created @@ -852,8 +908,9 @@ public final class Settings { } /** - * Retrieves the directory that the JAR file exists in so that we can ensure we always use a common data directory for the - * embedded H2 database. This is public solely for some unit tests; otherwise this should be private. + * Retrieves the directory that the JAR file exists in so that we can ensure + * we always use a common data directory for the embedded H2 database. This + * is public solely for some unit tests; otherwise this should be private. * * @return the data directory to store data files * @throws IOException is thrown if an IOException occurs of course... diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java index 84d6e18e6..bfbb52773 100644 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java +++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java @@ -107,7 +107,7 @@ public final class URLConnectionFactory { } throw new URLConnectionFailureException("Error getting connection.", ex); } - ConfigureTLS(url, conn); + configureTLS(url, conn); return conn; } @@ -176,15 +176,23 @@ public final class URLConnectionFactory { } catch (IOException ioe) { throw new URLConnectionFailureException("Error getting connection.", ioe); } - ConfigureTLS(url, conn); + configureTLS(url, conn); return conn; } - private static void ConfigureTLS(URL url, HttpURLConnection conn) { + /** + * If the protocol is HTTPS, this will configure the cipher suites so that + * connections can be made to the NVD, and others, using older versions of + * Java. + * + * @param url the URL + * @param conn the connection + */ + private static void configureTLS(URL url, HttpURLConnection conn) { if ("https".equals(url.getProtocol())) { try { - HttpsURLConnection secCon = (HttpsURLConnection) conn; - SSLSocketFactoryEx factory = new SSLSocketFactoryEx(); + final HttpsURLConnection secCon = (HttpsURLConnection) conn; + final SSLSocketFactoryEx factory = new SSLSocketFactoryEx(); secCon.setSSLSocketFactory(factory); } catch (NoSuchAlgorithmException ex) { LOGGER.debug("Unsupported algorithm in SSLSocketFactoryEx", ex); From c25330828476cb9084ce2a888aed2af4757ec9de Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sat, 23 Jul 2016 07:45:48 -0400 Subject: [PATCH 09/30] checkstyle corrections --- .../owasp/dependencycheck/taskdefs/Check.java | 1 - .../owasp/dependencycheck/taskdefs/Purge.java | 4 ++-- .../java/org/owasp/dependencycheck/App.java | 14 ++++++++----- .../org/owasp/dependencycheck/Engine.java | 6 +++--- .../agent/DependencyCheckScanAgent.java | 4 ++-- .../analyzer/ArchiveAnalyzer.java | 4 ++-- .../dependencycheck/analyzer/CPEAnalyzer.java | 16 +++++++-------- .../analyzer/HintAnalyzer.java | 5 ++--- .../dependencycheck/analyzer/JarAnalyzer.java | 7 +------ .../analyzer/RubyBundleAuditAnalyzer.java | 9 ++++++--- .../data/cpe/CpeMemoryIndex.java | 20 ++++--------------- .../data/lucene/FieldAnalyzer.java | 2 +- .../dependencycheck/data/nvdcve/CveDB.java | 9 ++++----- .../data/update/cpe/CPEHandler.java | 20 ++++++++++++------- .../data/update/nvd/UpdateableNvdCve.java | 3 +++ .../exception/ExceptionCollection.java | 5 +++-- .../xml/hints/HintHandler.java | 4 ++-- .../dependencycheck/xml/hints/Hints.java | 9 ++++----- .../dependencycheck/maven/AggregateMojo.java | 5 ++--- .../maven/BaseDependencyCheckMojo.java | 7 ++++--- .../dependencycheck/maven/CheckMojo.java | 2 +- .../dependencycheck/maven/UpdateMojo.java | 1 - 22 files changed, 75 insertions(+), 82 deletions(-) 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 86268a2d2..6c38786d4 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 @@ -18,7 +18,6 @@ package org.owasp.dependencycheck.taskdefs; import java.io.File; -import java.io.IOException; import java.util.List; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; diff --git a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java index 5316a44c8..3bc335fb0 100644 --- a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java +++ b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java @@ -78,7 +78,7 @@ public class Purge extends Task { private boolean failOnError = true; /** - * Get the value of failOnError + * Get the value of failOnError. * * @return the value of failOnError */ @@ -87,7 +87,7 @@ public class Purge extends Task { } /** - * Set the value of failOnError + * Set the value of failOnError. * * @param failOnError new value of failOnError */ diff --git a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java index 6e1d0f8dd..af8b2271b 100644 --- a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java +++ b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java @@ -37,7 +37,6 @@ import org.owasp.dependencycheck.utils.Settings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ch.qos.logback.core.FileAppender; -import java.util.logging.Level; import org.owasp.dependencycheck.data.update.exception.UpdateException; import org.owasp.dependencycheck.exception.ExceptionCollection; import org.owasp.dependencycheck.exception.ReportException; @@ -77,6 +76,7 @@ public class App { * Main CLI entry-point into the application. * * @param args the command line arguments + * @return the exit code to return */ public int run(String[] args) { int exitCode = 0; @@ -170,13 +170,13 @@ public class App { exitCode = -12; } catch (ExceptionCollection ex) { if (ex.isFatal()) { - exitCode =-13; + exitCode = -13; LOGGER.error("One or more fatal errors occured"); } else { - exitCode =-14; - } + exitCode = -14; + } for (Throwable e : ex.getExceptions()) { - LOGGER.error(e.getMessage()); + LOGGER.error(e.getMessage()); } } } else { @@ -301,6 +301,10 @@ public class App { /** * Only executes the update phase of dependency-check. + * + * @throws UpdateException thrown if there is an error updating + * @throws DatabaseException thrown if a fatal error occurred and a + * connection to the database could not be established */ private void runUpdateOnly() throws UpdateException, DatabaseException { Engine engine = null; diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java index 82e60467b..5560c4adc 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java @@ -333,7 +333,7 @@ public class Engine implements FileFilter { * during analysis */ public void analyzeDependencies() throws ExceptionCollection { - List exceptions = new ArrayList(); + final List exceptions = new ArrayList(); boolean autoUpdate = true; try { autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE); @@ -359,7 +359,7 @@ public class Engine implements FileFilter { LOGGER.error("{}\n\nUnable to continue dependency-check analysis.", ex.getMessage()); LOGGER.debug("", ex); exceptions.add(ex); - throw new ExceptionCollection("Unable to continue dependency-check analysis.",exceptions, true); + throw new ExceptionCollection("Unable to continue dependency-check analysis.", exceptions, true); } catch (DatabaseException ex) { LOGGER.error("{}\n\nUnable to continue dependency-check analysis.", ex.getMessage()); LOGGER.debug("", ex); @@ -480,7 +480,7 @@ public class Engine implements FileFilter { * Cycles through the cached web data sources and calls update on all of * them. * - * @throws UpdateException + * @throws UpdateException thrown if the operation fails */ public void doUpdates() throws UpdateException { LOGGER.info("Checking for updates"); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java index 038644a3e..56ab93810 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java @@ -845,8 +845,8 @@ public class DependencyCheckScanAgent { * Executes the Dependency-Check on the dependent libraries. * * @return the Engine used to scan the dependencies. - * @throws org.owasp.dependencycheck.data.nvdcve.DatabaseException thrown if - * there is an exception connecting to the database + * @throws ExceptionCollection a collection of one or more exceptions that + * occurred during analysis. */ private Engine executeDependencyCheck() throws ExceptionCollection { populateSettings(); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java index 5a14171c7..470d13e2a 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java @@ -367,7 +367,7 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer { final String archiveExt = FileUtils.getFileExtension(archive.getName()).toLowerCase(); try { if (ZIPPABLES.contains(archiveExt)) { - BufferedInputStream in = new BufferedInputStream(fis); + final BufferedInputStream in = new BufferedInputStream(fis); ensureReadableJar(archiveExt, in); extractArchive(new ZipArchiveInputStream(in), destination, engine); } else if ("tar".equals(archiveExt)) { @@ -413,7 +413,7 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer { private void ensureReadableJar(final String archiveExt, BufferedInputStream in) throws IOException { if ("jar".equals(archiveExt) && in.markSupported()) { in.mark(7); - byte[] b = new byte[7]; + final byte[] b = new byte[7]; in.read(b); if (b[0] == '#' && b[1] == '!' diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java index 815881155..f66ec39bd 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java @@ -574,15 +574,13 @@ public class CPEAnalyzer implements Analyzer { final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8")); final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf); collected.add(match); - } else //TODO the following isn't quite right is it? need to think about this guessing game a bit more. - { - if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size() - && evVer.matchesAtLeastThreeLevels(dbVer)) { - if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) { - if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) { - bestGuess = dbVer; - bestGuessConf = conf; - } + } else//TODO the following isn't quite right is it? need to think about this guessing game a bit more. + if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size() + && evVer.matchesAtLeastThreeLevels(dbVer)) { + if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) { + if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) { + bestGuess = dbVer; + bestGuessConf = conf; } } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java index b4ebcbfe0..8bce5cd25 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java @@ -32,7 +32,6 @@ import org.owasp.dependencycheck.dependency.Dependency; import org.owasp.dependencycheck.dependency.Evidence; import org.owasp.dependencycheck.exception.InitializationException; import org.owasp.dependencycheck.xml.suppression.PropertyType; -import org.owasp.dependencycheck.xml.suppression.SuppressionParseException; import org.owasp.dependencycheck.utils.DownloadFailedException; import org.owasp.dependencycheck.utils.Downloader; import org.owasp.dependencycheck.utils.FileUtils; @@ -279,7 +278,7 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer { /** * Loads the hint rules file. * - * @throws SuppressionParseException thrown if the XML cannot be parsed. + * @throws HintParseException thrown if the XML cannot be parsed. */ private void loadHintRules() throws HintParseException { final HintParser parser = new HintParser(); @@ -327,7 +326,7 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer { if (file != null) { try { - Hints newHints = parser.parseHints(file); + final Hints newHints = parser.parseHints(file); hints.getHintRules().addAll(newHints.getHintRules()); hints.getVendorDuplicatingHintRules().addAll(newHints.getVendorDuplicatingHintRules()); LOGGER.debug("{} hint rules were loaded.", hints.getHintRules().size()); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java index 9d952c14c..fed1824a9 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java @@ -39,7 +39,6 @@ import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.Manifest; -import java.util.logging.Level; import java.util.regex.Pattern; import java.util.zip.ZipEntry; import org.apache.commons.compress.utils.IOUtils; @@ -646,9 +645,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { * @return whether evidence was identified parsing the manifest * @throws IOException if there is an issue reading the JAR file */ - protected boolean parseManifest(Dependency dependency, - List classInformation) - throws IOException { + protected boolean parseManifest(Dependency dependency, List classInformation) throws IOException { boolean foundSomething = false; JarFile jar = null; try { @@ -667,7 +664,6 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { final EvidenceCollection vendorEvidence = dependency.getVendorEvidence(); final EvidenceCollection productEvidence = dependency.getProductEvidence(); final EvidenceCollection versionEvidence = dependency.getVersionEvidence(); - String source = "Manifest"; String specificationVersion = null; boolean hasImplementationVersion = false; @@ -784,7 +780,6 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { } } } - for (Map.Entry item : manifest.getEntries().entrySet()) { final String name = item.getKey(); source = "manifest: " + name; diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.java index 9b63eaa6c..8c5d0efed 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.java @@ -52,6 +52,9 @@ import org.owasp.dependencycheck.exception.InitializationException; @Experimental public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer { + /** + * The logger. + */ private static final Logger LOGGER = LoggerFactory.getLogger(RubyBundleAuditAnalyzer.class); /** @@ -150,7 +153,7 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer { setEnabled(false); cvedb.close(); cvedb = null; - String msg = String.format("Exception from bundle-audit process: %s. Disabling %s", ae.getCause(), ANALYZER_NAME); + final String msg = String.format("Exception from bundle-audit process: %s. Disabling %s", ae.getCause(), ANALYZER_NAME); throw new InitializationException(msg, ae); } catch (IOException ex) { setEnabled(false); @@ -162,12 +165,12 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer { exitValue = process.waitFor(); } catch (InterruptedException ex) { setEnabled(false); - String msg = String.format("Bundle-audit process was interupted. Disabling %s", ANALYZER_NAME); + final String msg = String.format("Bundle-audit process was interupted. Disabling %s", ANALYZER_NAME); throw new InitializationException(msg); } if (0 == exitValue) { setEnabled(false); - String msg = String.format("Unexpected exit code from bundle-audit process. Disabling %s: %s", ANALYZER_NAME, exitValue); + final String msg = String.format("Unexpected exit code from bundle-audit process. Disabling %s: %s", ANALYZER_NAME, exitValue); throw new InitializationException(msg); } else { BufferedReader reader = null; diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java index 666a2ffbe..692e4c4be 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java @@ -48,8 +48,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * An in memory lucene index that contains the vendor/product combinations from the CPE (application) identifiers within the NVD - * CVE data. + * An in memory lucene index that contains the vendor/product combinations from + * the CPE (application) identifiers within the NVD CVE data. * * @author Jeremy Long */ @@ -144,19 +144,6 @@ public final class CpeMemoryIndex { return openState; } - /** - * Creates the indexing analyzer for the CPE Index. - * - * @return the CPE Analyzer. - * @deprecated the search field analyzer must be used to include the token concatenating filter. - */ - @Deprecated - private Analyzer createIndexingAnalyzer() { - final Map fieldAnalyzers = new HashMap(); - fieldAnalyzers.put(Fields.DOCUMENT_KEY, new KeywordAnalyzer()); - return new PerFieldAnalyzerWrapper(new FieldAnalyzer(LuceneUtils.CURRENT_VERSION), fieldAnalyzers); - } - /** * Creates an Analyzer for searching the CPE Index. * @@ -275,7 +262,8 @@ public final class CpeMemoryIndex { * @param maxQueryResults the maximum number of documents to return * @return the TopDocs found by the search * @throws ParseException thrown when the searchString is invalid - * @throws IOException is thrown if there is an issue with the underlying Index + * @throws IOException is thrown if there is an issue with the underlying + * Index */ public TopDocs search(String searchString, int maxQueryResults) throws ParseException, IOException { if (searchString == null || searchString.trim().isEmpty()) { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/FieldAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/FieldAnalyzer.java index 534259f07..0736c9fb0 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/FieldAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/FieldAnalyzer.java @@ -34,7 +34,7 @@ import org.apache.lucene.util.Version; * index the CPE fields vendor and product.

* * @author Jeremy Long - * @Deprecated the field analyzer should not be used, instead use the + * @deprecated the field analyzer should not be used, instead use the * SearchFieldAnalyzer so that the token analyzing filter is used. */ @Deprecated diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java index fc920956c..48388a983 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java @@ -68,17 +68,16 @@ public class CveDB { private ResourceBundle statementBundle = null; /** - * Creates a new CveDB object and opens the database - * connection. Note, the connection must be closed by the caller by calling - * the close method. ======= Does the underlying connection support batch - * operations? + * Creates a new CveDB object and opens the database connection. Note, the + * connection must be closed by the caller by calling the close method. + * ======= Does the underlying connection support batch operations? */ private boolean batchSupported; /** * Creates a new CveDB object and opens the database connection. Note, the * connection must be closed by the caller by calling the close method. - * + * * @throws DatabaseException thrown if there is an exception opening the * database. */ diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/cpe/CPEHandler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/cpe/CPEHandler.java index 24293b969..4c778e7b2 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/cpe/CPEHandler.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/cpe/CPEHandler.java @@ -43,9 +43,10 @@ public class CPEHandler extends DefaultHandler { /** * The Starts with expression to filter CVE entries by CPE. */ - private static final String CPE_STARTS_WITH = Settings.getString(Settings.KEYS.CVE_CPE_STARTS_WITH_FILTER,"cpe:/a:"); + private static final String CPE_STARTS_WITH = Settings.getString(Settings.KEYS.CVE_CPE_STARTS_WITH_FILTER, "cpe:/a:"); /** - * The text content of the node being processed. This can be used during the end element event. + * The text content of the node being processed. This can be used during the + * end element event. */ private StringBuilder nodeText = null; /** @@ -77,7 +78,8 @@ public class CPEHandler extends DefaultHandler { * @param localName the local name * @param qName the qualified name * @param attributes the attributes - * @throws SAXException thrown if there is an exception processing the element + * @throws SAXException thrown if there is an exception processing the + * element */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { @@ -128,7 +130,8 @@ public class CPEHandler extends DefaultHandler { * @param ch the char array * @param start the start position of the data read * @param length the length of the data read - * @throws SAXException thrown if there is an exception processing the characters + * @throws SAXException thrown if there is an exception processing the + * characters */ @Override public void characters(char[] ch, int start, int length) throws SAXException { @@ -138,12 +141,14 @@ public class CPEHandler extends DefaultHandler { } /** - * Handles the end element event. Stores the CPE data in the Cve Database if the cpe item node is ending. + * Handles the end element event. Stores the CPE data in the Cve Database if + * the cpe item node is ending. * * @param uri the element's uri * @param localName the local name * @param qName the qualified name - * @throws SAXException thrown if there is an exception processing the element + * @throws SAXException thrown if there is an exception processing the + * element */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { @@ -182,7 +187,8 @@ public class CPEHandler extends DefaultHandler { // /** - * A simple class to maintain information about the current element while parsing the CPE XML. + * A simple class to maintain information about the current element while + * parsing the CPE XML. */ protected static final class Element { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/UpdateableNvdCve.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/UpdateableNvdCve.java index 0d5762708..6df4e5fa6 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/UpdateableNvdCve.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/UpdateableNvdCve.java @@ -36,6 +36,9 @@ import org.slf4j.LoggerFactory; */ public class UpdateableNvdCve implements Iterable, Iterator { + /** + * A reference to the logger. + */ private static final Logger LOGGER = LoggerFactory.getLogger(UpdateableNvdCve.class); /** * A collection of sources of data. diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java index 1d7c65afc..4f5fe058a 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java @@ -140,6 +140,7 @@ public class ExceptionCollection extends Exception { * Adds an exception to the collection. * * @param ex the exception to add + * @param fatal flag indicating if this is a fatal error */ public void addException(Throwable ex, boolean fatal) { addException(ex); @@ -153,7 +154,7 @@ public class ExceptionCollection extends Exception { private boolean fatal = false; /** - * Get the value of fatal + * Get the value of fatal. * * @return the value of fatal */ @@ -162,7 +163,7 @@ public class ExceptionCollection extends Exception { } /** - * Set the value of fatal + * Set the value of fatal. * * @param fatal new value of fatal */ diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintHandler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintHandler.java index c5bd0f7b3..9634fb3d2 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintHandler.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintHandler.java @@ -197,11 +197,11 @@ public class HintHandler extends DefaultHandler { vendorDuplicatingHintRules.add(new VendorDuplicatingHintRule(attr.getValue(VALUE), attr.getValue(DUPLICATE))); } } - + /** * Handles the end element event. * - * @param uri the element's uri + * @param uri the element's URI * @param localName the local name * @param qName the qualified name * @throws SAXException thrown if there is an exception processing the diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/Hints.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/Hints.java index 0240d2fc1..34e465004 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/Hints.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/Hints.java @@ -32,7 +32,7 @@ public class Hints { private List hintRules; /** - * Get the value of hintRules + * Get the value of hintRules. * * @return the value of hintRules */ @@ -41,7 +41,7 @@ public class Hints { } /** - * Set the value of hintRules + * Set the value of hintRules. * * @param hintRules new value of hintRules */ @@ -55,7 +55,7 @@ public class Hints { private List vendorDuplicatingHintRules; /** - * Get the value of vendorDuplicatingHintRules + * Get the value of vendorDuplicatingHintRules. * * @return the value of vendorDuplicatingHintRules */ @@ -64,12 +64,11 @@ public class Hints { } /** - * Set the value of vendorDuplicatingHintRules + * Set the value of vendorDuplicatingHintRules. * * @param vendorDuplicatingHintRules new value of vendorDuplicatingHintRules */ public void setVendorDuplicatingHintRules(List vendorDuplicatingHintRules) { this.vendorDuplicatingHintRules = vendorDuplicatingHintRules; } - } diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java index 4b1d35b42..d17854dd0 100644 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java +++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java @@ -25,7 +25,6 @@ import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Set; -import org.apache.maven.MavenExecutionException; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.LifecyclePhase; @@ -130,9 +129,9 @@ public class AggregateMojo extends BaseDependencyCheckMojo { try { writeReports(engine, current, outputDir); } catch (ReportException ex) { - ExceptionCollection exCol = (ExceptionCollection) engine.getExecutionRoot().getContextValue(AGGREGATE_EXCEPTIONS); + ExceptionCollection exCol = (ExceptionCollection) engine.getExecutionRoot().getContextValue(AGGREGATE_EXCEPTIONS); if (exCol == null) { - exCol = new ExceptionCollection("Error writing aggregate report",ex); + exCol = new ExceptionCollection("Error writing aggregate report", ex); } else { exCol.addException(ex); } 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 8869a35ed..3df3f6d75 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 @@ -85,12 +85,13 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma /** * Returns if the mojo should fail the build if an exception occurs. + * * @return whether or not the mojo should fail the build */ protected boolean isFailOnError() { return failOnError; } - + /** * The Maven Project Object. */ @@ -1079,8 +1080,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma * scan data between the "check" and "aggregate" phase. * * @param project the Maven project to read the data file from - * @return a MavenEngine object populated with dependencies if the - * serialized data file exists; otherwise null is returned + * @return a MavenEngine object populated with dependencies if + * the serialized data file exists; otherwise null is returned */ protected List readDataFile(MavenProject project) { final Object oPath = project.getContextValue(this.getDataFileContextKey()); diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java index 270ceba39..ccada1b5c 100644 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java +++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java @@ -106,7 +106,7 @@ public class CheckMojo extends BaseDependencyCheckMojo { writeReports(engine, getProject(), getCorrectOutputDirectory()); } catch (ReportException ex) { if (this.isFailOnError()) { - if (exCol!= null) { + if (exCol != null) { exCol.addException(ex); } else { exCol = new ExceptionCollection("Unable to write the dependency-check report", ex); diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/UpdateMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/UpdateMojo.java index 33f8f172d..bedb80a7c 100644 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/UpdateMojo.java +++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/UpdateMojo.java @@ -111,5 +111,4 @@ public class UpdateMojo extends BaseDependencyCheckMojo { public String getDescription(Locale locale) { return "Updates the local cache of the NVD data from NIST."; } - } From c6ea92cff91ecc1a08da0dd5630560ddd918bfec Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sun, 24 Jul 2016 07:33:28 -0400 Subject: [PATCH 10/30] added links to the SBT plugin --- src/site/markdown/index.md | 5 +++-- src/site/markdown/modules.md | 10 ++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md index 81273af65..81a187625 100644 --- a/src/site/markdown/index.md +++ b/src/site/markdown/index.md @@ -28,11 +28,12 @@ More information about dependency-check can be found here: OWASP dependency-check's core analysis engine can be used as: -- [Command Line Tool](dependency-check-cli/index.html) -- [Maven Plugin](dependency-check-maven/index.html) - [Ant Task](dependency-check-ant/index.html) +- [Command Line Tool](dependency-check-cli/index.html) - [Gradle Plugin](dependency-check-gradle/index.html) - [Jenkins Plugin](dependency-check-jenkins/index.html) +- [Maven Plugin](dependency-check-maven/index.html) +- [SBT Plugin](https://github.com/albuch/sbt-dependency-check) For help with dependency-check the following resource can be used: diff --git a/src/site/markdown/modules.md b/src/site/markdown/modules.md index 1a0d027fc..012988c08 100644 --- a/src/site/markdown/modules.md +++ b/src/site/markdown/modules.md @@ -3,10 +3,12 @@ Modules OWASP dependency-check's core analysis engine was designed to fit into an applications normal build and reporting process: -- [Maven Plugin](dependency-check-maven/index.html) -- [Ant Task](dependency-check-ant/index.html) -- [Gradle Plugin](dependency-check-gradle/index.html) -- [Jenkins Plugin](dependency-check-jenkins/index.html) +- [Ant Task](dependency-check-ant/index.html) +- [Command Line Tool](dependency-check-cli/index.html) +- [Gradle Plugin](dependency-check-gradle/index.html) +- [Jenkins Plugin](dependency-check-jenkins/index.html) +- [Maven Plugin](dependency-check-maven/index.html) +- [SBT Plugin](https://github.com/albuch/sbt-dependency-check) In addition, dependency-check can be executed from the [command line](dependency-check-cli/index.html). From 5f76843c4a04891e3b894b2b9ae32b65b772c7f9 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sun, 24 Jul 2016 08:06:54 -0400 Subject: [PATCH 11/30] findbugs correction --- .../owasp/dependencycheck/exception/ExceptionCollection.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java index 4f5fe058a..cf0a1015f 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java @@ -86,6 +86,7 @@ public class ExceptionCollection extends Exception { */ public ExceptionCollection(Throwable exceptions, boolean fatal) { super(); + this.exceptions = new ArrayList(); this.exceptions.add(exceptions); this.fatal = fatal; } @@ -97,6 +98,7 @@ public class ExceptionCollection extends Exception { */ public ExceptionCollection(String msg, Throwable exception) { super(msg); + this.exceptions = new ArrayList(); this.exceptions.add(exception); this.fatal = false; } From f0a3482edad69d181c23ccd77852510ebb78bd73 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sun, 24 Jul 2016 08:07:39 -0400 Subject: [PATCH 12/30] findbugs correction --- .../utils/SSLSocketFactoryEx.java | 91 +++++++++---------- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java index 767cd6884..a59e415d9 100644 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java +++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java @@ -25,6 +25,7 @@ import org.slf4j.LoggerFactory; * The following code was copied from * http://stackoverflow.com/questions/1037590/which-cipher-suites-to-enable-for-ssl-socket/23365536#23365536 * + * @author jww */ public class SSLSocketFactoryEx extends SSLSocketFactory { @@ -77,7 +78,7 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { */ @Override public String[] getDefaultCipherSuites() { - return m_ciphers; + return Arrays.copyOf(ciphers, ciphers.length); } /** @@ -87,7 +88,7 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { */ @Override public String[] getSupportedCipherSuites() { - return m_ciphers; + return Arrays.copyOf(ciphers, ciphers.length); } /** @@ -96,7 +97,7 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { * @return the default protocols */ public String[] getDefaultProtocols() { - return m_protocols; + return Arrays.copyOf(protocols, protocols.length); } /** @@ -105,7 +106,7 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { * @return the supported protocols */ public String[] getSupportedProtocols() { - return m_protocols; + return Arrays.copyOf(protocols, protocols.length); } /** @@ -120,11 +121,11 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { */ @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { - SSLSocketFactory factory = m_ctx.getSocketFactory(); - SSLSocket ss = (SSLSocket) factory.createSocket(s, host, port, autoClose); + final SSLSocketFactory factory = sslCtxt.getSocketFactory(); + final SSLSocket ss = (SSLSocket) factory.createSocket(s, host, port, autoClose); - ss.setEnabledProtocols(m_protocols); - ss.setEnabledCipherSuites(m_ciphers); + ss.setEnabledProtocols(protocols); + ss.setEnabledCipherSuites(ciphers); return ss; } @@ -141,11 +142,11 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { */ @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { - SSLSocketFactory factory = m_ctx.getSocketFactory(); - SSLSocket ss = (SSLSocket) factory.createSocket(address, port, localAddress, localPort); + final SSLSocketFactory factory = sslCtxt.getSocketFactory(); + final SSLSocket ss = (SSLSocket) factory.createSocket(address, port, localAddress, localPort); - ss.setEnabledProtocols(m_protocols); - ss.setEnabledCipherSuites(m_ciphers); + ss.setEnabledProtocols(protocols); + ss.setEnabledCipherSuites(ciphers); return ss; } @@ -162,11 +163,11 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { */ @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { - SSLSocketFactory factory = m_ctx.getSocketFactory(); - SSLSocket ss = (SSLSocket) factory.createSocket(host, port, localHost, localPort); + final SSLSocketFactory factory = sslCtxt.getSocketFactory(); + final SSLSocket ss = (SSLSocket) factory.createSocket(host, port, localHost, localPort); - ss.setEnabledProtocols(m_protocols); - ss.setEnabledCipherSuites(m_ciphers); + ss.setEnabledProtocols(protocols); + ss.setEnabledCipherSuites(ciphers); return ss; } @@ -181,11 +182,11 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { */ @Override public Socket createSocket(InetAddress host, int port) throws IOException { - SSLSocketFactory factory = m_ctx.getSocketFactory(); - SSLSocket ss = (SSLSocket) factory.createSocket(host, port); + final SSLSocketFactory factory = sslCtxt.getSocketFactory(); + final SSLSocket ss = (SSLSocket) factory.createSocket(host, port); - ss.setEnabledProtocols(m_protocols); - ss.setEnabledCipherSuites(m_ciphers); + ss.setEnabledProtocols(protocols); + ss.setEnabledCipherSuites(ciphers); return ss; } @@ -200,11 +201,11 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { */ @Override public Socket createSocket(String host, int port) throws IOException { - SSLSocketFactory factory = m_ctx.getSocketFactory(); - SSLSocket ss = (SSLSocket) factory.createSocket(host, port); + final SSLSocketFactory factory = sslCtxt.getSocketFactory(); + final SSLSocket ss = (SSLSocket) factory.createSocket(host, port); - ss.setEnabledProtocols(m_protocols); - ss.setEnabledCipherSuites(m_ciphers); + ss.setEnabledProtocols(protocols); + ss.setEnabledCipherSuites(ciphers); return ss; } @@ -221,11 +222,11 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { */ private void initSSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random) throws NoSuchAlgorithmException, KeyManagementException { - m_ctx = SSLContext.getInstance("TLS"); - m_ctx.init(km, tm, random); + sslCtxt = SSLContext.getInstance("TLS"); + sslCtxt.init(km, tm, random); - m_protocols = getProtocolList(); - m_ciphers = getCipherList(); + protocols = getProtocolList(); + ciphers = getCipherList(); } /** @@ -238,10 +239,10 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { */ private void initSSLSocketFactoryEx(SSLContext ctx) throws NoSuchAlgorithmException, KeyManagementException { - m_ctx = ctx; + sslCtxt = ctx; - m_protocols = getProtocolList(); - m_ciphers = getCipherList(); + protocols = getProtocolList(); + ciphers = getCipherList(); } /** @@ -250,13 +251,13 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { * @return the protocol list */ protected String[] getProtocolList() { - String[] preferredProtocols = {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"}; + final String[] preferredProtocols = {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"}; String[] availableProtocols = null; SSLSocket socket = null; try { - SSLSocketFactory factory = m_ctx.getSocketFactory(); + final SSLSocketFactory factory = sslCtxt.getSocketFactory(); socket = (SSLSocket) factory.createSocket(); availableProtocols = socket.getSupportedProtocols(); @@ -274,9 +275,9 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { } } - List aa = new ArrayList(); + final List aa = new ArrayList(); for (String preferredProtocol : preferredProtocols) { - int idx = Arrays.binarySearch(availableProtocols, preferredProtocol); + final int idx = Arrays.binarySearch(availableProtocols, preferredProtocol); if (idx >= 0) { aa.add(preferredProtocol); } @@ -291,7 +292,7 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { * @return the cipher list */ protected String[] getCipherList() { - String[] preferredCiphers = { + final String[] preferredCiphers = { // *_CHACHA20_POLY1305 are 3x to 4x faster than existing cipher suites. // http://googleonlinesecurity.blogspot.com/2014/04/speeding-up-and-strengthening-https.html // Use them if available. Normative names can be found at (TLS spec depends on IPSec spec): @@ -332,13 +333,12 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { "TLS_RSA_WITH_AES_256_CBC_SHA256", "TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA256", - "TLS_RSA_WITH_AES_128_CBC_SHA" - }; + "TLS_RSA_WITH_AES_128_CBC_SHA",}; String[] availableCiphers; try { - SSLSocketFactory factory = m_ctx.getSocketFactory(); + final SSLSocketFactory factory = sslCtxt.getSocketFactory(); availableCiphers = factory.getSupportedCipherSuites(); Arrays.sort(availableCiphers); } catch (Exception e) { @@ -352,13 +352,12 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { "TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA", - "TLS_EMPTY_RENEGOTIATION_INFO_SCSV" - }; + "TLS_EMPTY_RENEGOTIATION_INFO_SCSV",}; } - List aa = new ArrayList(); + final List aa = new ArrayList(); for (String preferredCipher : preferredCiphers) { - int idx = Arrays.binarySearch(availableCiphers, preferredCipher); + final int idx = Arrays.binarySearch(availableCiphers, preferredCipher); if (idx >= 0) { aa.add(preferredCipher); } @@ -372,13 +371,13 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { /** * The SSL context. */ - private SSLContext m_ctx; + private SSLContext sslCtxt; /** * The cipher suites. */ - private String[] m_ciphers; + private String[] ciphers; /** * The protocols. */ - private String[] m_protocols; + private String[] protocols; } From 27a98f4244cbfd40ab2aca57e2a2ad88a61aa068 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sun, 24 Jul 2016 08:12:57 -0400 Subject: [PATCH 13/30] checckstyle corrections --- .../java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java | 5 +++-- .../org/owasp/dependencycheck/analyzer/HintAnalyzer.java | 2 +- .../org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java | 1 - .../java/org/owasp/dependencycheck/xml/hints/HintRule.java | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java index f66ec39bd..3733809c9 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java @@ -574,8 +574,9 @@ public class CPEAnalyzer implements Analyzer { final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8")); final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf); collected.add(match); - } else//TODO the following isn't quite right is it? need to think about this guessing game a bit more. - if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size() + + //TODO the following isn't quite right is it? need to think about this guessing game a bit more. + } else if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size() && evVer.matchesAtLeastThreeLevels(dbVer)) { if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) { if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java index 8bce5cd25..d550e7260 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java @@ -254,7 +254,7 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer { if (product.contains(zendframeworkProduct)) { dependency.getProductEvidence().addEvidence("hint analyzer", "vendor", "zend_framework", Confidence.HIGHEST); } - + //sun/oracle problem final Iterator itr = dependency.getVendorEvidence().iterator(); final List newEntries = new ArrayList(); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java index 692e4c4be..5caed2e4f 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java @@ -38,7 +38,6 @@ import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.RAMDirectory; -import org.owasp.dependencycheck.data.lucene.FieldAnalyzer; import org.owasp.dependencycheck.data.lucene.LuceneUtils; import org.owasp.dependencycheck.data.lucene.SearchFieldAnalyzer; import org.owasp.dependencycheck.data.nvdcve.CveDB; diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintRule.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintRule.java index ec85d98f2..1d9df8d4d 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintRule.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintRule.java @@ -72,9 +72,9 @@ public class HintRule { } /** - * Get the value of givenProduct + * Get the value of givenProduct. * - * @return the value of givenProduct. + * @return the value of givenProduct */ public List getGivenProduct() { return givenProduct; From 62f92db1818cc4a1a448b0f64bed9024dd74c3de Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sun, 24 Jul 2016 08:44:09 -0400 Subject: [PATCH 14/30] added issue template --- .github/issue_template.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/issue_template.md diff --git a/.github/issue_template.md b/.github/issue_template.md new file mode 100644 index 000000000..ed4fc41df --- /dev/null +++ b/.github/issue_template.md @@ -0,0 +1,18 @@ +### Reporting Bugs/Errors +When reporting errors, 99% of the time log file output is required. Please post the log file as a [gist](https://gist.github.com/) and provide a link in the new issue. + +### Reporting False Positives +When reporting a false positive please include: +- The location of the dependency (Maven GAV, URL to download the dependency, etc.) +- The CPE that is believed to be false positive + - Please report the CPE not the CVE + +##### Example +False positive on library foo.jar - reported as CPE:/a:apache:tomcat:7.0 +```xml + + org.sample + foo + 1.0 + +``` \ No newline at end of file From d09f75658c50a35ce46477124c0723bdf4c352a9 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sun, 24 Jul 2016 08:47:27 -0400 Subject: [PATCH 15/30] minor formating correction --- .github/issue_template.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/issue_template.md b/.github/issue_template.md index ed4fc41df..f2a77a5bc 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -7,8 +7,8 @@ When reporting a false positive please include: - The CPE that is believed to be false positive - Please report the CPE not the CVE -##### Example -False positive on library foo.jar - reported as CPE:/a:apache:tomcat:7.0 +#### Example +False positive on library foo.jar - reported as cpe:/a:apache:tomcat:7.0 ```xml org.sample From e9ec89dc9c6c59c3c43e111ea9668feadb63690b Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Wed, 27 Jul 2016 06:04:08 -0400 Subject: [PATCH 16/30] improved error handling --- .../dependencycheck/utils/Downloader.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Downloader.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Downloader.java index 7709f2d83..266d80b51 100644 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Downloader.java +++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Downloader.java @@ -32,6 +32,7 @@ import java.security.InvalidAlgorithmParameterException; import java.util.zip.GZIPInputStream; import java.util.zip.InflaterInputStream; import static java.lang.String.format; +import static java.lang.String.format; /** * A utility to download files from the Internet. @@ -175,7 +176,7 @@ public final class Downloader { } LOGGER.debug("Download of {} complete", url.toString()); } catch (IOException ex) { - checkForSslExceptionn(ex); + checkForCommonExceptionTypes(ex); final String msg = format("Error saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n", url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding); throw new DownloadFailedException(msg, ex); @@ -261,10 +262,11 @@ public final class Downloader { } catch (URLConnectionFailureException ex) { throw new DownloadFailedException(format("Error creating URL Connection for HTTP %s request.", httpMethod), ex); } catch (IOException ex) { - checkForSslExceptionn(ex); - LOGGER.error("IO Exception: " + ex.getMessage(), ex); + checkForCommonExceptionTypes(ex); + LOGGER.error("IO Exception: " + ex.getMessage()); + LOGGER.debug("Exception details", ex); if (ex.getCause() != null) { - LOGGER.error("IO Exception cause: " + ex.getCause().getMessage(), ex.getCause()); + LOGGER.debug("IO Exception cause: " + ex.getCause().getMessage(), ex.getCause()); } try { //retry @@ -292,15 +294,21 @@ public final class Downloader { /** * Analyzes the IOException, logs the appropriate information for debugging * purposes, and then throws a DownloadFailedException that wraps the IO - * Exception. + * Exception for common IO Exceptions. This is to provide additional details + * to assist in resolution of the exception. * * @param ex the original exception * @throws DownloadFailedException a wrapper exception that contains the * original exception as the cause */ - protected static void checkForSslExceptionn(IOException ex) throws DownloadFailedException { + protected static void checkForCommonExceptionTypes(IOException ex) throws DownloadFailedException { Throwable cause = ex; while (cause != null) { + if (cause instanceof java.net.UnknownHostException) { + final String msg = String.format("Unable to resolve domain '%s'", cause.getMessage()); + LOGGER.error(msg); + throw new DownloadFailedException(msg); + } if (cause instanceof InvalidAlgorithmParameterException) { final String keystore = System.getProperty("javax.net.ssl.keyStore"); final String version = System.getProperty("java.version"); @@ -315,6 +323,7 @@ public final class Downloader { cause = cause.getCause(); } } + /** * Returns the HEAD or GET HTTP method. HEAD is the default. From ba15de22183585ac51c4b024fb8fd96ed1ab2e8a Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Wed, 27 Jul 2016 06:04:56 -0400 Subject: [PATCH 17/30] improved error handling --- .../src/main/java/org/owasp/dependencycheck/App.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java index af8b2271b..5d3a8fa18 100644 --- a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java +++ b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java @@ -66,6 +66,7 @@ public class App { Settings.initialize(); final App app = new App(); exitCode = app.run(args); + LOGGER.debug("Exit code: " + exitCode); } finally { Settings.cleanup(true); } @@ -292,11 +293,15 @@ public class App { throw ex; } } + if (exCol != null && exCol.getExceptions().size()>0) { + throw exCol; + } } finally { if (engine != null) { engine.cleanup(); } } + } /** From bed04150e1684cf7af16f4f5c91670a5c5eccd6c Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Wed, 27 Jul 2016 06:23:56 -0400 Subject: [PATCH 18/30] reverted H2 upgrade due to issues with Jenkins and Java 6 compatability --- .../src/main/resources/dependencycheck.properties | 2 +- .../src/test/resources/dependencycheck.properties | 2 +- .../src/test/resources/dependencycheck.properties | 2 +- pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dependency-check-core/src/main/resources/dependencycheck.properties b/dependency-check-core/src/main/resources/dependencycheck.properties index 023b7cf1f..def5b8d86 100644 --- a/dependency-check-core/src/main/resources/dependencycheck.properties +++ b/dependency-check-core/src/main/resources/dependencycheck.properties @@ -24,7 +24,7 @@ data.file_name=dc.h2.db ### the gradle PurgeDataExtension. data.version=3.0 -data.connection_string=jdbc:h2:file:%s;FILE_LOCK=FS;AUTOCOMMIT=ON; +data.connection_string=jdbc:h2:file:%s;FILE_LOCK=SERIALIZED;AUTOCOMMIT=ON; #data.connection_string=jdbc:mysql://localhost:3306/dependencycheck # user name and password for the database connection. The inherent case is to use H2. diff --git a/dependency-check-core/src/test/resources/dependencycheck.properties b/dependency-check-core/src/test/resources/dependencycheck.properties index e6b2ca6d4..ed207a3ff 100644 --- a/dependency-check-core/src/test/resources/dependencycheck.properties +++ b/dependency-check-core/src/test/resources/dependencycheck.properties @@ -19,7 +19,7 @@ data.directory=[JAR]/data #if the filename has a %s it will be replaced with the current expected version data.file_name=dc.h2.db data.version=3.0 -data.connection_string=jdbc:h2:file:%s;FILE_LOCK=FS;AUTOCOMMIT=ON; +data.connection_string=jdbc:h2:file:%s;FILE_LOCK=SERIALIZED;AUTOCOMMIT=ON; #data.connection_string=jdbc:mysql://localhost:3306/dependencycheck # user name and password for the database connection. The inherent case is to use H2. diff --git a/dependency-check-utils/src/test/resources/dependencycheck.properties b/dependency-check-utils/src/test/resources/dependencycheck.properties index 61c98f91e..49f47d480 100644 --- a/dependency-check-utils/src/test/resources/dependencycheck.properties +++ b/dependency-check-utils/src/test/resources/dependencycheck.properties @@ -18,7 +18,7 @@ engine.version.url=http://jeremylong.github.io/DependencyCheck/current.txt data.directory=[JAR]/data data.file_name=dc.h2.db data.version=3.0 -data.connection_string=jdbc:h2:file:%s;FILE_LOCK=FS;AUTOCOMMIT=ON; +data.connection_string=jdbc:h2:file:%s;FILE_LOCK=SERIALIZED;AUTOCOMMIT=ON; #data.connection_string=jdbc:h2:file:%s;AUTO_SERVER=TRUE;AUTOCOMMIT=ON; #data.connection_string=jdbc:mysql://localhost:3306/dependencycheck diff --git a/pom.xml b/pom.xml index ea4677b69..0576d574c 100644 --- a/pom.xml +++ b/pom.xml @@ -551,7 +551,7 @@ Copyright (c) 2012 - Jeremy Long com.h2database h2 - 1.4.192 + 1.3.176 commons-cli From f7a0982ca0e8547f9b5db896cecea24a413c6fb4 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Fri, 29 Jul 2016 06:12:40 -0400 Subject: [PATCH 19/30] checkstyle corrections --- .../java/org/owasp/dependencycheck/utils/Downloader.java | 2 -- .../org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java | 6 ++++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Downloader.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Downloader.java index 266d80b51..894c2fab2 100644 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Downloader.java +++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Downloader.java @@ -32,7 +32,6 @@ import java.security.InvalidAlgorithmParameterException; import java.util.zip.GZIPInputStream; import java.util.zip.InflaterInputStream; import static java.lang.String.format; -import static java.lang.String.format; /** * A utility to download files from the Internet. @@ -323,7 +322,6 @@ public final class Downloader { cause = cause.getCause(); } } - /** * Returns the HEAD or GET HTTP method. HEAD is the default. diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java index a59e415d9..727eb24f7 100644 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java +++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.java @@ -333,7 +333,8 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { "TLS_RSA_WITH_AES_256_CBC_SHA256", "TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA256", - "TLS_RSA_WITH_AES_128_CBC_SHA",}; + "TLS_RSA_WITH_AES_128_CBC_SHA", + }; String[] availableCiphers; @@ -352,7 +353,8 @@ public class SSLSocketFactoryEx extends SSLSocketFactory { "TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA", - "TLS_EMPTY_RENEGOTIATION_INFO_SCSV",}; + "TLS_EMPTY_RENEGOTIATION_INFO_SCSV", + }; } final List aa = new ArrayList(); From d22c920b35eeb74cc4f9e3906a39eb4986b7610b Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sat, 30 Jul 2016 06:52:48 -0400 Subject: [PATCH 20/30] version 1.4.1 --- dependency-check-ant/pom.xml | 2 +- dependency-check-cli/pom.xml | 2 +- dependency-check-core/pom.xml | 2 +- dependency-check-maven/pom.xml | 2 +- dependency-check-utils/pom.xml | 2 +- pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dependency-check-ant/pom.xml b/dependency-check-ant/pom.xml index 99ec93329..4febe6c7e 100644 --- a/dependency-check-ant/pom.xml +++ b/dependency-check-ant/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.4.1-SNAPSHOT + 1.4.1 dependency-check-ant diff --git a/dependency-check-cli/pom.xml b/dependency-check-cli/pom.xml index 29689775e..10f2153f9 100644 --- a/dependency-check-cli/pom.xml +++ b/dependency-check-cli/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.4.1-SNAPSHOT + 1.4.1 dependency-check-cli diff --git a/dependency-check-core/pom.xml b/dependency-check-core/pom.xml index 387601cdd..7be6e9dfa 100644 --- a/dependency-check-core/pom.xml +++ b/dependency-check-core/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.4.1-SNAPSHOT + 1.4.1 dependency-check-core diff --git a/dependency-check-maven/pom.xml b/dependency-check-maven/pom.xml index aa33ce2f8..d24b06344 100644 --- a/dependency-check-maven/pom.xml +++ b/dependency-check-maven/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.4.1-SNAPSHOT + 1.4.1 dependency-check-maven diff --git a/dependency-check-utils/pom.xml b/dependency-check-utils/pom.xml index 709ab9f4c..edeef7265 100644 --- a/dependency-check-utils/pom.xml +++ b/dependency-check-utils/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.4.1-SNAPSHOT + 1.4.1 dependency-check-utils diff --git a/pom.xml b/pom.xml index 0576d574c..9ca41cae1 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long org.owasp dependency-check-parent - 1.4.1-SNAPSHOT + 1.4.1 pom From 71e7412f158636355a1318c01ba7084ccde259d6 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sun, 31 Jul 2016 07:32:30 -0400 Subject: [PATCH 21/30] corrected example --- .../src/site/markdown/index.md.vm | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/dependency-check-maven/src/site/markdown/index.md.vm b/dependency-check-maven/src/site/markdown/index.md.vm index 49312f4ba..c4e5c1c2a 100644 --- a/dependency-check-maven/src/site/markdown/index.md.vm +++ b/dependency-check-maven/src/site/markdown/index.md.vm @@ -53,18 +53,16 @@ Create an aggregated dependency-check report within the site. ... - - org.owasp - dependency-check-maven - ${project.version} - - - - aggregate - - - - + org.owasp + dependency-check-maven + ${project.version} + + + + aggregate + + + ... From 84c6dd5dfab42f35df820dce9a9f28c56885927a Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sun, 31 Jul 2016 07:34:09 -0400 Subject: [PATCH 22/30] resolved gradle issue 14 - https://github.com/jeremylong/dependency-check-gradle/issues/14 --- .../java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java | 2 +- .../xml/suppression/SuppressionErrorHandler.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java index d550e7260..5c206037b 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java @@ -292,7 +292,7 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer { LOGGER.error("Unable to parse the base hint data file"); LOGGER.debug("Unable to parse the base hint data file", ex); } - final String filePath = Settings.getString(Settings.KEYS.SUPPRESSION_FILE); + final String filePath = Settings.getString(Settings.KEYS.HINTS_FILE); if (filePath == null) { return; } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionErrorHandler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionErrorHandler.java index bacbcb5a0..e36bc5365 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionErrorHandler.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionErrorHandler.java @@ -70,7 +70,7 @@ public class SuppressionErrorHandler implements ErrorHandler { */ @Override public void warning(SAXParseException ex) throws SAXException { - LOGGER.debug("", ex); + //LOGGER.debug("", ex); } /** From 6bd7d6b07854e646ef02f61aa8258d0850951b5a Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sun, 31 Jul 2016 08:01:47 -0400 Subject: [PATCH 23/30] version 1.4.2 --- dependency-check-ant/pom.xml | 2 +- dependency-check-cli/pom.xml | 2 +- dependency-check-core/pom.xml | 2 +- dependency-check-maven/pom.xml | 2 +- dependency-check-utils/pom.xml | 2 +- pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dependency-check-ant/pom.xml b/dependency-check-ant/pom.xml index 4febe6c7e..b7128fd00 100644 --- a/dependency-check-ant/pom.xml +++ b/dependency-check-ant/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.4.1 + 1.4.2 dependency-check-ant diff --git a/dependency-check-cli/pom.xml b/dependency-check-cli/pom.xml index 10f2153f9..a36ddab5b 100644 --- a/dependency-check-cli/pom.xml +++ b/dependency-check-cli/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.4.1 + 1.4.2 dependency-check-cli diff --git a/dependency-check-core/pom.xml b/dependency-check-core/pom.xml index 7be6e9dfa..67d1ae561 100644 --- a/dependency-check-core/pom.xml +++ b/dependency-check-core/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.4.1 + 1.4.2 dependency-check-core diff --git a/dependency-check-maven/pom.xml b/dependency-check-maven/pom.xml index d24b06344..6e4170749 100644 --- a/dependency-check-maven/pom.xml +++ b/dependency-check-maven/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.4.1 + 1.4.2 dependency-check-maven diff --git a/dependency-check-utils/pom.xml b/dependency-check-utils/pom.xml index edeef7265..6d2ecd5f7 100644 --- a/dependency-check-utils/pom.xml +++ b/dependency-check-utils/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.4.1 + 1.4.2 dependency-check-utils diff --git a/pom.xml b/pom.xml index 9ca41cae1..c2bf01d42 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long org.owasp dependency-check-parent - 1.4.1 + 1.4.2 pom From d9ce3cda66816af5b54e63db84339c2f7cfcd5ea Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Thu, 11 Aug 2016 20:09:34 -0400 Subject: [PATCH 24/30] snapshot version --- dependency-check-ant/pom.xml | 2 +- dependency-check-cli/pom.xml | 2 +- dependency-check-core/pom.xml | 2 +- dependency-check-maven/pom.xml | 2 +- dependency-check-utils/pom.xml | 2 +- pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dependency-check-ant/pom.xml b/dependency-check-ant/pom.xml index b7128fd00..9c6685dd1 100644 --- a/dependency-check-ant/pom.xml +++ b/dependency-check-ant/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.4.2 + 1.4.3-SNAPSHOT dependency-check-ant diff --git a/dependency-check-cli/pom.xml b/dependency-check-cli/pom.xml index a36ddab5b..584a4a72b 100644 --- a/dependency-check-cli/pom.xml +++ b/dependency-check-cli/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.4.2 + 1.4.3-SNAPSHOT dependency-check-cli diff --git a/dependency-check-core/pom.xml b/dependency-check-core/pom.xml index 67d1ae561..dd7419c56 100644 --- a/dependency-check-core/pom.xml +++ b/dependency-check-core/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.4.2 + 1.4.3-SNAPSHOT dependency-check-core diff --git a/dependency-check-maven/pom.xml b/dependency-check-maven/pom.xml index 6e4170749..d6f48ff87 100644 --- a/dependency-check-maven/pom.xml +++ b/dependency-check-maven/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.4.2 + 1.4.3-SNAPSHOT dependency-check-maven diff --git a/dependency-check-utils/pom.xml b/dependency-check-utils/pom.xml index 6d2ecd5f7..c5c10da90 100644 --- a/dependency-check-utils/pom.xml +++ b/dependency-check-utils/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.4.2 + 1.4.3-SNAPSHOT dependency-check-utils diff --git a/pom.xml b/pom.xml index c2bf01d42..3df61fcb1 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long org.owasp dependency-check-parent - 1.4.2 + 1.4.3-SNAPSHOT pom From c4d662fd2b47a59ff73adcdf1fed34779b727f4f Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Thu, 11 Aug 2016 20:49:27 -0400 Subject: [PATCH 25/30] patch for issue #536 --- .../org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java index 470d13e2a..62e502254 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java @@ -441,6 +441,8 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer { } } } + } else { + in.reset(); } } } From 45941adb71327309ef2f1d931bf7c4d674035c5c Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Thu, 11 Aug 2016 20:55:36 -0400 Subject: [PATCH 26/30] fixed type per issue #533 --- .../main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java | 2 +- .../src/main/java/org/owasp/dependencycheck/utils/Settings.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java index 48388a983..8b770ec66 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java @@ -658,7 +658,7 @@ public class CveDB { + "If the problem persist try deleting the files in '{}' and running {} again. If the problem continues, please " + "create a log file (see documentation at http://jeremylong.github.io/DependencyCheck/) and open a ticket at " + "https://github.com/jeremylong/DependencyCheck/issues and include the log file.\n\n", - dd, dd, Settings.getString(Settings.KEYS.APPLICATION_VAME)); + dd, dd, Settings.getString(Settings.KEYS.APPLICATION_NAME)); LOGGER.debug("", ex); } finally { DBUtils.closeResultSet(rs); 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 bacc4870a..de6f4d7e1 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 @@ -55,7 +55,7 @@ public final class Settings { /** * The key to obtain the application name. */ - public static final String APPLICATION_VAME = "application.name"; + public static final String APPLICATION_NAME = "application.name"; /** * The key to obtain the application version. */ From 9ea16ad1d11172177b780f3113ce5a857634ab92 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Thu, 11 Aug 2016 20:59:26 -0400 Subject: [PATCH 27/30] skipped patch for Java 1.6 & 1.7 if the JRE is at least 1.8 - see issue #523 --- .../org/owasp/dependencycheck/utils/URLConnectionFactory.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java index bfbb52773..8a50a33cc 100644 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java +++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java @@ -31,6 +31,8 @@ import java.net.URL; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import javax.net.ssl.HttpsURLConnection; +import org.apache.commons.lang3.JavaVersion; +import org.apache.commons.lang3.SystemUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -189,7 +191,7 @@ public final class URLConnectionFactory { * @param conn the connection */ private static void configureTLS(URL url, HttpURLConnection conn) { - if ("https".equals(url.getProtocol())) { + if ("https".equals(url.getProtocol()) && !SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8)) { try { final HttpsURLConnection secCon = (HttpsURLConnection) conn; final SSLSocketFactoryEx factory = new SSLSocketFactoryEx(); From d2158e5e44342a9cce5bbfa67d212750769d17d4 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Thu, 11 Aug 2016 21:12:47 -0400 Subject: [PATCH 28/30] fixed typo --- .../src/main/java/org/owasp/dependencycheck/CliParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 d2e522834..19d826bf3 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 @@ -966,7 +966,7 @@ public final class CliParser { */ public void printVersionInfo() { final String version = String.format("%s version %s", - Settings.getString(Settings.KEYS.APPLICATION_VAME, "dependency-check"), + Settings.getString(Settings.KEYS.APPLICATION_NAME, "dependency-check"), Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown")); System.out.println(version); } From 74282c8ac5422beee0a689b86b501b419a7129a6 Mon Sep 17 00:00:00 2001 From: bjiang Date: Fri, 12 Aug 2016 13:15:29 -0400 Subject: [PATCH 29/30] filter out version from jar filename for name --- .../analyzer/FileNameAnalyzer.java | 9 +++--- .../utils/DependencyVersionUtil.java | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.java index fcaaeb102..5e6dee5b8 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.java @@ -93,26 +93,27 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer { //add version evidence final DependencyVersion version = DependencyVersionUtil.parseVersion(fileName); + final String packageName = DependencyVersionUtil.parsePreVersion(fileName); if (version != null) { // If the version number is just a number like 2 or 23, reduce the confidence // a shade. This should hopefully correct for cases like log4j.jar or // struts2-core.jar if (version.getVersionParts() == null || version.getVersionParts().size() < 2) { - dependency.getVersionEvidence().addEvidence("file", "name", + dependency.getVersionEvidence().addEvidence("file", "version", version.toString(), Confidence.MEDIUM); } else { dependency.getVersionEvidence().addEvidence("file", "version", version.toString(), Confidence.HIGHEST); } dependency.getVersionEvidence().addEvidence("file", "name", - fileName, Confidence.MEDIUM); + packageName, Confidence.MEDIUM); } if (!IGNORED_FILES.accept(f)) { dependency.getProductEvidence().addEvidence("file", "name", - fileName, Confidence.HIGH); + packageName, Confidence.HIGH); dependency.getVendorEvidence().addEvidence("file", "name", - fileName, Confidence.HIGH); + packageName, Confidence.HIGH); } } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DependencyVersionUtil.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DependencyVersionUtil.java index 483413dcb..b91510b1e 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DependencyVersionUtil.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DependencyVersionUtil.java @@ -39,6 +39,11 @@ public final class DependencyVersionUtil { * are missing a version number using the previous regex. */ private static final Pattern RX_SINGLE_VERSION = Pattern.compile("\\d+(\\.?([_-](release|beta|alpha)|[a-zA-Z_-]{1,3}\\d{1,8}))?"); + + /** + * Regular expression to extract the part before the version numbers if there are any based on RX_VERSION. In most cases, this part represents a more accurate name. + */ + private static final Pattern RX_PRE_VERSION = Pattern.compile("^(.+)[_-](\\d+\\.\\d{1,6})+"); /** * Private constructor for utility class. @@ -95,4 +100,27 @@ public final class DependencyVersionUtil { } return new DependencyVersion(version); } + + /** + *

+ * A utility class to extract the part before version numbers from file names (or other strings containing version numbers. + * In most cases, this part represents a more accurate name than the full file name.

+ *
+     * Example:
+     * Give the file name: library-name-1.4.1r2-release.jar
+     * This function would return: library-name
+ * + * @param text the text being analyzed + * @return the part before the version numbers if any, otherwise return the text itself. + */ + public static String parsePreVersion(String text) { + if(parseVersion(text) == null) + return text; + + Matcher matcher = RX_PRE_VERSION.matcher(text); + if (matcher.find()) { + return matcher.group(1); + } + return text; + } } From 8cd377b99f857772277a452a11134227507a14c3 Mon Sep 17 00:00:00 2001 From: bjiang Date: Fri, 12 Aug 2016 13:32:25 -0400 Subject: [PATCH 30/30] use value of specification-version as version from Manifest --- .../java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java index fed1824a9..9edbcf6ab 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java @@ -685,7 +685,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { foundSomething = true; versionEvidence.addEvidence(source, key, value, Confidence.HIGH); } else if ("specification-version".equalsIgnoreCase(key)) { - specificationVersion = key; + specificationVersion = value; } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) { foundSomething = true; vendorEvidence.addEvidence(source, key, value, Confidence.HIGH);