From 6f451736ba7d8c0aade2c2aec48dd04528475595 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sat, 14 May 2016 07:20:53 -0400 Subject: [PATCH 1/3] Add ability to flag analyzers as experimental so that they are not always enabled --- .../owasp/dependencycheck/taskdefs/Check.java | 24 ++ .../src/site/markdown/configuration.md | 3 +- .../java/org/owasp/dependencycheck/App.java | 2 + .../org/owasp/dependencycheck/CliParser.java | 253 ++++++++++++------ .../src/site/markdown/arguments.md | 2 +- .../org/owasp/dependencycheck/Engine.java | 5 +- .../analyzer/AnalyzerService.java | 37 ++- .../analyzer/AutoconfAnalyzer.java | 1 + .../analyzer/CMakeAnalyzer.java | 1 + .../analyzer/Experimental.java | 34 +++ .../analyzer/NodePackageAnalyzer.java | 1 + .../main/resources/dependencycheck.properties | 9 +- .../analyzer/AnalyzerServiceTest.java | 36 ++- .../test/resources/dependencycheck.properties | 8 +- .../maven/BaseDependencyCheckMojo.java | 141 ++++++---- .../src/site/markdown/configuration.md | 7 +- .../owasp/dependencycheck/utils/Settings.java | 30 ++- 17 files changed, 412 insertions(+), 182 deletions(-) create mode 100644 dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/Experimental.java 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 cfefeb27c..fc4fc9d3b 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 @@ -361,6 +361,29 @@ public class Check extends Update { this.showSummary = showSummary; } + /** + * Whether experimental analyzers are enabled. + */ + private Boolean enableExperimental; + + /** + * Get the value of enableExperimental. + * + * @return the value of enableExperimental + */ + public Boolean isEnableExperimental() { + return enableExperimental; + } + + /** + * Set the value of enableExperimental. + * + * @param enableExperimental new value of enableExperimental + */ + public void setEnableExperimental(Boolean enableExperimental) { + this.enableExperimental = enableExperimental; + } + /** * Whether or not the Jar Analyzer is enabled. */ @@ -854,6 +877,7 @@ public class Check extends Update { super.populateSettings(); Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate); Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental); Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled); Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled); Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled); diff --git a/dependency-check-ant/src/site/markdown/configuration.md b/dependency-check-ant/src/site/markdown/configuration.md index dafc18355..a58b73716 100644 --- a/dependency-check-ant/src/site/markdown/configuration.md +++ b/dependency-check-ant/src/site/markdown/configuration.md @@ -27,7 +27,7 @@ the project's dependencies. Configuration: dependency-check Task -------------------- -The following properties can be set on the dependency-check-update task. +The following properties can be set on the dependency-check task. Property | Description | Default Value ----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------- @@ -43,6 +43,7 @@ proxyPort | The Proxy Port. proxyUsername | Defines the proxy user name. |   proxyPassword | Defines the proxy password. |   connectionTimeout | The URL Connection Timeout. |   +enableExperimental | Enable the experimental analyzers. | false Analyzer Configuration ==================== 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 f34108383..c8bc71cd6 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 @@ -280,6 +280,7 @@ public class App { final String cveBase12 = cli.getBaseCve12Url(); final String cveBase20 = cli.getBaseCve20Url(); final Integer cveValidForHours = cli.getCveValidForHours(); + final boolean experimentalEnabled = cli.isExperimentalEnabled(); if (propertiesFile != null) { try { @@ -318,6 +319,7 @@ public class App { Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours); //File Type Analyzer Settings + Settings.setBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, experimentalEnabled); Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !cli.isJarDisabled()); Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, !cli.isArchiveDisabled()); Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, !cli.isPythonDistributionDisabled()); 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 33ffc841b..d2e522834 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 @@ -58,7 +58,8 @@ public final class CliParser { * Parses the arguments passed in and captures the results for later use. * * @param args the command line arguments - * @throws FileNotFoundException is thrown when a 'file' argument does not point to a file that exists. + * @throws FileNotFoundException is thrown when a 'file' argument does not + * point to a file that exists. * @throws ParseException is thrown when a Parse Exception occurs. */ public void parse(String[] args) throws FileNotFoundException, ParseException { @@ -85,9 +86,10 @@ public final class CliParser { /** * Validates that the command line arguments are valid. * - * @throws FileNotFoundException if there is a file specified by either the SCAN or CPE command line arguments that does not - * exist. - * @throws ParseException is thrown if there is an exception parsing the command line. + * @throws FileNotFoundException if there is a file specified by either the + * SCAN or CPE command line arguments that does not exist. + * @throws ParseException is thrown if there is an exception parsing the + * command line. */ private void validateArgs() throws FileNotFoundException, ParseException { if (isUpdateOnly() || isRunScan()) { @@ -141,12 +143,14 @@ public final class CliParser { } /** - * Validates whether or not the path(s) points at a file that exists; if the path(s) does not point to an existing file a - * FileNotFoundException is thrown. + * Validates whether or not the path(s) points at a file that exists; if the + * path(s) does not point to an existing file a FileNotFoundException is + * thrown. * * @param paths the paths to validate if they exists * @param optType the option being validated (e.g. scan, out, etc.) - * @throws FileNotFoundException is thrown if one of the paths being validated does not exist. + * @throws FileNotFoundException is thrown if one of the paths being + * validated does not exist. */ private void validatePathExists(String[] paths, String optType) throws FileNotFoundException { for (String path : paths) { @@ -155,12 +159,14 @@ public final class CliParser { } /** - * Validates whether or not the path points at a file that exists; if the path does not point to an existing file a - * FileNotFoundException is thrown. + * Validates whether or not the path points at a file that exists; if the + * path does not point to an existing file a FileNotFoundException is + * thrown. * * @param path the paths to validate if they exists * @param argumentName the argument being validated (e.g. scan, out, etc.) - * @throws FileNotFoundException is thrown if the path being validated does not exist. + * @throws FileNotFoundException is thrown if the path being validated does + * not exist. */ private void validatePathExists(String path, String argumentName) throws FileNotFoundException { if (path == null) { @@ -181,12 +187,10 @@ public final class CliParser { throw new FileNotFoundException(msg); } } - } else { - if (!f.exists()) { - isValid = false; - final String msg = String.format("Invalid '%s' argument: '%s'", argumentName, path); - throw new FileNotFoundException(msg); - } + } else if (!f.exists()) { + isValid = false; + final String msg = String.format("Invalid '%s' argument: '%s'", argumentName, path); + throw new FileNotFoundException(msg); } } else if (path.startsWith("//") || path.startsWith("\\\\")) { isValid = false; @@ -196,7 +200,8 @@ public final class CliParser { } /** - * Generates an Options collection that is used to parse the command line and to display the help message. + * Generates an Options collection that is used to parse the command line + * and to display the help message. * * @return the command line options used for parsing the command line */ @@ -272,6 +277,10 @@ public final class CliParser { .desc("The number of hours to wait before checking for new updates from the NVD.") .build(); + final Option experimentalEnabled = Option.builder().longOpt(ARGUMENT.EXPERIMENTAL) + .desc("Enables the experimental analzers.") + .build(); + //This is an option group because it can be specified more then once. final OptionGroup og = new OptionGroup(); og.addOption(path); @@ -292,12 +301,14 @@ public final class CliParser { .addOption(props) .addOption(verboseLog) .addOption(suppressionFile) - .addOption(cveValidForHours); + .addOption(cveValidForHours) + .addOption(experimentalEnabled); } /** - * Adds the advanced command line options to the given options collection. These are split out for purposes of being able to - * display two different help messages. + * Adds the advanced command line options to the given options collection. + * These are split out for purposes of being able to display two different + * help messages. * * @param options a collection of command line arguments * @throws IllegalArgumentException thrown if there is an exception @@ -466,8 +477,10 @@ public final class CliParser { } /** - * Adds the deprecated command line options to the given options collection. These are split out for purposes of not including - * them in the help message. We need to add the deprecated options so as not to break existing scripts. + * Adds the deprecated command line options to the given options collection. + * These are split out for purposes of not including them in the help + * message. We need to add the deprecated options so as not to break + * existing scripts. * * @param options a collection of command line arguments * @throws IllegalArgumentException thrown if there is an exception @@ -514,7 +527,8 @@ public final class CliParser { } /** - * Returns the symbolic link depth (how deeply symbolic links will be followed). + * Returns the symbolic link depth (how deeply symbolic links will be + * followed). * * @return the symbolic link depth */ @@ -534,7 +548,8 @@ public final class CliParser { /** * Returns true if the disableJar command line argument was specified. * - * @return true if the disableJar command line argument was specified; otherwise false + * @return true if the disableJar command line argument was specified; + * otherwise false */ public boolean isJarDisabled() { return (line != null) && line.hasOption(ARGUMENT.DISABLE_JAR); @@ -543,7 +558,8 @@ public final class CliParser { /** * Returns true if the disableArchive command line argument was specified. * - * @return true if the disableArchive command line argument was specified; otherwise false + * @return true if the disableArchive command line argument was specified; + * otherwise false */ public boolean isArchiveDisabled() { return (line != null) && line.hasOption(ARGUMENT.DISABLE_ARCHIVE); @@ -552,7 +568,8 @@ public final class CliParser { /** * Returns true if the disableNuspec command line argument was specified. * - * @return true if the disableNuspec command line argument was specified; otherwise false + * @return true if the disableNuspec command line argument was specified; + * otherwise false */ public boolean isNuspecDisabled() { return (line != null) && line.hasOption(ARGUMENT.DISABLE_NUSPEC); @@ -561,16 +578,19 @@ public final class CliParser { /** * Returns true if the disableAssembly command line argument was specified. * - * @return true if the disableAssembly command line argument was specified; otherwise false + * @return true if the disableAssembly command line argument was specified; + * otherwise false */ public boolean isAssemblyDisabled() { return (line != null) && line.hasOption(ARGUMENT.DISABLE_ASSEMBLY); } /** - * Returns true if the disableBundleAudit command line argument was specified. + * Returns true if the disableBundleAudit command line argument was + * specified. * - * @return true if the disableBundleAudit command line argument was specified; otherwise false + * @return true if the disableBundleAudit command line argument was + * specified; otherwise false */ public boolean isBundleAuditDisabled() { return (line != null) && line.hasOption(ARGUMENT.DISABLE_BUNDLE_AUDIT); @@ -579,7 +599,8 @@ public final class CliParser { /** * Returns true if the disablePyDist command line argument was specified. * - * @return true if the disablePyDist command line argument was specified; otherwise false + * @return true if the disablePyDist command line argument was specified; + * otherwise false */ public boolean isPythonDistributionDisabled() { return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_DIST); @@ -588,7 +609,8 @@ public final class CliParser { /** * Returns true if the disablePyPkg command line argument was specified. * - * @return true if the disablePyPkg command line argument was specified; otherwise false + * @return true if the disablePyPkg command line argument was specified; + * otherwise false */ public boolean isPythonPackageDisabled() { return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_PKG); @@ -597,7 +619,8 @@ public final class CliParser { /** * Returns whether the Ruby gemspec analyzer is disabled. * - * @return true if the {@link ARGUMENT#DISABLE_RUBYGEMS} command line argument was specified; otherwise false + * @return true if the {@link ARGUMENT#DISABLE_RUBYGEMS} command line + * argument was specified; otherwise false */ public boolean isRubyGemspecDisabled() { return (null != line) && line.hasOption(ARGUMENT.DISABLE_RUBYGEMS); @@ -606,7 +629,8 @@ public final class CliParser { /** * Returns true if the disableCmake command line argument was specified. * - * @return true if the disableCmake command line argument was specified; otherwise false + * @return true if the disableCmake command line argument was specified; + * otherwise false */ public boolean isCmakeDisabled() { return (line != null) && line.hasOption(ARGUMENT.DISABLE_CMAKE); @@ -615,7 +639,8 @@ public final class CliParser { /** * Returns true if the disableAutoconf command line argument was specified. * - * @return true if the disableAutoconf command line argument was specified; otherwise false + * @return true if the disableAutoconf command line argument was specified; + * otherwise false */ public boolean isAutoconfDisabled() { return (line != null) && line.hasOption(ARGUMENT.DISABLE_AUTOCONF); @@ -624,7 +649,8 @@ public final class CliParser { /** * Returns true if the disableComposer command line argument was specified. * - * @return true if the disableComposer command line argument was specified; otherwise false + * @return true if the disableComposer command line argument was specified; + * otherwise false */ public boolean isComposerDisabled() { return (line != null) && line.hasOption(ARGUMENT.DISABLE_COMPOSER); @@ -633,7 +659,8 @@ public final class CliParser { /** * Returns true if the disableNexus command line argument was specified. * - * @return true if the disableNexus command line argument was specified; otherwise false + * @return true if the disableNexus command line argument was specified; + * otherwise false */ public boolean isNexusDisabled() { return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS); @@ -642,7 +669,8 @@ public final class CliParser { /** * Returns true if the disableOpenSSL command line argument was specified. * - * @return true if the disableOpenSSL command line argument was specified; otherwise false + * @return true if the disableOpenSSL command line argument was specified; + * otherwise false */ public boolean isOpenSSLDisabled() { return (line != null) && line.hasOption(ARGUMENT.DISABLE_OPENSSL); @@ -651,7 +679,8 @@ public final class CliParser { /** * Returns true if the disableNodeJS command line argument was specified. * - * @return true if the disableNodeJS command line argument was specified; otherwise false + * @return true if the disableNodeJS command line argument was specified; + * otherwise false */ public boolean isNodeJsDisabled() { return (line != null) && line.hasOption(ARGUMENT.DISABLE_NODE_JS); @@ -660,7 +689,8 @@ public final class CliParser { /** * Returns true if the disableCentral command line argument was specified. * - * @return true if the disableCentral command line argument was specified; otherwise false + * @return true if the disableCentral command line argument was specified; + * otherwise false */ public boolean isCentralDisabled() { return (line != null) && line.hasOption(ARGUMENT.DISABLE_CENTRAL); @@ -669,7 +699,8 @@ public final class CliParser { /** * Returns the url to the nexus server if one was specified. * - * @return the url to the nexus server; if none was specified this will return null; + * @return the url to the nexus server; if none was specified this will + * return null; */ public String getNexusUrl() { if (line == null || !line.hasOption(ARGUMENT.NEXUS_URL)) { @@ -680,9 +711,11 @@ public final class CliParser { } /** - * Returns true if the Nexus Analyzer should use the configured proxy to connect to Nexus; otherwise false is returned. + * Returns true if the Nexus Analyzer should use the configured proxy to + * connect to Nexus; otherwise false is returned. * - * @return true if the Nexus Analyzer should use the configured proxy to connect to Nexus; otherwise false + * @return true if the Nexus Analyzer should use the configured proxy to + * connect to Nexus; otherwise false */ public boolean isNexusUsesProxy() { // If they didn't specify whether Nexus needs to use the proxy, we should @@ -722,7 +755,8 @@ public final class CliParser { } /** - * Retrieves the file command line parameter(s) specified for the 'scan' argument. + * Retrieves the file command line parameter(s) specified for the 'scan' + * argument. * * @return the file paths specified on the command line for scan */ @@ -731,7 +765,8 @@ public final class CliParser { } /** - * Retrieves the list of excluded file patterns specified by the 'exclude' argument. + * Retrieves the list of excluded file patterns specified by the 'exclude' + * argument. * * @return the excluded file patterns */ @@ -740,7 +775,8 @@ public final class CliParser { } /** - * Returns the directory to write the reports to specified on the command line. + * Returns the directory to write the reports to specified on the command + * line. * * @return the path to the reports directory. */ @@ -749,7 +785,8 @@ public final class CliParser { } /** - * Returns the path to Mono for .NET Assembly analysis on non-windows systems. + * Returns the path to Mono for .NET Assembly analysis on non-windows + * systems. * * @return the path to Mono */ @@ -767,7 +804,8 @@ public final class CliParser { } /** - * Returns the output format specified on the command line. Defaults to HTML if no format was specified. + * Returns the output format specified on the command line. Defaults to HTML + * if no format was specified. * * @return the output format name. */ @@ -934,9 +972,11 @@ public final class CliParser { } /** - * Checks if the auto update feature has been disabled. If it has been disabled via the command line this will return false. + * Checks if the auto update feature has been disabled. If it has been + * disabled via the command line this will return false. * - * @return true if auto-update is allowed; otherwise false + * @return true if auto-update is allowed; otherwise + * false */ public boolean isAutoUpdate() { return line != null && !line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE); @@ -945,7 +985,8 @@ public final class CliParser { /** * Checks if the update only flag has been set. * - * @return true if the update only flag has been set; otherwise false. + * @return true if the update only flag has been set; otherwise + * false. */ public boolean isUpdateOnly() { return line != null && line.hasOption(ARGUMENT.UPDATE_ONLY); @@ -954,14 +995,16 @@ public final class CliParser { /** * Checks if the purge NVD flag has been set. * - * @return true if the purge nvd flag has been set; otherwise false. + * @return true if the purge nvd flag has been set; otherwise + * false. */ public boolean isPurge() { return line != null && line.hasOption(ARGUMENT.PURGE_NVD); } /** - * Returns the database driver name if specified; otherwise null is returned. + * Returns the database driver name if specified; otherwise null is + * returned. * * @return the database driver name if specified; otherwise null is returned */ @@ -970,7 +1013,8 @@ public final class CliParser { } /** - * Returns the database driver path if specified; otherwise null is returned. + * Returns the database driver path if specified; otherwise null is + * returned. * * @return the database driver name if specified; otherwise null is returned */ @@ -979,34 +1023,41 @@ public final class CliParser { } /** - * Returns the database connection string if specified; otherwise null is returned. + * Returns the database connection string if specified; otherwise null is + * returned. * - * @return the database connection string if specified; otherwise null is returned + * @return the database connection string if specified; otherwise null is + * returned */ public String getConnectionString() { return line.getOptionValue(ARGUMENT.CONNECTION_STRING); } /** - * Returns the database database user name if specified; otherwise null is returned. + * Returns the database database user name if specified; otherwise null is + * returned. * - * @return the database database user name if specified; otherwise null is returned + * @return the database database user name if specified; otherwise null is + * returned */ public String getDatabaseUser() { return line.getOptionValue(ARGUMENT.DB_NAME); } /** - * Returns the database database password if specified; otherwise null is returned. + * Returns the database database password if specified; otherwise null is + * returned. * - * @return the database database password if specified; otherwise null is returned + * @return the database database password if specified; otherwise null is + * returned */ public String getDatabasePassword() { return line.getOptionValue(ARGUMENT.DB_PASSWORD); } /** - * Returns the additional Extensions if specified; otherwise null is returned. + * Returns the additional Extensions if specified; otherwise null is + * returned. * * @return the additional Extensions; otherwise null is returned */ @@ -1028,7 +1079,17 @@ public final class CliParser { } /** - * A collection of static final strings that represent the possible command line arguments. + * Returns true if the experimental analyzers are enabled. + * + * @return true if the experimental analyzers are enabled; otherwise false + */ + public boolean isExperimentalEnabled() { + return line.hasOption(ARGUMENT.EXPERIMENTAL); + } + + /** + * A collection of static final strings that represent the possible command + * line arguments. */ public static class ARGUMENT { @@ -1041,50 +1102,61 @@ public final class CliParser { */ public static final String SCAN_SHORT = "s"; /** - * The long CLI argument name specifying that the CPE/CVE/etc. data should not be automatically updated. + * The long CLI argument name specifying that the CPE/CVE/etc. data + * should not be automatically updated. */ public static final String DISABLE_AUTO_UPDATE = "noupdate"; /** - * The short CLI argument name specifying that the CPE/CVE/etc. data should not be automatically updated. + * The short CLI argument name specifying that the CPE/CVE/etc. data + * should not be automatically updated. */ public static final String DISABLE_AUTO_UPDATE_SHORT = "n"; /** - * The long CLI argument name specifying that only the update phase should be executed; no scan should be run. + * The long CLI argument name specifying that only the update phase + * should be executed; no scan should be run. */ public static final String UPDATE_ONLY = "updateonly"; /** - * The long CLI argument name specifying that only the update phase should be executed; no scan should be run. + * The long CLI argument name specifying that only the update phase + * should be executed; no scan should be run. */ public static final String PURGE_NVD = "purge"; /** - * The long CLI argument name specifying the directory to write the reports to. + * The long CLI argument name specifying the directory to write the + * reports to. */ public static final String OUT = "out"; /** - * The short CLI argument name specifying the directory to write the reports to. + * The short CLI argument name specifying the directory to write the + * reports to. */ public static final String OUT_SHORT = "o"; /** - * The long CLI argument name specifying the output format to write the reports to. + * The long CLI argument name specifying the output format to write the + * reports to. */ public static final String OUTPUT_FORMAT = "format"; /** - * The short CLI argument name specifying the output format to write the reports to. + * The short CLI argument name specifying the output format to write the + * reports to. */ public static final String OUTPUT_FORMAT_SHORT = "f"; /** - * The long CLI argument name specifying the name of the project to be scanned. + * The long CLI argument name specifying the name of the project to be + * scanned. */ public static final String PROJECT = "project"; /** - * The long CLI argument name specifying the name of the application to be scanned. + * The long CLI argument name specifying the name of the application to + * be scanned. * * @deprecated project should be used instead */ @Deprecated public static final String APP_NAME = "app"; /** - * The short CLI argument name specifying the name of the application to be scanned. + * The short CLI argument name specifying the name of the application to + * be scanned. * * @deprecated project should be used instead */ @@ -1142,11 +1214,13 @@ public final class CliParser { */ public static final String CONNECTION_TIMEOUT = "connectiontimeout"; /** - * The short CLI argument name for setting the location of an additional properties file. + * The short CLI argument name for setting the location of an additional + * properties file. */ public static final String PROP_SHORT = "P"; /** - * The CLI argument name for setting the location of an additional properties file. + * The CLI argument name for setting the location of an additional + * properties file. */ public static final String PROP = "propertyfile"; /** @@ -1170,7 +1244,8 @@ public final class CliParser { */ public static final String CVE_BASE_20 = "cveUrl20Base"; /** - * The short CLI argument name for setting the location of the data directory. + * The short CLI argument name for setting the location of the data + * directory. */ public static final String DATA_DIRECTORY_SHORT = "d"; /** @@ -1178,20 +1253,24 @@ public final class CliParser { */ public static final String VERBOSE_LOG = "log"; /** - * The short CLI argument name for setting the location of the data directory. + * The short CLI argument name for setting the location of the data + * directory. */ public static final String VERBOSE_LOG_SHORT = "l"; /** - * The CLI argument name for setting the depth of symbolic links that will be followed. + * The CLI argument name for setting the depth of symbolic links that + * will be followed. */ public static final String SYM_LINK_DEPTH = "symLink"; /** - * The CLI argument name for setting the location of the suppression file. + * The CLI argument name for setting the location of the suppression + * file. */ public static final String SUPPRESSION_FILE = "suppression"; /** - * The CLI argument name for setting the location of the suppression file. + * The CLI argument name for setting the location of the suppression + * file. */ public static final String CVE_VALID_FOR_HOURS = "cveValidForHours"; /** @@ -1259,7 +1338,8 @@ public final class CliParser { */ public static final String NEXUS_URL = "nexus"; /** - * Whether or not the defined proxy should be used when connecting to Nexus. + * Whether or not the defined proxy should be used when connecting to + * Nexus. */ public static final String NEXUS_USES_PROXY = "nexusUsesProxy"; /** @@ -1279,11 +1359,13 @@ public final class CliParser { */ public static final String DB_DRIVER = "dbDriverName"; /** - * The CLI argument name for setting the path to the database driver; in case it is not on the class path. + * The CLI argument name for setting the path to the database driver; in + * case it is not on the class path. */ public static final String DB_DRIVER_PATH = "dbDriverPath"; /** - * The CLI argument name for setting the path to mono for .NET Assembly analysis on non-windows systems. + * The CLI argument name for setting the path to mono for .NET Assembly + * analysis on non-windows systems. */ public static final String PATH_TO_MONO = "mono"; /** @@ -1295,8 +1377,13 @@ public final class CliParser { */ public static final String EXCLUDE = "exclude"; /** - * The CLI argument name for setting the path to bundle-audit for Ruby bundle analysis. + * The CLI argument name for setting the path to bundle-audit for Ruby + * bundle analysis. */ public static final String PATH_TO_BUNDLE_AUDIT = "bundleAudit"; + /** + * The CLI argument to enable the experimental analyzers. + */ + private static final String EXPERIMENTAL = "enableExperimental"; } } diff --git a/dependency-check-cli/src/site/markdown/arguments.md b/dependency-check-cli/src/site/markdown/arguments.md index 66f37af01..876eee216 100644 --- a/dependency-check-cli/src/site/markdown/arguments.md +++ b/dependency-check-cli/src/site/markdown/arguments.md @@ -18,7 +18,7 @@ Short | Argument Name   | Parameter | Description | Requir | \-\-advancedHelp | | Print the advanced help message. | Optional \-v | \-\-version | | Print the version information. | Optional | \-\-cveValidForHours | \ | The number of hours to wait before checking for new updates from the NVD. The default is 4 hours. | Optional - + | \-\-experimental | | Enable the experimental analyzers. | Optional Advanced Options ================ 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 fa120a0e8..c35a796e0 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 @@ -126,9 +126,8 @@ public class Engine implements FileFilter { } final AnalyzerService service = new AnalyzerService(serviceClassLoader); - final Iterator iterator = service.getAnalyzers(); - while (iterator.hasNext()) { - final Analyzer a = iterator.next(); + final List iterator = service.getAnalyzers(); + for (Analyzer a : iterator) { analyzers.get(a.getAnalysisPhase()).add(a); if (a instanceof FileTypeAnalyzer) { this.fileTypeAnalyzers.add((FileTypeAnalyzer) a); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AnalyzerService.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AnalyzerService.java index a794b1030..41a243021 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AnalyzerService.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AnalyzerService.java @@ -17,8 +17,13 @@ */ package org.owasp.dependencycheck.analyzer; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import java.util.ServiceLoader; +import org.owasp.dependencycheck.utils.InvalidSettingException; +import org.owasp.dependencycheck.utils.Settings; +import org.slf4j.LoggerFactory; /** * The Analyzer Service Loader. This class loads all services that implement @@ -27,11 +32,15 @@ import java.util.ServiceLoader; * @author Jeremy Long */ public class AnalyzerService { + /** + * The Logger for use throughout the class. + */ + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(AnalyzerService.class); /** * The service loader for analyzers. */ - private final ServiceLoader loader; + private final ServiceLoader service; /** * Creates a new instance of AnalyzerService. @@ -39,15 +48,31 @@ public class AnalyzerService { * @param classLoader the ClassLoader to use when dynamically loading Analyzer and Update services */ public AnalyzerService(ClassLoader classLoader) { - loader = ServiceLoader.load(Analyzer.class, classLoader); + service = ServiceLoader.load(Analyzer.class, classLoader); } /** - * Returns an Iterator for all instances of the Analyzer interface. + * Returns a list of all instances of the Analyzer interface. * - * @return an iterator of Analyzers. + * @return a list of Analyzers. */ - public Iterator getAnalyzers() { - return loader.iterator(); + public List getAnalyzers() { + List analyzers = new ArrayList(); + final Iterator iterator = service.iterator(); + boolean experimentalEnabled = false; + try { + experimentalEnabled = Settings.getBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, false); + } catch (InvalidSettingException ex) { + LOGGER.error("invalide experimental setting", ex); + } + while (iterator.hasNext()) { + final Analyzer a = iterator.next(); + if (!experimentalEnabled && a.getClass().isAnnotationPresent(Experimental.class)) { + continue; + } + LOGGER.debug("Loaded Analyzer {}", a.getName()); + analyzers.add(a); + } + return analyzers; } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.java index 04dcfcefe..cb6736134 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.java @@ -42,6 +42,7 @@ import java.util.regex.Pattern; * @author Dale Visser * @see Autoconf - GNU Project - Free Software Foundation (FSF) */ +@Experimental public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.java index 55a81e216..fc434370f 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.java @@ -49,6 +49,7 @@ import java.util.regex.Pattern; * * @author Dale Visser */ +@Experimental public class CMakeAnalyzer extends AbstractFileTypeAnalyzer { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/Experimental.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/Experimental.java new file mode 100644 index 000000000..8f5a3842a --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/Experimental.java @@ -0,0 +1,34 @@ +/* + * 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.analyzer; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation used to flag an analyzer as experimental. + * + * @author jeremy long + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface Experimental { + +} diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NodePackageAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NodePackageAnalyzer.java index 85326f392..52b9afe11 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NodePackageAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NodePackageAnalyzer.java @@ -45,6 +45,7 @@ import javax.json.JsonValue; * * @author Dale Visser */ +@Experimental public class NodePackageAnalyzer extends AbstractFileTypeAnalyzer { /** diff --git a/dependency-check-core/src/main/resources/dependencycheck.properties b/dependency-check-core/src/main/resources/dependencycheck.properties index 118b5b50f..a0a1fd3e7 100644 --- a/dependency-check-core/src/main/resources/dependencycheck.properties +++ b/dependency-check-core/src/main/resources/dependencycheck.properties @@ -63,13 +63,6 @@ cve.url-2.0.base=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz cpe.validfordays=30 cpe.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.3.xml.gz -# file type analyzer settings: -analyzer.archive.enabled=true -analyzer.jar.enabled=true -analyzer.nuspec.enabled=true -analyzer.assembly.enabled=true -analyzer.composer.lock.enabled=true - # the URL for searching Nexus for SHA-1 hashes and whether it's enabled analyzer.nexus.enabled=true analyzer.nexus.url=https://repository.sonatype.org/service/local/ @@ -87,7 +80,7 @@ archive.scan.depth=3 # use HEAD (default) or GET as HTTP request method for query timestamp downloader.quick.query.timestamp=true - +analyzer.experimental.enabled=false analyzer.jar.enabled=true analyzer.archive.enabled=true analyzer.node.package.enabled=true diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/AnalyzerServiceTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/AnalyzerServiceTest.java index befa0692c..229e61d9b 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/AnalyzerServiceTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/AnalyzerServiceTest.java @@ -18,9 +18,12 @@ package org.owasp.dependencycheck.analyzer; import java.util.Iterator; +import java.util.List; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; import org.owasp.dependencycheck.BaseDBTestCase; +import org.owasp.dependencycheck.utils.Settings; /** * @@ -34,15 +37,42 @@ public class AnalyzerServiceTest extends BaseDBTestCase { @Test public void testGetAnalyzers() { AnalyzerService instance = new AnalyzerService(Thread.currentThread().getContextClassLoader()); - Iterator result = instance.getAnalyzers(); + List result = instance.getAnalyzers(); boolean found = false; - while (result.hasNext()) { - Analyzer a = result.next(); + for (Analyzer a : result) { if ("Jar Analyzer".equals(a.getName())) { found = true; } } assertTrue("JarAnalyzer loaded", found); } + + /** + * Test of getAnalyzers method, of class AnalyzerService. + */ + @Test + public void testGetExperimentalAnalyzers() { + Settings.setBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, false); + AnalyzerService instance = new AnalyzerService(Thread.currentThread().getContextClassLoader()); + List result = instance.getAnalyzers(); + String experimental = "CMake Analyzer"; + boolean found = false; + for (Analyzer a : result) { + if (experimental.equals(a.getName())) { + found = true; + } + } + assertFalse("Experimental analyzer loaded when set to false", found); + + Settings.setBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, true); + result = instance.getAnalyzers(); + found = false; + for (Analyzer a : result) { + if (experimental.equals(a.getName())) { + found = true; + } + } + assertTrue("Experimental analyzer not loaded when set to true", found); + } } diff --git a/dependency-check-core/src/test/resources/dependencycheck.properties b/dependency-check-core/src/test/resources/dependencycheck.properties index e3862e8e7..c82d46051 100644 --- a/dependency-check-core/src/test/resources/dependencycheck.properties +++ b/dependency-check-core/src/test/resources/dependencycheck.properties @@ -58,12 +58,6 @@ cve.url-2.0.base=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz cpe.validfordays=30 cpe.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.3.xml.gz -# file type analyzer settings: -analyzer.archive.enabled=true -analyzer.jar.enabled=true -analyzer.nuspec.enabled=true -analyzer.assembly.enabled=true -analyzer.composer.lock.enabled=true # the URL for searching Nexus for SHA-1 hashes and whether it's enabled analyzer.nexus.enabled=true @@ -82,7 +76,7 @@ archive.scan.depth=3 # use HEAD (default) or GET as HTTP request method for query timestamp downloader.quick.query.timestamp=true - +analyzer.experimental.enabled=true analyzer.jar.enabled=true analyzer.archive.enabled=true analyzer.node.package.enabled=true 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 57e8677be..1fd81babe 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 @@ -94,24 +94,32 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma @Parameter(defaultValue = "${project.build.directory}", required = true) private File outputDirectory; /** - * Specifies the destination directory for the generated Dependency-Check report. This generally maps to "target/site". + * Specifies the destination directory for the generated Dependency-Check + * report. This generally maps to "target/site". */ @Parameter(property = "project.reporting.outputDirectory", required = true) private File reportOutputDirectory; /** - * 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. + * 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. */ @SuppressWarnings("CanBeFinal") @Parameter(property = "failBuildOnCVSS", defaultValue = "11", required = true) private float failBuildOnCVSS = 11; /** - * 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. */ @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; /** * Generate aggregate reports in multi-module projects. * @@ -121,8 +129,9 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma @Deprecated private Boolean aggregate; /** - * The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the - * Site plug-in 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 plug-in + * unless the externalReport is set to true. Default is HTML. */ @SuppressWarnings("CanBeFinal") @Parameter(property = "format", defaultValue = "HTML", required = true) @@ -234,7 +243,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma private Boolean nexusAnalyzerEnabled; /** - * The URL of a Nexus server's REST API end point (http://domain/nexus/service/local). + * The URL of a Nexus server's REST API end point + * (http://domain/nexus/service/local). */ @Parameter(property = "nexusUrl", required = false) private String nexusUrl; @@ -268,7 +278,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma @Parameter(property = "databaseDriverPath", defaultValue = "", required = false) private String databaseDriverPath; /** - * The server id in the settings.xml; used to retrieve encrypted passwords from the settings.xml. + * The server id in the settings.xml; used to retrieve encrypted passwords + * from the settings.xml. */ @Parameter(property = "serverId", defaultValue = "", required = false) private String serverId; @@ -293,7 +304,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma @Parameter(property = "databasePassword", defaultValue = "", required = false) private String databasePassword; /** - * A comma-separated list of file extensions to add to analysis next to jar, zip, .... + * A comma-separated list of file extensions to add to analysis next to jar, + * zip, .... */ @Parameter(property = "zipExtensions", required = false) private String zipExtensions; @@ -347,7 +359,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma @Parameter(property = "cveUrl20Base", defaultValue = "", required = false) private String cveUrl20Base; /** - * Optionally skip excessive CVE update checks for a designated duration in hours. + * Optionally skip excessive CVE update checks for a designated duration in + * hours. */ @Parameter(property = "cveValidForHours", defaultValue = "", required = false) private Integer cveValidForHours; @@ -382,7 +395,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma /** * Executes dependency-check. * - * @throws MojoExecutionException thrown if there is an exception executing the mojo + * @throws MojoExecutionException thrown if there is an exception executing + * the mojo * @throws MojoFailureException thrown if dependency-check failed the build */ @Override @@ -398,8 +412,9 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma } /** - * Checks if the aggregate configuration parameter has been set to true. If it has a MojoExecutionException is thrown because - * the aggregate configuration parameter is no longer supported. + * Checks if the aggregate configuration parameter has been set to true. If + * it has a MojoExecutionException is thrown because the aggregate + * configuration parameter is no longer supported. * * @throws MojoExecutionException thrown if aggregate is set to true */ @@ -417,7 +432,9 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma * @param sink the sink to write the report to * @param locale the locale to use when generating the report * @throws MavenReportException if a maven report exception occurs - * @deprecated use {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale)} instead. + * @deprecated use + * {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale)} + * instead. */ @Override @Deprecated @@ -464,17 +481,20 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma } /** - * Returns the correct output directory depending on if a site is being executed or not. + * Returns the correct output directory depending on if a site is being + * executed or not. * * @return the directory to write the report(s) - * @throws MojoExecutionException thrown if there is an error loading the file path + * @throws MojoExecutionException thrown if there is an error loading the + * file path */ protected File getCorrectOutputDirectory() throws MojoExecutionException { return getCorrectOutputDirectory(this.project); } /** - * Returns the correct output directory depending on if a site is being executed or not. + * Returns the correct output directory depending on if a site is being + * executed or not. * * @param current the Maven project to get the output directory from * @return the directory to write the report(s) @@ -492,7 +512,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma } /** - * Returns the correct output directory depending on if a site is being executed or not. + * Returns the correct output directory depending on if a site is being + * executed or not. * * @param current the Maven project to get the output directory from * @return the directory to write the report(s) @@ -507,16 +528,15 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma final File f = new File((String) obj); return f; } - } else { - if (getLog().isDebugEnabled()) { - getLog().debug("Context value not found"); - } + } else if (getLog().isDebugEnabled()) { + getLog().debug("Context value not found"); } return null; } /** - * Scans the project's artifacts and adds them to the engine's dependency list. + * Scans the project's artifacts and adds them to the engine's dependency + * list. * * @param project the project to scan the dependencies of * @param engine the engine to use to scan the dependencies @@ -539,12 +559,10 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma d.getDisplayFileName())); } } - } else { - if (getLog().isDebugEnabled()) { - final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'", - a.getGroupId(), a.getArtifactId(), a.getVersion()); - getLog().debug(msg); - } + } else if (getLog().isDebugEnabled()) { + final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'", + a.getGroupId(), a.getArtifactId(), a.getVersion()); + getLog().debug(msg); } } } @@ -553,8 +571,10 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma /** * Executes the dependency-check scan and generates the necassary report. * - * @throws MojoExecutionException thrown if there is an exception running the scan - * @throws MojoFailureException thrown if dependency-check is configured to fail the build + * @throws MojoExecutionException thrown if there is an exception running + * the scan + * @throws MojoFailureException thrown if dependency-check is configured to + * fail the build */ public abstract void runCheck() throws MojoExecutionException, MojoFailureException; @@ -588,7 +608,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma } /** - * Returns whether this is an external report. This method always returns true. + * Returns whether this is an external report. This method always returns + * true. * * @return true */ @@ -640,8 +661,9 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma } /** - * Takes the properties supplied and updates the dependency-check settings. Additionally, this sets the system properties - * required to change the proxy url, 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 url, port, and connection timeout. */ protected void populateSettings() { Settings.initialize(); @@ -666,6 +688,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma } } Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate); + + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental); if (externalReport != null) { getLog().warn("The 'externalReport' option was set; this configuration option has been removed. " @@ -795,10 +819,12 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma } /** - * Tests is the artifact should be included in the scan (i.e. is the dependency in a scope that is being scanned). + * Tests is the artifact should be included in the scan (i.e. is the + * dependency in a scope that is being scanned). * * @param a the Artifact to test - * @return true if the artifact is in an excluded scope; otherwise false + * @return true if the artifact is in an excluded scope; + * otherwise false */ protected boolean excludeFromScan(Artifact a) { if (skipTestScope && Artifact.SCOPE_TEST.equals(a.getScope())) { @@ -814,10 +840,12 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma } /** - * Returns a reference to the current project. This method is used instead of auto-binding the project via component - * annotation in concrete implementations of this. If the child has a @Component MavenProject project; defined - * then the abstract class (i.e. this class) will not have access to the current project (just the way Maven works with the - * binding). + * Returns a reference to the current project. This method is used instead + * of auto-binding the project via component annotation in concrete + * implementations of this. If the child has a + * @Component MavenProject project; defined then the abstract + * class (i.e. this class) will not have access to the current project (just + * the way Maven works with the binding). * * @return returns a reference to the current project */ @@ -886,11 +914,12 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma // /** - * 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 MojoFailureException thrown if a CVSS score is found that is higher then the threshold set + * @throws MojoFailureException thrown if a CVSS score is found that is + * higher then the threshold set */ protected void checkForFailure(List dependencies) throws MojoFailureException { if (failBuildOnCVSS <= 10) { @@ -919,7 +948,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma } /** - * 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 mp the Maven project for which the summary is shown * @param dependencies a list of dependency objects @@ -963,8 +993,9 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma // // /** - * Returns the key used to store the path to the data file that is saved by writeDataFile(). This key is used in - * the MavenProject.(set|get)ContextValue. + * Returns the key used to store the path to the data file that is saved by + * writeDataFile(). This key is used in the + * MavenProject.(set|get)ContextValue. * * @return the key used to store the path to the data file */ @@ -973,8 +1004,9 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma } /** - * Returns the key used to store the path to the output directory. When generating the report in the - * executeAggregateReport() the output directory should be obtained by using this key. + * Returns the key used to store the path to the output directory. When + * generating the report in the executeAggregateReport() the + * output directory should be obtained by using this key. * * @return the key used to store the path to the output directory */ @@ -983,7 +1015,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma } /** - * Writes the scan data to disk. This is used to serialize the scan data between the "check" and "aggregate" phase. + * Writes the scan data to disk. This is used to serialize the scan data + * between the "check" and "aggregate" phase. * * @param mp the mMven project for which the data file was created * @param writeTo the directory to write the data file @@ -1037,12 +1070,12 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma } /** - * Reads the serialized scan data from disk. This is used to serialize the scan data between the "check" and "aggregate" - * phase. + * Reads the serialized scan data from disk. This is used to serialize the + * 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 serialized data file exists; otherwise - * null is returned + * @return a Engine 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/site/markdown/configuration.md b/dependency-check-maven/src/site/markdown/configuration.md index 7e64ab216..e35574aff 100644 --- a/dependency-check-maven/src/site/markdown/configuration.md +++ b/dependency-check-maven/src/site/markdown/configuration.md @@ -21,10 +21,11 @@ format | The report format to be generated (HTML, XML, VULN, ALL). 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' skip | Skips the dependency-check analysis | false -skipTestScope | Should be skip analysis for artifacts with Test Scope | true -skipProvidedScope | Should be skip analysis for artifacts with Provided Scope | false -skipRuntimeScope | Should be skip analysis for artifacts with Runtime Scope | false +skipTestScope | Skip analysis for artifacts with Test Scope | true +skipProvidedScope | Skip analysis for artifacts with Provided Scope | false +skipRuntimeScope | Skip analysis for artifacts with Runtime Scope | false suppressionFile | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html) |   +enableExperimental | Enable the experimental analyzers | false Analyzer Configuration ==================== 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 8f1f38147..924e355cd 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 @@ -189,6 +189,10 @@ public final class Settings { * The properties key for whether the Jar Analyzer is enabled. */ public static final String ANALYZER_JAR_ENABLED = "analyzer.jar.enabled"; + /** + * The properties key for whether experimental analyzers are loaded. + */ + public static final String ANALYZER_EXPERIMENTAL_ENABLED = "analyzer.experimental.enabled"; /** * The properties key for whether the Archive analyzer is enabled. */ @@ -309,7 +313,7 @@ public final class Settings { /** * Thread local settings. */ - private static ThreadLocal localSettings = new ThreadLocal(); + private static final ThreadLocal LOCAL_SETTINGS = new ThreadLocal(); /** * The properties. */ @@ -346,7 +350,7 @@ public final class Settings { * also call Settings.cleanup() to properly release resources. */ public static void initialize() { - localSettings.set(new Settings(PROPERTIES_FILE)); + LOCAL_SETTINGS.set(new Settings(PROPERTIES_FILE)); } /** @@ -356,7 +360,7 @@ public final class Settings { * @param propertiesFilePath the path to the base properties file to load */ public static void initialize(String propertiesFilePath) { - localSettings.set(new Settings(propertiesFilePath)); + LOCAL_SETTINGS.set(new Settings(propertiesFilePath)); } /** @@ -385,7 +389,7 @@ public final class Settings { } } try { - localSettings.remove(); + LOCAL_SETTINGS.remove(); } catch (Throwable ex) { LOGGER.debug("Error cleaning up Settings", ex); } @@ -397,7 +401,7 @@ public final class Settings { * @return the Settings object */ public static Settings getInstance() { - return localSettings.get(); + return LOCAL_SETTINGS.get(); } /** @@ -406,7 +410,7 @@ public final class Settings { * @param instance the instance of the settings object to use in this thread */ public static void setInstance(Settings instance) { - localSettings.set(instance); + LOCAL_SETTINGS.set(instance); } /** @@ -452,7 +456,7 @@ public final class Settings { * @param value the value for the property */ public static void setString(String key, String value) { - localSettings.get().props.setProperty(key, value); + LOCAL_SETTINGS.get().props.setProperty(key, value); LOGGER.debug("Setting: {}='{}'", key, value); } @@ -509,7 +513,7 @@ public final class Settings { * @param value the value for the property */ public static void setInt(String key, int value) { - localSettings.get().props.setProperty(key, String.valueOf(value)); + LOCAL_SETTINGS.get().props.setProperty(key, String.valueOf(value)); LOGGER.debug("Setting: {}='{}'", key, value); } @@ -584,8 +588,8 @@ public final class Settings { * @throws IOException is thrown when there is an exception loading/merging the properties */ public static void mergeProperties(InputStream stream) throws IOException { - localSettings.get().props.load(stream); - logProperties("Properties updated via merge", localSettings.get().props); + LOCAL_SETTINGS.get().props.load(stream); + logProperties("Properties updated via merge", LOCAL_SETTINGS.get().props); } /** @@ -665,7 +669,7 @@ public final class Settings { * @return the property from the properties file */ public static String getString(String key, String defaultValue) { - final String str = System.getProperty(key, localSettings.get().props.getProperty(key, defaultValue)); + final String str = System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key, defaultValue)); return str; } @@ -699,7 +703,7 @@ public final class Settings { * @return the property from the properties file */ public static String getString(String key) { - return System.getProperty(key, localSettings.get().props.getProperty(key)); + return System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key)); } /** @@ -708,7 +712,7 @@ public final class Settings { * @param key the property key to remove */ public static void removeProperty(String key) { - localSettings.get().props.remove(key); + LOCAL_SETTINGS.get().props.remove(key); } /** From 6790727260212b3e27810f4521c4300e3dd04556 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sun, 15 May 2016 07:02:18 -0400 Subject: [PATCH 2/3] ensured resources are properly closed --- .../analyzer/RubyBundleAuditAnalyzer.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) 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 1d983169b..5e4f90afa 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 @@ -225,8 +225,9 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer { throw new AnalysisException("bundle-audit process interrupted", ie); } BufferedReader rdr = null; + BufferedReader errReader = null; try { - BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8")); + errReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8")); while (errReader.ready()) { String error = errReader.readLine(); LOGGER.warn(error); @@ -236,6 +237,13 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer { } catch (IOException ioe) { LOGGER.warn("bundle-audit failure", ioe); } finally { + if (errReader!= null) { + try { + errReader.close(); + } catch (IOException ioe) { + LOGGER.warn("bundle-audit close failure", ioe); + } + } if (null != rdr) { try { rdr.close(); From 353b17690f0f7beb38b0b00c50d88921b44f5989 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sun, 15 May 2016 07:22:52 -0400 Subject: [PATCH 3/3] checkstyle/pmd/findbugs correction(s) --- .../owasp/dependencycheck/taskdefs/Check.java | 61 ++++--- .../org/slf4j/impl/StaticLoggerBinder.java | 27 ++- .../analyzer/AbstractSuppressionAnalyzer.java | 7 +- .../analyzer/AnalyzerService.java | 2 +- .../analyzer/FileNameAnalyzer.java | 6 +- .../dependencycheck/analyzer/JarAnalyzer.java | 162 +++++++++++------- .../analyzer/RubyBundleAuditAnalyzer.java | 20 ++- .../data/update/nvd/DownloadTask.java | 1 + .../suppression/SuppressionParser.java | 4 +- .../analyzer/RubyBundleAuditAnalyzerTest.java | 25 ++- .../maven/BaseDependencyCheckMojo.java | 2 +- .../org/slf4j/impl/StaticLoggerBinder.java | 14 +- 12 files changed, 197 insertions(+), 134 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 fc4fc9d3b..78f6e823a 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 @@ -86,8 +86,8 @@ public class Check extends Update { } /** - * Returns the path. If the path has not been initialized yet, this class is synchronized, and will instantiate the path - * object. + * Returns the path. If the path has not been initialized yet, this class is + * synchronized, and will instantiate the path object. * * @return the path */ @@ -109,7 +109,8 @@ public class Check extends Update { } /** - * Add a reference to a Path, FileSet, DirSet, or FileList defined elsewhere. + * Add a reference to a Path, FileSet, DirSet, or FileList defined + * elsewhere. * * @param r the reference to a path, fileset, dirset or filelist. */ @@ -121,7 +122,8 @@ public class Check extends Update { } /** - * If this is a reference, this method will add the referenced resource collection to the collection of paths. + * If this is a reference, this method will add the referenced resource + * collection to the collection of paths. * * @throws BuildException if the reference is not to a resource collection */ @@ -196,7 +198,8 @@ public class Check extends Update { } /** - * Specifies the destination directory for the generated Dependency-Check report. + * Specifies the destination directory for the generated Dependency-Check + * report. */ private String reportOutputDirectory = "."; @@ -218,9 +221,11 @@ public class Check extends Update { this.reportOutputDirectory = reportOutputDirectory; } /** - * 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; @@ -242,8 +247,8 @@ public class Check extends Update { this.failBuildOnCVSS = failBuildOnCVSS; } /** - * 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; @@ -295,7 +300,8 @@ public class Check extends Update { } /** - * The report format to be generated (HTML, XML, VULN, ALL). Default is HTML. + * The report format to be generated (HTML, XML, VULN, ALL). Default is + * HTML. */ private String reportFormat = "HTML"; @@ -383,7 +389,7 @@ public class Check extends Update { public void setEnableExperimental(Boolean enableExperimental) { this.enableExperimental = enableExperimental; } - + /** * Whether or not the Jar Analyzer is enabled. */ @@ -644,7 +650,8 @@ public class Check extends Update { /** * Set the value of pyDistributionAnalyzerEnabled. * - * @param pyDistributionAnalyzerEnabled new value of pyDistributionAnalyzerEnabled + * @param pyDistributionAnalyzerEnabled new value of + * pyDistributionAnalyzerEnabled */ public void setPyDistributionAnalyzerEnabled(Boolean pyDistributionAnalyzerEnabled) { this.pyDistributionAnalyzerEnabled = pyDistributionAnalyzerEnabled; @@ -697,7 +704,8 @@ public class Check extends Update { } /** - * The URL of a Nexus server's REST API end point (http://domain/nexus/service/local). + * The URL of a Nexus server's REST API end point + * (http://domain/nexus/service/local). */ private String nexusUrl; @@ -742,8 +750,8 @@ public class Check extends Update { } /** - * 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; @@ -853,7 +861,8 @@ public class Check extends Update { } /** - * Validate the configuration to ensure the parameters have been properly configured/initialized. + * Validate the configuration to ensure the parameters have been properly + * configured/initialized. * * @throws BuildException if the task was not configured correctly. */ @@ -867,8 +876,9 @@ public class Check extends Update { } /** - * 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. */ @@ -899,11 +909,12 @@ public class Check extends Update { } /** - * 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 BuildException thrown if a CVSS score is found that is higher then the threshold set + * @throws BuildException thrown if a CVSS score is found that is higher + * then the threshold set */ private void checkForFailure(List dependencies) throws BuildException { final StringBuilder ids = new StringBuilder(); @@ -927,7 +938,8 @@ public class Check extends Update { } /** - * 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 */ @@ -967,7 +979,8 @@ public class Check extends Update { } /** - * An enumeration of supported report formats: "ALL", "HTML", "XML", "VULN", etc.. + * An enumeration of supported report formats: "ALL", "HTML", "XML", "VULN", + * etc.. */ public static class ReportFormats extends EnumeratedAttribute { diff --git a/dependency-check-ant/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/dependency-check-ant/src/main/java/org/slf4j/impl/StaticLoggerBinder.java index c7d3bd93b..92c87d3e1 100644 --- a/dependency-check-ant/src/main/java/org/slf4j/impl/StaticLoggerBinder.java +++ b/dependency-check-ant/src/main/java/org/slf4j/impl/StaticLoggerBinder.java @@ -23,16 +23,18 @@ import org.slf4j.ILoggerFactory; import org.slf4j.spi.LoggerFactoryBinder; /** - * The binding of org.slf4j.LoggerFactory class with an actual instance of org.slf4j.ILoggerFactory is performed using information - * returned by this class. + * The binding of org.slf4j.LoggerFactory class with an actual instance of + * org.slf4j.ILoggerFactory is performed using information returned by this + * class. * * @author colezlaw */ +//CSOFF: FinalClass public class StaticLoggerBinder implements LoggerFactoryBinder { +//CSON: FinalClass /** * The unique instance of this class - * */ private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder(); @@ -46,7 +48,8 @@ public class StaticLoggerBinder implements LoggerFactoryBinder { } /** - * Ant tasks have the log method we actually want to call. So we hang onto the task as a delegate + * Ant tasks have the log method we actually want to call. So we hang onto + * the task as a delegate */ private Task task = null; @@ -61,16 +64,24 @@ public class StaticLoggerBinder implements LoggerFactoryBinder { } /** - * Declare the version of the SLF4J API this implementation is compiled against. The value of this filed is usually modified - * with each release. + * Declare the version of the SLF4J API this implementation is compiled + * against. The value of this filed is usually modified with each release. */ // to avoid constant folding by the compiler, this field must *not* be final + //CSOFF: StaticVariableName + //CSOFF: VisibilityModifier public static String REQUESTED_API_VERSION = "1.7.12"; // final - + //CSON: VisibilityModifier + //CSON: StaticVariableName + + /** + * The logger factory class string. + */ private static final String LOGGER_FACTORY_CLASS = AntLoggerFactory.class.getName(); /** - * The ILoggerFactory instance returned by the {@link #getLoggerFactory} method should always be the smae object + * The ILoggerFactory instance returned by the {@link #getLoggerFactory} + * method should always be the smae object */ private ILoggerFactory loggerFactory; diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java index 97c0719d5..812f70394 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java @@ -24,7 +24,6 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.List; import java.util.Set; -import java.util.logging.Level; import java.util.regex.Pattern; import org.owasp.dependencycheck.suppression.SuppressionParseException; import org.owasp.dependencycheck.suppression.SuppressionParser; @@ -38,7 +37,8 @@ import org.slf4j.LoggerFactory; import org.xml.sax.SAXException; /** - * Abstract base suppression analyzer that contains methods for parsing the suppression xml file. + * Abstract base suppression analyzer that contains methods for parsing the + * suppression xml file. * * @author Jeremy Long */ @@ -173,7 +173,8 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer { * * @param message the exception message * @param exception the cause of the exception - * @throws SuppressionParseException throws the generated SuppressionParseException + * @throws SuppressionParseException throws the generated + * SuppressionParseException */ private void throwSuppressionParseException(String message, Exception exception) throws SuppressionParseException { LOGGER.warn(message); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AnalyzerService.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AnalyzerService.java index 41a243021..e27f95649 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AnalyzerService.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AnalyzerService.java @@ -57,7 +57,7 @@ public class AnalyzerService { * @return a list of Analyzers. */ public List getAnalyzers() { - List analyzers = new ArrayList(); + final List analyzers = new ArrayList(); final Iterator iterator = service.iterator(); boolean experimentalEnabled = false; try { 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 b7d23a3e3..0775e8a88 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 @@ -67,11 +67,13 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer { } // - // Python init files + /** + * Python init files + */ private static final NameFileFilter IGNORED_FILES = new NameFileFilter(new String[] { "__init__.py", "__init__.pyc", - "__init__.pyo" + "__init__.pyo", }); /** 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 c76e8199b..18218d583 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 @@ -60,7 +60,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Used to load a JAR file and collect information that can be used to determine the associated CPE. + * Used to load a JAR file and collect information that can be used to determine + * the associated CPE. * * @author Jeremy Long */ @@ -72,7 +73,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { */ private static final Logger LOGGER = LoggerFactory.getLogger(JarAnalyzer.class); /** - * The count of directories created during analysis. This is used for creating temporary directories. + * The count of directories created during analysis. This is used for + * creating temporary directories. */ private static int dirCount = 0; /** @@ -80,7 +82,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { */ private static final String NEWLINE = System.getProperty("line.separator"); /** - * A list of values in the manifest to ignore as they only result in false positives. + * A list of values in the manifest to ignore as they only result in false + * positives. */ private static final Set IGNORE_VALUES = newHashSet( "Sun Java System Application Server"); @@ -123,7 +126,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { "ipojo-extension", "eclipse-sourcereferences"); /** - * Deprecated Jar manifest attribute, that is, nonetheless, useful for analysis. + * Deprecated Jar manifest attribute, that is, nonetheless, useful for + * analysis. */ @SuppressWarnings("deprecation") private static final String IMPLEMENTATION_VENDOR_ID = Attributes.Name.IMPLEMENTATION_VENDOR_ID @@ -203,7 +207,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { // /** - * Returns the key used in the properties file to reference the analyzer's enabled property. + * Returns the key used in the properties file to reference the analyzer's + * enabled property. * * @return the analyzer's enabled property setting key */ @@ -213,12 +218,13 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { } /** - * Loads a specified JAR file and collects information from the manifest and checksums to identify the correct CPE - * information. + * Loads a specified JAR file and collects information from the manifest and + * checksums to identify the correct CPE information. * * @param dependency the dependency to analyze. * @param engine the engine that is scanning the dependencies - * @throws AnalysisException is thrown if there is an error reading the JAR file. + * @throws AnalysisException is thrown if there is an error reading the JAR + * file. */ @Override public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException { @@ -242,13 +248,15 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { } /** - * Attempts to find a pom.xml within the JAR file. If found it extracts information and adds it to the evidence. This will - * attempt to interpolate the strings contained within the pom.properties if one exists. + * Attempts to find a pom.xml within the JAR file. If found it extracts + * information and adds it to the evidence. This will attempt to interpolate + * the strings contained within the pom.properties if one exists. * * @param dependency the dependency being analyzed * @param classes a collection of class name information * @param engine the analysis engine, used to add additional dependencies - * @throws AnalysisException is thrown if there is an exception parsing the pom + * @throws AnalysisException is thrown if there is an exception parsing the + * pom * @return whether or not evidence was added to the dependency */ protected boolean analyzePOM(Dependency dependency, List classes, Engine engine) throws AnalysisException { @@ -329,12 +337,14 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { } /** - * Given a path to a pom.xml within a JarFile, this method attempts to load a sibling pom.properties if one exists. + * Given a path to a pom.xml within a JarFile, this method attempts to load + * a sibling pom.properties if one exists. * * @param path the path to the pom.xml within the JarFile * @param jar the JarFile to load the pom.properties from * @return a Properties object or null if no pom.properties was found - * @throws IOException thrown if there is an exception reading the pom.properties + * @throws IOException thrown if there is an exception reading the + * pom.properties */ private Properties retrievePomProperties(String path, final JarFile jar) throws IOException { Properties pomProperties = null; @@ -361,7 +371,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { } /** - * Searches a JarFile for pom.xml entries and returns a listing of these entries. + * Searches a JarFile for pom.xml entries and returns a listing of these + * entries. * * @param jar the JarFile to search * @return a list of pom.xml entries @@ -388,8 +399,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { * @param jar the jar file to extract the pom from * @param dependency the dependency being analyzed * @return returns the POM object - * @throws AnalysisException is thrown if there is an exception extracting or parsing the POM - * {@link org.owasp.dependencycheck.xml.pom.Model} object + * @throws AnalysisException is thrown if there is an exception extracting + * or parsing the POM {@link org.owasp.dependencycheck.xml.pom.Model} object */ private Model extractPom(String path, JarFile jar, Dependency dependency) throws AnalysisException { InputStream input = null; @@ -447,9 +458,10 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { * * @param dependency the dependency to set data on * @param pom the information from the pom - * @param classes a collection of ClassNameInformation - containing data about the fully qualified class names within the JAR - * file being analyzed - * @return true if there was evidence within the pom that we could use; otherwise false + * @param classes a collection of ClassNameInformation - containing data + * about the fully qualified class names within the JAR file being analyzed + * @return true if there was evidence within the pom that we could use; + * otherwise false */ public static boolean setPomEvidence(Dependency dependency, Model pom, List classes) { boolean foundSomething = false; @@ -571,12 +583,15 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { } /** - * Analyzes the path information of the classes contained within the JarAnalyzer to try and determine possible vendor or - * product names. If any are found they are stored in the packageVendor and packageProduct hashSets. + * Analyzes the path information of the classes contained within the + * JarAnalyzer to try and determine possible vendor or product names. If any + * are found they are stored in the packageVendor and packageProduct + * hashSets. * * @param classNames a list of class names * @param dependency a dependency to analyze - * @param addPackagesAsEvidence a flag indicating whether or not package names should be added as evidence. + * @param addPackagesAsEvidence a flag indicating whether or not package + * names should be added as evidence. */ protected void analyzePackageNames(List classNames, Dependency dependency, boolean addPackagesAsEvidence) { @@ -611,11 +626,13 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { /** *

- * Reads the manifest from the JAR file and collects the entries. Some vendorKey entries are:

+ * Reads the manifest from the JAR file and collects the entries. Some + * vendorKey entries are:

*
  • Implementation Title
  • *
  • Implementation Version
  • Implementation Vendor
  • - *
  • Implementation VendorId
  • Bundle Name
  • Bundle Version
  • Bundle Vendor
  • Bundle - * Description
  • Main Class
+ *
  • Implementation VendorId
  • Bundle Name
  • Bundle + * Version
  • Bundle Vendor
  • Bundle Description
  • Main + * Class
  • * However, all but a handful of specific entries are read in. * * @param dependency A reference to the dependency @@ -623,7 +640,8 @@ 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 { @@ -748,21 +766,19 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { addMatchingValues(classInformation, value, productEvidence); } else if (key.contains("license")) { addLicense(dependency, value); + } else if (key.contains("description")) { + addDescription(dependency, value, "manifest", key); } else { - if (key.contains("description")) { - addDescription(dependency, value, "manifest", key); - } else { - productEvidence.addEvidence(source, key, value, Confidence.LOW); - vendorEvidence.addEvidence(source, key, value, Confidence.LOW); - addMatchingValues(classInformation, value, vendorEvidence); - addMatchingValues(classInformation, value, productEvidence); - if (value.matches(".*\\d.*")) { - final StringTokenizer tokenizer = new StringTokenizer(value, " "); - while (tokenizer.hasMoreElements()) { - final String s = tokenizer.nextToken(); - if (s.matches("^[0-9.]+$")) { - versionEvidence.addEvidence(source, key, s, Confidence.LOW); - } + productEvidence.addEvidence(source, key, value, Confidence.LOW); + vendorEvidence.addEvidence(source, key, value, Confidence.LOW); + addMatchingValues(classInformation, value, vendorEvidence); + addMatchingValues(classInformation, value, productEvidence); + if (value.matches(".*\\d.*")) { + final StringTokenizer tokenizer = new StringTokenizer(value, " "); + while (tokenizer.hasMoreElements()) { + final String s = tokenizer.nextToken(); + if (s.matches("^[0-9.]+$")) { + versionEvidence.addEvidence(source, key, s, Confidence.LOW); } } } @@ -810,15 +826,18 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { } /** - * Adds a description to the given dependency. If the description contains one of the following strings beyond 100 characters, - * then the description used will be trimmed to that position: - *
    • "such as"
    • "like "
    • "will use "
    • "* uses "
    + * Adds a description to the given dependency. If the description contains + * one of the following strings beyond 100 characters, then the description + * used will be trimmed to that position: + *
    • "such as"
    • "like "
    • "will use "
    • "* uses + * "
    * * @param dependency a dependency * @param description the description * @param source the source of the evidence * @param key the "name" of the evidence - * @return if the description is trimmed, the trimmed version is returned; otherwise the original description is returned + * @return if the description is trimmed, the trimmed version is returned; + * otherwise the original description is returned */ public static String addDescription(Dependency dependency, String description, String source, String key) { if (dependency.getDescription() == null) { @@ -889,7 +908,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { /** * Initializes the JarAnalyzer. * - * @throws Exception is thrown if there is an exception creating a temporary directory + * @throws Exception is thrown if there is an exception creating a temporary + * directory */ @Override public void initializeFileTypeAnalyzer() throws Exception { @@ -920,11 +940,13 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { } /** - * Determines if the key value pair from the manifest is for an "import" type entry for package names. + * Determines if the key value pair from the manifest is for an "import" + * type entry for package names. * * @param key the key from the manifest * @param value the value from the manifest - * @return true or false depending on if it is believed the entry is an "import" entry + * @return true or false depending on if it is believed the entry is an + * "import" entry */ private boolean isImportPackage(String key, String value) { final Pattern packageRx = Pattern.compile("^([a-zA-Z0-9_#\\$\\*\\.]+\\s*[,;]\\s*)+([a-zA-Z0-9_#\\$\\*\\.]+\\s*)?$"); @@ -933,8 +955,9 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { } /** - * Cycles through an enumeration of JarEntries, contained within the dependency, and returns a list of the class names. This - * does not include core Java package names (i.e. java.* or javax.*). + * Cycles through an enumeration of JarEntries, contained within the + * dependency, and returns a list of the class names. This does not include + * core Java package names (i.e. java.* or javax.*). * * @param dependency the dependency being analyzed * @return an list of fully qualified class names @@ -970,12 +993,16 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { } /** - * Cycles through the list of class names and places the package levels 0-3 into the provided maps for vendor and product. - * This is helpful when analyzing vendor/product as many times this is included in the package name. + * Cycles through the list of class names and places the package levels 0-3 + * into the provided maps for vendor and product. This is helpful when + * analyzing vendor/product as many times this is included in the package + * name. * * @param classNames a list of class names - * @param vendor HashMap of possible vendor names from package names (e.g. owasp) - * @param product HashMap of possible product names from package names (e.g. dependencycheck) + * @param vendor HashMap of possible vendor names from package names (e.g. + * owasp) + * @param product HashMap of possible product names from package names (e.g. + * dependencycheck) */ private void analyzeFullyQualifiedClassNames(List classNames, Map vendor, Map product) { @@ -1002,8 +1029,9 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { } /** - * Adds an entry to the specified collection and sets the Integer (e.g. the count) to 1. If the entry already exists in the - * collection then the Integer is incremented by 1. + * Adds an entry to the specified collection and sets the Integer (e.g. the + * count) to 1. If the entry already exists in the collection then the + * Integer is incremented by 1. * * @param collection a collection of strings and their occurrence count * @param key the key to add to the collection @@ -1017,9 +1045,10 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { } /** - * Cycles through the collection of class name information to see if parts of the package names are contained in the provided - * value. If found, it will be added as the HIGHEST confidence evidence because we have more then one source corroborating the - * value. + * Cycles through the collection of class name information to see if parts + * of the package names are contained in the provided value. If found, it + * will be added as the HIGHEST confidence evidence because we have more + * then one source corroborating the value. * * @param classes a collection of class name information * @param value the value to check to see if it contains a package name @@ -1042,7 +1071,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { } /** - * Simple check to see if the attribute from a manifest is just a package name. + * Simple check to see if the attribute from a manifest is just a package + * name. * * @param key the key of the value to check * @param value the value to check @@ -1056,7 +1086,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { } /** - * Extracts the license information from the pom and adds it to the dependency. + * Extracts the license information from the pom and adds it to the + * dependency. * * @param pom the pom object * @param dependency the dependency to add license information too @@ -1103,9 +1134,11 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { /** *

    - * Stores information about a given class name. This class will keep the fully qualified class name and a list of the - * important parts of the package structure. Up to the first four levels of the package structure are stored, excluding a - * leading "org" or "com". Example:

    + * Stores information about a given class name. This class will keep the + * fully qualified class name and a list of the important parts of the + * package structure. Up to the first four levels of the package + * structure are stored, excluding a leading "org" or "com". + * Example:

    * ClassNameInformation obj = new ClassNameInformation("org.owasp.dependencycheck.analyzer.JarAnalyzer"); * System.out.println(obj.getName()); * for (String p : obj.getPackageStructure()) @@ -1164,7 +1197,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { this.name = name; } /** - * Up to the first four levels of the package structure, excluding a leading "org" or "com". + * Up to the first four levels of the package structure, excluding a + * leading "org" or "com". */ private final ArrayList packageStructure = new ArrayList(); 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 5e4f90afa..940d50cbf 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 @@ -17,6 +17,15 @@ */ package org.owasp.dependencycheck.analyzer; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.apache.commons.io.FileUtils; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; @@ -30,9 +39,6 @@ import org.owasp.dependencycheck.utils.Settings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.*; -import java.util.*; -import java.util.logging.Level; import org.owasp.dependencycheck.data.nvdcve.DatabaseException; /** @@ -62,10 +68,8 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer { public static final String ADVISORY = "Advisory: "; public static final String CRITICALITY = "Criticality: "; - public CveDB cvedb; - //instance.open(); - //Vulnerability result = instance.getVulnerability("CVE-2015-3225"); - + private CveDB cvedb; + /** * @return a filter that accepts files named Gemfile.lock */ @@ -237,7 +241,7 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer { } catch (IOException ioe) { LOGGER.warn("bundle-audit failure", ioe); } finally { - if (errReader!= null) { + if (errReader != null) { try { errReader.close(); } catch (IOException ioe) { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/DownloadTask.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/DownloadTask.java index 1ec66a517..020c2263c 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/DownloadTask.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/DownloadTask.java @@ -261,6 +261,7 @@ public class DownloadTask implements Callable> { try { is.close(); } catch (IOException ex) { + LOGGER.debug("Error closing stream", ex); } } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionParser.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionParser.java index e4956ed1b..4d368fb3c 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionParser.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionParser.java @@ -25,7 +25,6 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.List; -import java.util.logging.Level; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; @@ -110,7 +109,8 @@ public class SuppressionParser { * * @param inputStream an InputStream containing suppression rues * @return a list of suppression rules - * @throws SuppressionParseException if the xml cannot be parsed + * @throws SuppressionParseException thrown if the xml cannot be parsed + * @throws SAXException thrown if the xml cannot be parsed */ public List parseSuppressionRules(InputStream inputStream) throws SuppressionParseException, SAXException { try { 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 68436e92e..4eabdcab9 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 @@ -59,7 +59,7 @@ public class RubyBundleAuditAnalyzerTest extends BaseTest { */ @Before public void setUp() throws Exception { - Settings.initialize(); + Settings.initialize(); analyzer = new RubyBundleAuditAnalyzer(); analyzer.setFilesMatched(true); } @@ -71,7 +71,7 @@ public class RubyBundleAuditAnalyzerTest extends BaseTest { */ @After public void tearDown() throws Exception { - Settings.cleanup(); + Settings.cleanup(); analyzer.close(); analyzer = null; } @@ -99,7 +99,7 @@ public class RubyBundleAuditAnalyzerTest extends BaseTest { */ @Test public void testAnalysis() throws AnalysisException, DatabaseException { - try { + try { analyzer.initialize(); final Dependency result = new Dependency(BaseTest.getResourceAsFile(this, @@ -113,7 +113,6 @@ public class RubyBundleAuditAnalyzerTest extends BaseTest { assertTrue(dependency.getProductEvidence().toString().toLowerCase().contains("redcarpet")); assertTrue(dependency.getVersionEvidence().toString().toLowerCase().contains("2.2.2")); - } catch (Exception e) { LOGGER.warn("Exception setting up RubyBundleAuditAnalyzer. Make sure Ruby gem bundle-audit is installed. You may also need to set property \"analyzer.bundle.audit.path\".", e); Assume.assumeNoException("Exception setting up RubyBundleAuditAnalyzer; bundle audit may not be installed, or property \"analyzer.bundle.audit.path\" may not be set.", e); @@ -133,7 +132,6 @@ public class RubyBundleAuditAnalyzerTest extends BaseTest { final Engine engine = new Engine(); analyzer.analyze(result, engine); - Dependency dependency = engine.getDependencies().get(0); Vulnerability vulnerability = dependency.getVulnerabilities().first(); assertEquals(vulnerability.getCvssScore(), 5.0f, 0.0); @@ -144,7 +142,6 @@ public class RubyBundleAuditAnalyzerTest extends BaseTest { } } - /** * Test when Ruby bundle-audit is not available on the system. * @@ -152,19 +149,17 @@ public class RubyBundleAuditAnalyzerTest extends BaseTest { */ @Test public void testMissingBundleAudit() throws AnalysisException, DatabaseException { - //set a non-exist bundle-audit + //set a non-exist bundle-audit Settings.setString(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, "phantom-bundle-audit"); try { //initialize should fail. - analyzer.initialize(); - } catch (Exception e) { - //expected, so ignore. - } - finally { - assertThat(analyzer.isEnabled(), is(false)); - LOGGER.info("phantom-bundle-audit is not available. Ruby Bundle Audit Analyzer is disabled as expected."); + analyzer.initialize(); + } catch (Exception e) { + //expected, so ignore. + } finally { + assertThat(analyzer.isEnabled(), is(false)); + LOGGER.info("phantom-bundle-audit is not available. Ruby Bundle Audit Analyzer is disabled as expected."); } } - } 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 1fd81babe..070c6e693 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 @@ -688,7 +688,7 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma } } Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate); - + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental); if (externalReport != null) { diff --git a/dependency-check-maven/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/dependency-check-maven/src/main/java/org/slf4j/impl/StaticLoggerBinder.java index bb9c6f538..af66c7ee3 100644 --- a/dependency-check-maven/src/main/java/org/slf4j/impl/StaticLoggerBinder.java +++ b/dependency-check-maven/src/main/java/org/slf4j/impl/StaticLoggerBinder.java @@ -23,8 +23,9 @@ import org.slf4j.ILoggerFactory; import org.slf4j.spi.LoggerFactoryBinder; /** - * The binding of org.slf4j.LoggerFactory class with an actual instance of org.slf4j.ILoggerFactory is performed using information - * returned by this class. + * The binding of org.slf4j.LoggerFactory class with an actual instance of + * org.slf4j.ILoggerFactory is performed using information returned by this + * class. * * @author colezlaw */ @@ -47,7 +48,7 @@ public class StaticLoggerBinder implements LoggerFactoryBinder { } /** - * Maven mojos have their own logger, so we'll use one of those + * Maven mojos have their own logger, so we'll use one of those. */ private Log log = null; @@ -62,8 +63,8 @@ public class StaticLoggerBinder implements LoggerFactoryBinder { } /** - * Declare the version of the SLF4J API this implementation is compiled against. The value of this filed is usually modified - * with each release. + * Declare the version of the SLF4J API this implementation is compiled + * against. The value of this filed is usually modified with each release. */ // to avoid constant folding by the compiler, this field must *not* be final //CSOFF: StaticVariableName @@ -78,7 +79,8 @@ public class StaticLoggerBinder implements LoggerFactoryBinder { private static final String LOGGER_FACTORY_CLASS = MavenLoggerFactory.class.getName(); /** - * The ILoggerFactory instance returned by the {@link #getLoggerFactory} method should always be the same object + * The ILoggerFactory instance returned by the {@link #getLoggerFactory} + * method should always be the same object */ private ILoggerFactory loggerFactory;