diff --git a/dependency-check-ant/README.md b/dependency-check-ant/README.md index d3496c649..d12265b6c 100644 --- a/dependency-check-ant/README.md +++ b/dependency-check-ant/README.md @@ -1,25 +1,134 @@ -Dependency-Check Ant Task +Dependency-Check-Gradle ========= -Dependency-Check Ant Task can be used to check the project dependencies for published security vulnerabilities. The checks -performed are a "best effort" and as such, there could be false positives as well as false negatives. However, -vulnerabilities in 3rd party components is a well-known problem and is currently documented in the 2013 OWASP -Top 10 as [A9 - Using Components with Known Vulnerabilities](https://www.owasp.org/index.php/Top_10_2013-A9-Using_Components_with_Known_Vulnerabilities). +**Working in progress** -Documentation and links to production binary releases can be found on the [github pages](http://jeremylong.github.io/DependencyCheck/dependency-check-ant/installation.html). +This is a DependencyCheck gradle plugin designed for project which use Gradle as build script. -Mailing List ------------- +Dependency-Check is a utility that attempts to detect publicly disclosed vulnerabilities contained within project dependencies. It does this by determining if there is a Common Platform Enumeration (CPE) identifier for a given dependency. If found, it will generate a report linking to the associated CVE entries. -Subscribe: [dependency-check+subscribe@googlegroups.com](mailto:dependency-check+subscribe@googlegroups.com) +========= -Post: [dependency-check@googlegroups.com](mailto:dependency-check@googlegroups.com) +## What's New +Current latest version is `0.0.8` -Copyright & License -------------------- +## Usage -Dependency-Check is Copyright (c) 2012-2014 Jeremy Long. All Rights Reserved. +### Step 1, Apply dependency check gradle plugin -Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt](https://raw.githubusercontent.com/jeremylong/DependencyCheck/master/LICENSE.txt) file for the full license. +Install from Maven central repo -Dependency-Check-Ant makes use of other open source libraries. Please see the [NOTICE.txt](https://raw.githubusercontent.com/jeremylong/DependencyCheck/master/dependency-check-ant/NOTICE.txt) file for more information. +```groovy +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath 'org.owasp:dependency-check-gradle:1.3.2' + } +} + +apply plugin: 'dependency-check-gradle' +``` + +### Step 2, Run gradle task + +Once gradle plugin applied, run following gradle task to check dependencies: + +``` +gradle dependencyCheck --info +``` + +The reports will be generated automatically under `./reports` folder. + +If your project includes multiple sub-projects, the report will be generated for each sub-project in different sub-directory. + +## FAQ + +> **Questions List:** +> - What if I'm behind a proxy? +> - What if my project includes multiple sub-project? How can I use this plugin for each of them including the root project? +> - How to customize the report directory? + +### What if I'm behind a proxy? + +Maybe you have to use proxy to access internet, in this case, you could configure proxy settings for this plugin: + +```groovy +dependencyCheck { + proxy { + server = "127.0.0.1" // required, the server name or IP address of the proxy + port = 3128 // required, the port number of the proxy + + // optional, the proxy server might require username + // username = "username" + + // optional, the proxy server might require password + // password = "password" + } +} +``` + +In addition, if the proxy only allow HTTP `GET` or `POST` methods, you will find that the update process will always fail, + the root cause is that every time you run `dependencyCheck` task, it will try to query the latest timestamp to determine whether need to perform an update action, + and for performance reason the HTTP method it uses by default is `HEAD`, which probably is disabled or not supported by the proxy. To avoid this problem, you can simply change the HTTP method by below configuration: + +```groovy +dependencyCheck { + quickQueryTimestamp = false // when set to false, it means use HTTP GET method to query timestamp. (default value is true) +} +``` + +### What if my project includes multiple sub-project? How can I use this plugin for each of them including the root project? + +Try put 'apply plugin: "dependency-check"' inside the 'allprojects' or 'subprojects' if you'd like to check all sub-projects only, see below: + +(1) For all projects including root project: + +```groovy +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath "gradle.plugin.com.tools.security:dependency-check:0.0.8" + } +} + +allprojects { + apply plugin: "dependency-check" +} +``` + +(2) For all sub-projects: + +```groovy +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath "gradle.plugin.com.tools.security:dependency-check:0.0.8" + } +} + +subprojects { + apply plugin: "dependency-check" +} +``` + +In this way, the dependency check will be executed for all projects (including root project) or just sub projects. + +### How to customize the report directory? + +By default, all reports will be placed under `./reports` folder, to change the default directory, just modify it in the configuration section like this: + +```groovy +subprojects { + apply plugin: "dependency-check" + + dependencyCheck { + outputDirectory = "./customized-path/security-report" + } +} +``` \ No newline at end of file diff --git a/dependency-check-ant/pom.xml b/dependency-check-ant/pom.xml index 78eb0cb07..00d8559a5 100644 --- a/dependency-check-ant/pom.xml +++ b/dependency-check-ant/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.3.1 + 1.3.2-SNAPSHOT dependency-check-ant 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 bb4c6a86f..cfefeb27c 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 @@ -245,14 +245,14 @@ public class Check extends Update { * Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. Default * is true. */ - private boolean autoUpdate = true; + private Boolean autoUpdate; /** * Get the value of autoUpdate. * * @return the value of autoUpdate */ - public boolean isAutoUpdate() { + public Boolean isAutoUpdate() { return autoUpdate; } @@ -261,19 +261,24 @@ public class Check extends Update { * * @param autoUpdate new value of autoUpdate */ - public void setAutoUpdate(boolean autoUpdate) { + public void setAutoUpdate(Boolean autoUpdate) { this.autoUpdate = autoUpdate; } /** * Whether only the update phase should be executed. + * + * @deprecated Use the update task instead */ + @Deprecated private boolean updateOnly = false; /** * Get the value of updateOnly. * * @return the value of updateOnly + * @deprecated Use the update task instead */ + @Deprecated public boolean isUpdateOnly() { return updateOnly; } @@ -282,7 +287,9 @@ public class Check extends Update { * Set the value of updateOnly. * * @param updateOnly new value of updateOnly + * @deprecated Use the update task instead */ + @Deprecated public void setUpdateOnly(boolean updateOnly) { this.updateOnly = updateOnly; } @@ -357,14 +364,14 @@ public class Check extends Update { /** * Whether or not the Jar Analyzer is enabled. */ - private boolean jarAnalyzerEnabled = true; + private Boolean jarAnalyzerEnabled; /** * Returns whether or not the analyzer is enabled. * * @return true if the analyzer is enabled */ - public boolean isJarAnalyzerEnabled() { + public Boolean isJarAnalyzerEnabled() { return jarAnalyzerEnabled; } @@ -373,33 +380,33 @@ public class Check extends Update { * * @param jarAnalyzerEnabled the value of the new setting */ - public void setJarAnalyzerEnabled(boolean jarAnalyzerEnabled) { + public void setJarAnalyzerEnabled(Boolean jarAnalyzerEnabled) { this.jarAnalyzerEnabled = jarAnalyzerEnabled; } /** * Whether or not the Archive Analyzer is enabled. */ - private boolean archiveAnalyzerEnabled = true; + private Boolean archiveAnalyzerEnabled; /** * Returns whether or not the analyzer is enabled. * * @return true if the analyzer is enabled */ - public boolean isArchiveAnalyzerEnabled() { + public Boolean isArchiveAnalyzerEnabled() { return archiveAnalyzerEnabled; } /** * Whether or not the .NET Assembly Analyzer is enabled. */ - private boolean assemblyAnalyzerEnabled = true; + private Boolean assemblyAnalyzerEnabled; /** * Sets whether or not the analyzer is enabled. * * @param archiveAnalyzerEnabled the value of the new setting */ - public void setArchiveAnalyzerEnabled(boolean archiveAnalyzerEnabled) { + public void setArchiveAnalyzerEnabled(Boolean archiveAnalyzerEnabled) { this.archiveAnalyzerEnabled = archiveAnalyzerEnabled; } @@ -408,7 +415,7 @@ public class Check extends Update { * * @return true if the analyzer is enabled */ - public boolean isAssemblyAnalyzerEnabled() { + public Boolean isAssemblyAnalyzerEnabled() { return assemblyAnalyzerEnabled; } @@ -417,20 +424,20 @@ public class Check extends Update { * * @param assemblyAnalyzerEnabled the value of the new setting */ - public void setAssemblyAnalyzerEnabled(boolean assemblyAnalyzerEnabled) { + public void setAssemblyAnalyzerEnabled(Boolean assemblyAnalyzerEnabled) { this.assemblyAnalyzerEnabled = assemblyAnalyzerEnabled; } /** * Whether or not the .NET Nuspec Analyzer is enabled. */ - private boolean nuspecAnalyzerEnabled = true; + private Boolean nuspecAnalyzerEnabled; /** * Returns whether or not the analyzer is enabled. * * @return true if the analyzer is enabled */ - public boolean isNuspecAnalyzerEnabled() { + public Boolean isNuspecAnalyzerEnabled() { return nuspecAnalyzerEnabled; } @@ -439,20 +446,20 @@ public class Check extends Update { * * @param nuspecAnalyzerEnabled the value of the new setting */ - public void setNuspecAnalyzerEnabled(boolean nuspecAnalyzerEnabled) { + public void setNuspecAnalyzerEnabled(Boolean nuspecAnalyzerEnabled) { this.nuspecAnalyzerEnabled = nuspecAnalyzerEnabled; } /** * Whether or not the PHP Composer Analyzer is enabled. */ - private boolean composerAnalyzerEnabled = true; + private Boolean composerAnalyzerEnabled; /** * Get the value of composerAnalyzerEnabled. * * @return the value of composerAnalyzerEnabled */ - public boolean isComposerAnalyzerEnabled() { + public Boolean isComposerAnalyzerEnabled() { return composerAnalyzerEnabled; } @@ -461,20 +468,20 @@ public class Check extends Update { * * @param composerAnalyzerEnabled new value of composerAnalyzerEnabled */ - public void setComposerAnalyzerEnabled(boolean composerAnalyzerEnabled) { + public void setComposerAnalyzerEnabled(Boolean composerAnalyzerEnabled) { this.composerAnalyzerEnabled = composerAnalyzerEnabled; } /** * Whether the autoconf analyzer should be enabled. */ - private boolean autoconfAnalyzerEnabled = true; + private Boolean autoconfAnalyzerEnabled; /** * Get the value of autoconfAnalyzerEnabled. * * @return the value of autoconfAnalyzerEnabled */ - public boolean isAutoconfAnalyzerEnabled() { + public Boolean isAutoconfAnalyzerEnabled() { return autoconfAnalyzerEnabled; } @@ -483,20 +490,20 @@ public class Check extends Update { * * @param autoconfAnalyzerEnabled new value of autoconfAnalyzerEnabled */ - public void setAutoconfAnalyzerEnabled(boolean autoconfAnalyzerEnabled) { + public void setAutoconfAnalyzerEnabled(Boolean autoconfAnalyzerEnabled) { this.autoconfAnalyzerEnabled = autoconfAnalyzerEnabled; } /** * Whether the CMake analyzer should be enabled. */ - private boolean cmakeAnalyzerEnabled = true; + private Boolean cmakeAnalyzerEnabled; /** * Get the value of cmakeAnalyzerEnabled. * * @return the value of cmakeAnalyzerEnabled */ - public boolean isCMakeAnalyzerEnabled() { + public Boolean isCMakeAnalyzerEnabled() { return cmakeAnalyzerEnabled; } @@ -505,20 +512,20 @@ public class Check extends Update { * * @param cmakeAnalyzerEnabled new value of cmakeAnalyzerEnabled */ - public void setCMakeAnalyzerEnabled(boolean cmakeAnalyzerEnabled) { + public void setCMakeAnalyzerEnabled(Boolean cmakeAnalyzerEnabled) { this.cmakeAnalyzerEnabled = cmakeAnalyzerEnabled; } /** * Whether or not the openssl analyzer is enabled. */ - private boolean opensslAnalyzerEnabled = true; + private Boolean opensslAnalyzerEnabled; /** * Get the value of opensslAnalyzerEnabled. * * @return the value of opensslAnalyzerEnabled */ - public boolean isOpensslAnalyzerEnabled() { + public Boolean isOpensslAnalyzerEnabled() { return opensslAnalyzerEnabled; } @@ -527,20 +534,20 @@ public class Check extends Update { * * @param opensslAnalyzerEnabled new value of opensslAnalyzerEnabled */ - public void setOpensslAnalyzerEnabled(boolean opensslAnalyzerEnabled) { + public void setOpensslAnalyzerEnabled(Boolean opensslAnalyzerEnabled) { this.opensslAnalyzerEnabled = opensslAnalyzerEnabled; } /** * Whether or not the Node.js Analyzer is enabled. */ - private boolean nodeAnalyzerEnabled = true; + private Boolean nodeAnalyzerEnabled; /** * Get the value of nodeAnalyzerEnabled. * * @return the value of nodeAnalyzerEnabled */ - public boolean isNodeAnalyzerEnabled() { + public Boolean isNodeAnalyzerEnabled() { return nodeAnalyzerEnabled; } @@ -549,20 +556,20 @@ public class Check extends Update { * * @param nodeAnalyzerEnabled new value of nodeAnalyzerEnabled */ - public void setNodeAnalyzerEnabled(boolean nodeAnalyzerEnabled) { + public void setNodeAnalyzerEnabled(Boolean nodeAnalyzerEnabled) { this.nodeAnalyzerEnabled = nodeAnalyzerEnabled; } /** * Whether the ruby gemspec analyzer should be enabled. */ - private boolean rubygemsAnalyzerEnabled = true; + private Boolean rubygemsAnalyzerEnabled; /** * Get the value of rubygemsAnalyzerEnabled. * * @return the value of rubygemsAnalyzerEnabled */ - public boolean isRubygemsAnalyzerEnabled() { + public Boolean isRubygemsAnalyzerEnabled() { return rubygemsAnalyzerEnabled; } @@ -571,20 +578,20 @@ public class Check extends Update { * * @param rubygemsAnalyzerEnabled new value of rubygemsAnalyzerEnabled */ - public void setRubygemsAnalyzerEnabled(boolean rubygemsAnalyzerEnabled) { + public void setRubygemsAnalyzerEnabled(Boolean rubygemsAnalyzerEnabled) { this.rubygemsAnalyzerEnabled = rubygemsAnalyzerEnabled; } /** * Whether the python package analyzer should be enabled. */ - private boolean pyPackageAnalyzerEnabled = true; + private Boolean pyPackageAnalyzerEnabled; /** * Get the value of pyPackageAnalyzerEnabled. * * @return the value of pyPackageAnalyzerEnabled */ - public boolean isPyPackageAnalyzerEnabled() { + public Boolean isPyPackageAnalyzerEnabled() { return pyPackageAnalyzerEnabled; } @@ -593,21 +600,21 @@ public class Check extends Update { * * @param pyPackageAnalyzerEnabled new value of pyPackageAnalyzerEnabled */ - public void setPyPackageAnalyzerEnabled(boolean pyPackageAnalyzerEnabled) { + public void setPyPackageAnalyzerEnabled(Boolean pyPackageAnalyzerEnabled) { this.pyPackageAnalyzerEnabled = pyPackageAnalyzerEnabled; } /** * Whether the python distribution analyzer should be enabled. */ - private boolean pyDistributionAnalyzerEnabled = true; + private Boolean pyDistributionAnalyzerEnabled; /** * Get the value of pyDistributionAnalyzerEnabled. * * @return the value of pyDistributionAnalyzerEnabled */ - public boolean isPyDistributionAnalyzerEnabled() { + public Boolean isPyDistributionAnalyzerEnabled() { return pyDistributionAnalyzerEnabled; } @@ -616,21 +623,21 @@ public class Check extends Update { * * @param pyDistributionAnalyzerEnabled new value of pyDistributionAnalyzerEnabled */ - public void setPyDistributionAnalyzerEnabled(boolean pyDistributionAnalyzerEnabled) { + public void setPyDistributionAnalyzerEnabled(Boolean pyDistributionAnalyzerEnabled) { this.pyDistributionAnalyzerEnabled = pyDistributionAnalyzerEnabled; } /** * Whether or not the central analyzer is enabled. */ - private boolean centralAnalyzerEnabled = false; + private Boolean centralAnalyzerEnabled; /** * Get the value of centralAnalyzerEnabled. * * @return the value of centralAnalyzerEnabled */ - public boolean isCentralAnalyzerEnabled() { + public Boolean isCentralAnalyzerEnabled() { return centralAnalyzerEnabled; } @@ -639,21 +646,21 @@ public class Check extends Update { * * @param centralAnalyzerEnabled new value of centralAnalyzerEnabled */ - public void setCentralAnalyzerEnabled(boolean centralAnalyzerEnabled) { + public void setCentralAnalyzerEnabled(Boolean centralAnalyzerEnabled) { this.centralAnalyzerEnabled = centralAnalyzerEnabled; } /** * Whether or not the nexus analyzer is enabled. */ - private boolean nexusAnalyzerEnabled = true; + private Boolean nexusAnalyzerEnabled; /** * Get the value of nexusAnalyzerEnabled. * * @return the value of nexusAnalyzerEnabled */ - public boolean isNexusAnalyzerEnabled() { + public Boolean isNexusAnalyzerEnabled() { return nexusAnalyzerEnabled; } @@ -662,7 +669,7 @@ public class Check extends Update { * * @param nexusAnalyzerEnabled new value of nexusAnalyzerEnabled */ - public void setNexusAnalyzerEnabled(boolean nexusAnalyzerEnabled) { + public void setNexusAnalyzerEnabled(Boolean nexusAnalyzerEnabled) { this.nexusAnalyzerEnabled = nexusAnalyzerEnabled; } @@ -691,14 +698,14 @@ public class Check extends Update { /** * Whether or not the defined proxy should be used when connecting to Nexus. */ - private boolean nexusUsesProxy = true; + private Boolean nexusUsesProxy; /** * Get the value of nexusUsesProxy. * * @return the value of nexusUsesProxy */ - public boolean isNexusUsesProxy() { + public Boolean isNexusUsesProxy() { return nexusUsesProxy; } @@ -707,7 +714,7 @@ public class Check extends Update { * * @param nexusUsesProxy new value of nexusUsesProxy */ - public void setNexusUsesProxy(boolean nexusUsesProxy) { + public void setNexusUsesProxy(Boolean nexusUsesProxy) { this.nexusUsesProxy = nexusUsesProxy; } @@ -839,42 +846,32 @@ 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. + * + * @throws BuildException thrown when an invalid setting is configured. */ @Override - protected void populateSettings() { + protected void populateSettings() throws BuildException { super.populateSettings(); - Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); - - if (suppressionFile != null && !suppressionFile.isEmpty()) { - Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); - } - - Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled); - - Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled); - Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled); - Settings.setBoolean(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, rubygemsAnalyzerEnabled); - Settings.setBoolean(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled); - Settings.setBoolean(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled); - Settings.setBoolean(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled); - Settings.setBoolean(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled); - Settings.setBoolean(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled); - - Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled); - Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled); - Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled); - if (nexusUrl != null && !nexusUrl.isEmpty()) { - Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); - } - Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy); - Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled); - if (zipExtensions != null && !zipExtensions.isEmpty()) { - Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions); - } - Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled); - if (pathToMono != null && !pathToMono.isEmpty()) { - Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); - } + Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate); + Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); + 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); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, rubygemsAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled); + Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); + Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions); + Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); } /** diff --git a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Update.java b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Update.java index cd8e2d107..b25979f67 100644 --- a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Update.java +++ b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Update.java @@ -357,6 +357,26 @@ public class Update extends Purge { this.cveUrl20Base = cveUrl20Base; } + private Integer cveValidForHours; + + /** + * Get the value of cveValidForHours + * + * @return the value of cveValidForHours + */ + public Integer getCveValidForHours() { + return cveValidForHours; + } + + /** + * Set the value of cveValidForHours + * + * @param cveValidForHours new value of cveValidForHours + */ + public void setCveValidForHours(Integer cveValidForHours) { + this.cveValidForHours = cveValidForHours; + } + /** * Executes the update by initializing the settings, downloads the NVD XML data, and then processes the data storing it in the * local database. @@ -383,51 +403,32 @@ public class Update extends Purge { /** * Takes the properties supplied and updates the dependency-check settings. Additionally, this sets the system properties * required to change the proxy server, port, and connection timeout. + * + * @throws BuildException thrown when an invalid setting is configured. */ @Override - protected void populateSettings() { + protected void populateSettings() throws BuildException { super.populateSettings(); - if (proxyServer != null && !proxyServer.isEmpty()) { - Settings.setString(Settings.KEYS.PROXY_SERVER, proxyServer); - } - if (proxyPort != null && !proxyPort.isEmpty()) { - Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort); - } - if (proxyUsername != null && !proxyUsername.isEmpty()) { - Settings.setString(Settings.KEYS.PROXY_USERNAME, proxyUsername); - } - if (proxyPassword != null && !proxyPassword.isEmpty()) { - Settings.setString(Settings.KEYS.PROXY_PASSWORD, proxyPassword); - } - if (connectionTimeout != null && !connectionTimeout.isEmpty()) { - Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); - } - if (databaseDriverName != null && !databaseDriverName.isEmpty()) { - Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); - } - if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) { - Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); - } - if (connectionString != null && !connectionString.isEmpty()) { - Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString); - } - if (databaseUser != null && !databaseUser.isEmpty()) { - Settings.setString(Settings.KEYS.DB_USER, databaseUser); - } - if (databasePassword != null && !databasePassword.isEmpty()) { - Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword); - } - if (cveUrl12Modified != null && !cveUrl12Modified.isEmpty()) { - Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified); - } - if (cveUrl20Modified != null && !cveUrl20Modified.isEmpty()) { - Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified); - } - if (cveUrl12Base != null && !cveUrl12Base.isEmpty()) { - Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base); - } - if (cveUrl20Base != null && !cveUrl20Base.isEmpty()) { - Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base); + Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_SERVER, proxyServer); + Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PORT, proxyPort); + Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_USERNAME, proxyUsername); + Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PASSWORD, proxyPassword); + Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword); + Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified); + Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified); + Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base); + Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base); + if (cveValidForHours != null) { + if (cveValidForHours >= 0) { + Settings.setInt(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours); + } else { + throw new BuildException("Invalid setting: `cpeValidForHours` must be 0 or greater"); + } } } } diff --git a/dependency-check-ant/src/site/markdown/config-update.md b/dependency-check-ant/src/site/markdown/config-update.md index be8405a7e..dd62e3dbe 100644 --- a/dependency-check-ant/src/site/markdown/config-update.md +++ b/dependency-check-ant/src/site/markdown/config-update.md @@ -32,10 +32,10 @@ may be the cvedUrl properties, which can be used to host a mirror of the NVD wit Property | Description | Default Value ---------------------|-------------------------------------------------------------------------------------------------------|------------------ -cveUrl12Modified | URL for the modified CVE 1.2. | http://nvd.nist.gov/download/nvdcve-modified.xml -cveUrl20Modified | URL for the modified CVE 2.0. | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml -cveUrl12Base | Base URL for each year's CVE 1.2, the %d will be replaced with the year. | http://nvd.nist.gov/download/nvdcve-%d.xml -cveUrl20Base | Base URL for each year's CVE 2.0, the %d will be replaced with the year. | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml +cveUrl12Modified | URL for the modified CVE 1.2. | https://nvd.nist.gov/download/nvdcve-Modified.xml.gz +cveUrl20Modified | URL for the modified CVE 2.0. | https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-Modified.xml.gz +cveUrl12Base | Base URL for each year's CVE 1.2, the %d will be replaced with the year. | https://nvd.nist.gov/download/nvdcve-%d.xml.gz +cveUrl20Base | Base URL for each year's CVE 2.0, the %d will be replaced with the year. | https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz dataDirectory | Data directory that is used to store the local copy of the NVD. This should generally not be changed. | data databaseDriverName | The name of the database driver. Example: org.h2.Driver. |   databaseDriverPath | The path to the database driver JAR file; only used if the driver is not in the class path. |   diff --git a/dependency-check-ant/src/site/markdown/configuration.md b/dependency-check-ant/src/site/markdown/configuration.md index 0f2f7d893..dafc18355 100644 --- a/dependency-check-ant/src/site/markdown/configuration.md +++ b/dependency-check-ant/src/site/markdown/configuration.md @@ -29,19 +29,20 @@ Configuration: dependency-check Task -------------------- The following properties can be set on the dependency-check-update task. -Property | Description | Default Value -----------------------|------------------------------------|------------------ -autoUpdate | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. | true -projectName | The name of the project being scanned. | Dependency-Check -reportOutputDirectory | The location to write the report(s). Note, this is not used if generating the report as part of a `mvn site` build | 'target' -failBuildOnCVSS | Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail. | 11 -reportFormat | The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the Site plugin unless the externalReport is set to true. | HTML -suppressionFile | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html) |   -proxyServer | The Proxy Server. |   -proxyPort | The Proxy Port. |   -proxyUsername | Defines the proxy user name. |   -proxyPassword | Defines the proxy password. |   -connectionTimeout | The URL Connection Timeout. |   +Property | Description | Default Value +----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------- +autoUpdate | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. | true +cveValidForHours | Sets the number of hours to wait before checking for new updates from the NVD | 4 +failBuildOnCVSS | Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail. | 11 +projectName | The name of the project being scanned. | Dependency-Check +reportFormat | The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the Site plugin unless the externalReport is set to true. | HTML +reportOutputDirectory | The location to write the report(s). Note, this is not used if generating the report as part of a `mvn site` build | 'target' +suppressionFile | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html) |   +proxyServer | The Proxy Server. |   +proxyPort | The Proxy Port. |   +proxyUsername | Defines the proxy user name. |   +proxyPassword | Defines the proxy password. |   +connectionTimeout | The URL Connection Timeout. |   Analyzer Configuration ==================== diff --git a/dependency-check-ant/src/test/java/org/owasp/dependencycheck/taskdefs/DependencyCheckTaskTest.java b/dependency-check-ant/src/test/java/org/owasp/dependencycheck/taskdefs/DependencyCheckTaskTest.java index f381e04d2..de9f62c1e 100644 --- a/dependency-check-ant/src/test/java/org/owasp/dependencycheck/taskdefs/DependencyCheckTaskTest.java +++ b/dependency-check-ant/src/test/java/org/owasp/dependencycheck/taskdefs/DependencyCheckTaskTest.java @@ -26,7 +26,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.owasp.dependencycheck.data.nvdcve.BaseDBTestCase; +import org.owasp.dependencycheck.BaseDBTestCase; import org.owasp.dependencycheck.utils.Settings; import static org.junit.Assert.assertTrue; diff --git a/dependency-check-cli/pom.xml b/dependency-check-cli/pom.xml index d79559436..56db3d8a1 100644 --- a/dependency-check-cli/pom.xml +++ b/dependency-check-cli/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.3.1 + 1.3.2-SNAPSHOT dependency-check-cli 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 5700d1e6c..b7d07c7cc 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 cveMod20 = cli.getModifiedCve20Url(); final String cveBase12 = cli.getBaseCve12Url(); final String cveBase20 = cli.getBaseCve20Url(); + final Integer cveValidForHours = cli.getCveValidForHours(); if (propertiesFile != null) { try { @@ -309,24 +310,13 @@ public class App { Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath()); } Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); - if (proxyServer != null && !proxyServer.isEmpty()) { - Settings.setString(Settings.KEYS.PROXY_SERVER, proxyServer); - } - if (proxyPort != null && !proxyPort.isEmpty()) { - Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort); - } - if (proxyUser != null && !proxyUser.isEmpty()) { - Settings.setString(Settings.KEYS.PROXY_USERNAME, proxyUser); - } - if (proxyPass != null && !proxyPass.isEmpty()) { - Settings.setString(Settings.KEYS.PROXY_PASSWORD, proxyPass); - } - if (connectionTimeout != null && !connectionTimeout.isEmpty()) { - Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); - } - if (suppressionFile != null && !suppressionFile.isEmpty()) { - Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); - } + Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_SERVER, proxyServer); + Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PORT, proxyPort); + Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_USERNAME, proxyUser); + Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PASSWORD, proxyPass); + Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); + Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); + Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours); //File Type Analyzer Settings Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !cli.isJarDisabled()); @@ -342,38 +332,19 @@ public class App { Settings.setBoolean(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, !cli.isComposerDisabled()); Settings.setBoolean(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, !cli.isNodeJsDisabled()); Settings.setBoolean(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, !cli.isRubyGemspecDisabled()); - Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, !cli.isCentralDisabled()); Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !cli.isNexusDisabled()); - if (nexusUrl != null && !nexusUrl.isEmpty()) { - Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); - } - Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy); - if (databaseDriverName != null && !databaseDriverName.isEmpty()) { - Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); - } - if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) { - Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); - } - if (connectionString != null && !connectionString.isEmpty()) { - Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString); - } - if (databaseUser != null && !databaseUser.isEmpty()) { - Settings.setString(Settings.KEYS.DB_USER, databaseUser); - } - if (databasePassword != null && !databasePassword.isEmpty()) { - Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword); - } - if (additionalZipExtensions != null && !additionalZipExtensions.isEmpty()) { - Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, additionalZipExtensions); - } - if (pathToMono != null && !pathToMono.isEmpty()) { - Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); - } - String pathToBundleAudit = cli.getPathToBundleAudit(); - if (!StringUtils.isEmpty(pathToBundleAudit)){ - Settings.setString(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, pathToBundleAudit); - } + + Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, cli.getPathToBundleAudit()); + Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); + Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword); + Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, additionalZipExtensions); + Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); if (cveBase12 != null && !cveBase12.isEmpty()) { Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveBase12); Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveBase20); 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 2dc56c75b..521a1842e 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 @@ -90,6 +90,19 @@ public final class CliParser { * @throws ParseException is thrown if there is an exception parsing the command line. */ private void validateArgs() throws FileNotFoundException, ParseException { + if (isUpdateOnly() || isRunScan()) { + String value = line.getOptionValue(ARGUMENT.CVE_VALID_FOR_HOURS); + if (value != null) { + try { + int i = Integer.parseInt(value); + if (i < 0) { + throw new ParseException("Invalid Setting: cveValidForHours must be a number greater than or equal to 0."); + } + } catch (NumberFormatException ex) { + throw new ParseException("Invalid Setting: cveValidForHours must be a number greater than or equal to 0."); + } + } + } if (isRunScan()) { validatePathExists(getScanFiles(), ARGUMENT.SCAN); validatePathExists(getReportDirectory(), ARGUMENT.OUT); @@ -255,6 +268,10 @@ public final class CliParser { .desc("The file path to the suppression XML file.") .build(); + final Option cveValidForHours = Option.builder().argName("hours").hasArg().longOpt(ARGUMENT.CVE_VALID_FOR_HOURS) + .desc("The number of hours to wait before checking for new updates from the NVD.") + .build(); + //This is an option group because it can be specified more then once. final OptionGroup og = new OptionGroup(); og.addOption(path); @@ -274,7 +291,8 @@ public final class CliParser { .addOption(symLinkDepth) .addOption(props) .addOption(verboseLog) - .addOption(suppressionFile); + .addOption(suppressionFile) + .addOption(cveValidForHours); } /** @@ -672,7 +690,7 @@ public final class CliParser { // still honor the property if it's set. if (line == null || !line.hasOption(ARGUMENT.NEXUS_USES_PROXY)) { try { - return Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY); + return Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY); } catch (InvalidSettingException ise) { return true; } @@ -997,6 +1015,19 @@ public final class CliParser { return line.getOptionValue(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS); } + /** + * Get the value of cveValidForHours + * + * @return the value of cveValidForHours + */ + public Integer getCveValidForHours() { + String v = line.getOptionValue(ARGUMENT.CVE_VALID_FOR_HOURS); + if (v != null) { + return Integer.parseInt(v); + } + return null; + } + /** * A collection of static final strings that represent the possible command line arguments. */ @@ -1160,6 +1191,10 @@ public final class CliParser { * 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. + */ + public static final String CVE_VALID_FOR_HOURS = "cveValidForHours"; /** * Disables the Jar Analyzer. */ diff --git a/dependency-check-cli/src/site/markdown/arguments.md b/dependency-check-cli/src/site/markdown/arguments.md index 3c3963877..66f37af01 100644 --- a/dependency-check-cli/src/site/markdown/arguments.md +++ b/dependency-check-cli/src/site/markdown/arguments.md @@ -17,15 +17,17 @@ Short | Argument Name   | Parameter | Description | Requir \-h | \-\-help | | Print the help message. | Optional | \-\-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 + Advanced Options ================ Short | Argument Name        | Parameter | Description | Default Value -------|-----------------------|-----------------|----------------------------------------------------------------------------------|------------------- - | \-\-cveUrl12Modified | \ | URL for the modified CVE 1.2 | http://nvd.nist.gov/download/nvdcve-modified.xml - | \-\-cveUrl20Modified | \ | URL for the modified CVE 2.0 | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml - | \-\-cveUrl12Base | \ | Base URL for each year's CVE 1.2, the %d will be replaced with the year | http://nvd.nist.gov/download/nvdcve-%d.xml - | \-\-cveUrl20Base | \ | Base URL for each year's CVE 2.0, the %d will be replaced with the year | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml + | \-\-cveUrl12Modified | \ | URL for the modified CVE 1.2 | https://nvd.nist.gov/download/nvdcve-Modified.xml.gz + | \-\-cveUrl20Modified | \ | URL for the modified CVE 2.0 | https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-Modified.xml.gz + | \-\-cveUrl12Base | \ | Base URL for each year's CVE 1.2, the %d will be replaced with the year | https://nvd.nist.gov/download/nvdcve-%d.xml.gz + | \-\-cveUrl20Base | \ | Base URL for each year's CVE 2.0, the %d will be replaced with the year | https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz \-P | \-\-propertyfile | \ | Specifies a file that contains properties to use instead of applicaion defaults. |   | \-\-updateonly | | If set only the update phase of dependency-check will be executed; no scan will be executed and no report will be generated. |   | \-\-disablePyDist | | Sets whether the Python Distribution Analyzer will be used. | false diff --git a/dependency-check-cli/src/site/markdown/index.md.vm b/dependency-check-cli/src/site/markdown/index.md.vm index 671da940a..a0f9b5e84 100644 --- a/dependency-check-cli/src/site/markdown/index.md.vm +++ b/dependency-check-cli/src/site/markdown/index.md.vm @@ -25,10 +25,10 @@ your homebrew installation. To scan a folder on the system you can run: $H$H$H Windows - dependency-check.bat --app "My App Name" --scan "c:\java\application\lib" + dependency-check.bat --project "My App Name" --scan "c:\java\application\lib" $H$H$H *nix - dependency-check.sh --app "My App Name" --scan "/java/application/lib" + dependency-check.sh --project "My App Name" --scan "/java/application/lib" To view the command line arguments, see the arguments page, or you can run: diff --git a/dependency-check-core/pom.xml b/dependency-check-core/pom.xml index 00695017f..b801dd8d0 100644 --- a/dependency-check-core/pom.xml +++ b/dependency-check-core/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.3.1 + 1.3.2-SNAPSHOT dependency-check-core @@ -468,7 +468,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. org.apache.maven.plugins maven-surefire-plugin - 2.18.1 true @@ -476,12 +475,68 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. org.apache.maven.plugins maven-failsafe-plugin - 2.18.1 data.driver_path - ${basedir}/${driver_path} + ${driver_path} + + + data.driver_name + ${driver_name} + + + data.connection_string + ${connection_string} + + + + **/*MySQLTest.java + + + + + + integration-test + verify + + + + + + + + + Postgresql-IntegrationTest + + + postgresql + + + + + org.postgresql + postgresql + 9.4-1204-jdbc42 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + data.driver_path + ${driver_path} data.driver_name 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 58b2712d7..fa120a0e8 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 @@ -38,6 +38,7 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileFilter; import java.util.ArrayList; +import java.util.Collection; import java.util.EnumMap; import java.util.HashSet; import java.util.Iterator; @@ -174,8 +175,7 @@ public class Engine implements FileFilter { public List scan(String[] paths) { final List deps = new ArrayList(); for (String path : paths) { - final File file = new File(path); - final List d = scan(file); + final List d = scan(path); if (d != null) { deps.addAll(d); } @@ -215,33 +215,14 @@ public class Engine implements FileFilter { } /** - * Scans a list of files or directories. If a directory is specified, it will be scanned recursively. Any dependencies + * Scans a collection of files or directories. If a directory is specified, it will be scanned recursively. Any dependencies * identified are added to the dependency collection. * * @param files a set of paths to files or directories to be analyzed * @return the list of dependencies scanned * @since v0.3.2.5 */ - public List scan(Set files) { - final List deps = new ArrayList(); - for (File file : files) { - final List d = scan(file); - if (d != null) { - deps.addAll(d); - } - } - return deps; - } - - /** - * Scans a list of files or directories. If a directory is specified, it will be scanned recursively. Any dependencies - * identified are added to the dependency collection. - * - * @param files a set of paths to files or directories to be analyzed - * @return the list of dependencies scanned - * @since v0.3.2.5 - */ - public List scan(List files) { + public List scan(Collection files) { final List deps = new ArrayList(); for (File file : files) { final List d = scan(file); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java index 7420e5302..ef3b1506d 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java @@ -840,8 +840,7 @@ public class DependencyCheckScanAgent { */ private Engine executeDependencyCheck() throws DatabaseException { populateSettings(); - Engine engine = null; - engine = new Engine(); + final Engine engine = new Engine(); engine.setDependencies(this.dependencies); engine.analyzeDependencies(); return engine; @@ -898,67 +897,28 @@ public class DependencyCheckScanAgent { } Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); - - if (proxyServer != null && !proxyServer.isEmpty()) { - Settings.setString(Settings.KEYS.PROXY_SERVER, proxyServer); - } - if (proxyPort != null && !proxyPort.isEmpty()) { - Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort); - } - if (proxyUsername != null && !proxyUsername.isEmpty()) { - Settings.setString(Settings.KEYS.PROXY_USERNAME, proxyUsername); - } - if (proxyPassword != null && !proxyPassword.isEmpty()) { - Settings.setString(Settings.KEYS.PROXY_PASSWORD, proxyPassword); - } - if (connectionTimeout != null && !connectionTimeout.isEmpty()) { - Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); - } - if (suppressionFile != null && !suppressionFile.isEmpty()) { - Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); - } + Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_SERVER, proxyServer); + Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PORT, proxyPort); + Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_USERNAME, proxyUsername); + Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PASSWORD, proxyPassword); + Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); + Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled); - if (centralUrl != null && !centralUrl.isEmpty()) { - Settings.setString(Settings.KEYS.ANALYZER_CENTRAL_URL, centralUrl); - } + Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_CENTRAL_URL, centralUrl); Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled); - if (nexusUrl != null && !nexusUrl.isEmpty()) { - Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); - } - Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy); - if (databaseDriverName != null && !databaseDriverName.isEmpty()) { - Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); - } - if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) { - Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); - } - if (connectionString != null && !connectionString.isEmpty()) { - Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString); - } - if (databaseUser != null && !databaseUser.isEmpty()) { - Settings.setString(Settings.KEYS.DB_USER, databaseUser); - } - if (databasePassword != null && !databasePassword.isEmpty()) { - Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword); - } - if (zipExtensions != null && !zipExtensions.isEmpty()) { - Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions); - } - if (cveUrl12Modified != null && !cveUrl12Modified.isEmpty()) { - Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified); - } - if (cveUrl20Modified != null && !cveUrl20Modified.isEmpty()) { - Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified); - } - if (cveUrl12Base != null && !cveUrl12Base.isEmpty()) { - Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base); - } - if (cveUrl20Base != null && !cveUrl20Base.isEmpty()) { - Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base); - } - if (pathToMono != null && !pathToMono.isEmpty()) { - Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); - } + Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); + Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword); + Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions); + Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified); + Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified); + Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base); + Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base); + Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); } /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.java index 6f23a75b2..26d8d8ab8 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.java @@ -214,7 +214,7 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen * @return a Set of strings. */ protected static Set newHashSet(String... strings) { - final Set set = new HashSet(); + final Set set = new HashSet(strings.length); Collections.addAll(set, strings); return set; } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java index 289b434ba..750b99432 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java @@ -114,8 +114,8 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer { static { final String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS); if (additionalZipExt != null) { - final Set ext = new HashSet(Collections.singletonList(additionalZipExt)); - ZIPPABLES.addAll(ext); + String[] ext = additionalZipExt.split("\\s*,\\s*"); + Collections.addAll(ZIPPABLES, ext); } EXTENSIONS.addAll(ZIPPABLES); } @@ -415,11 +415,9 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer { FileOutputStream fos = null; try { final File parent = file.getParentFile(); - if (!parent.isDirectory()) { - if (!parent.mkdirs()) { - final String msg = String.format("Unable to build directory '%s'.", parent.getAbsolutePath()); - throw new AnalysisException(msg); - } + if (!parent.isDirectory() && !parent.mkdirs()) { + final String msg = String.format("Unable to build directory '%s'.", parent.getAbsolutePath()); + throw new AnalysisException(msg); } fos = new FileOutputStream(file); IOUtils.copy(input, fos); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java index 8e5e20a1c..984ea8a22 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java @@ -17,13 +17,13 @@ */ package org.owasp.dependencycheck.analyzer; -import java.io.BufferedReader; import java.io.File; import java.io.FileFilter; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; +import org.apache.commons.io.IOUtils; +import org.apache.commons.io.output.NullOutputStream; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.dependency.Confidence; @@ -115,18 +115,15 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { final List args = buildArgumentList(); args.add(dependency.getActualFilePath()); final ProcessBuilder pb = new ProcessBuilder(args); - BufferedReader rdr = null; Document doc = null; try { final Process proc = pb.start(); // Try evacuating the error stream - rdr = new BufferedReader(new InputStreamReader(proc.getErrorStream(), "UTF-8")); - String line = null; - // CHECKSTYLE:OFF - while (rdr.ready() && (line = rdr.readLine()) != null) { - LOGGER.warn("Error from GrokAssembly: {}", line); + final String errorStream = IOUtils.toString(proc.getErrorStream(), "UTF-8"); + if (null != errorStream && !errorStream.isEmpty()) { + LOGGER.warn("Error from GrokAssembly: {}", errorStream); } - // CHECKSTYLE:ON + int rc = 0; doc = builder.parse(proc.getInputStream()); @@ -176,14 +173,6 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { } catch (XPathExpressionException xpe) { // This shouldn't happen throw new AnalysisException(xpe); - } finally { - if (rdr != null) { - try { - rdr.close(); - } catch (IOException ex) { - LOGGER.debug("ignore", ex); - } - } } } @@ -200,11 +189,8 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { try { fos = new FileOutputStream(tempFile); is = AssemblyAnalyzer.class.getClassLoader().getResourceAsStream("GrokAssembly.exe"); - final byte[] buff = new byte[4096]; - int bread = -1; - while ((bread = is.read(buff)) >= 0) { - fos.write(buff, 0, bread); - } + IOUtils.copy(is, fos); + grokAssemblyExe = tempFile; // Set the temp file to get deleted when we're done grokAssemblyExe.deleteOnExit(); @@ -232,17 +218,12 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { // Now, need to see if GrokAssembly actually runs from this location. final List args = buildArgumentList(); - BufferedReader rdr = null; try { final ProcessBuilder pb = new ProcessBuilder(args); final Process p = pb.start(); // Try evacuating the error stream - rdr = new BufferedReader(new InputStreamReader(p.getErrorStream(), "UTF-8")); - // CHECKSTYLE:OFF - while (rdr.ready() && rdr.readLine() != null) { - // We expect this to complain - } - // CHECKSTYLE:ON + IOUtils.copy(p.getErrorStream(), NullOutputStream.NULL_OUTPUT_STREAM); + final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(p.getInputStream()); final XPath xpath = XPathFactory.newInstance().newXPath(); final String error = xpath.evaluate("/assembly/error", doc); @@ -263,14 +244,6 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { this.setEnabled(false); throw new AnalysisException("An error occured with the .NET AssemblyAnalyzer", e); } - } finally { - if (rdr != null) { - try { - rdr.close(); - } catch (IOException ex) { - LOGGER.trace("ignore", ex); - } - } } builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java index 367fe376a..32272f342 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java @@ -335,7 +335,7 @@ public class CPEAnalyzer implements Analyzer { * @return if the append was successful. */ private boolean appendWeightedSearch(StringBuilder sb, String field, String searchText, Set weightedText) { - sb.append(" ").append(field).append(":( "); + sb.append(' ').append(field).append(":( "); final String cleanText = cleanseText(searchText); @@ -349,20 +349,27 @@ public class CPEAnalyzer implements Analyzer { final StringTokenizer tokens = new StringTokenizer(cleanText); while (tokens.hasMoreElements()) { final String word = tokens.nextToken(); - String temp = null; + StringBuilder temp = null; for (String weighted : weightedText) { final String weightedStr = cleanseText(weighted); if (equalsIgnoreCaseAndNonAlpha(word, weightedStr)) { - temp = LuceneUtils.escapeLuceneQuery(word) + WEIGHTING_BOOST; + temp = new StringBuilder(word.length() + 2); + LuceneUtils.appendEscapedLuceneQuery(temp, word); + temp.append(WEIGHTING_BOOST); if (!word.equalsIgnoreCase(weightedStr)) { - temp += " " + LuceneUtils.escapeLuceneQuery(weightedStr) + WEIGHTING_BOOST; + temp.append(' '); + LuceneUtils.appendEscapedLuceneQuery(temp, weightedStr); + temp.append(WEIGHTING_BOOST); } + break; } } + sb.append(' '); if (temp == null) { - temp = LuceneUtils.escapeLuceneQuery(word); + LuceneUtils.appendEscapedLuceneQuery(sb, word); + } else { + sb.append(temp); } - sb.append(" ").append(temp); } } sb.append(" ) "); @@ -515,7 +522,7 @@ public class CPEAnalyzer implements Analyzer { for (VulnerableSoftware vs : cpes) { DependencyVersion dbVer; if (vs.getUpdate() != null && !vs.getUpdate().isEmpty()) { - dbVer = DependencyVersionUtil.parseVersion(vs.getVersion() + "." + vs.getUpdate()); + dbVer = DependencyVersionUtil.parseVersion(vs.getVersion() + '.' + vs.getUpdate()); } else { dbVer = DependencyVersionUtil.parseVersion(vs.getVersion()); } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CentralAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CentralAnalyzer.java index 70e8d3159..08b9d4f63 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CentralAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CentralAnalyzer.java @@ -192,7 +192,7 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer { final List mas = searcher.searchSha1(dependency.getSha1sum()); final Confidence confidence = mas.size() > 1 ? Confidence.HIGH : Confidence.HIGHEST; for (MavenArtifact ma : mas) { - LOGGER.debug("Central analyzer found artifact ({}) for dependency ({})", ma.toString(), dependency.getFileName()); + LOGGER.debug("Central analyzer found artifact ({}) for dependency ({})", ma, dependency.getFileName()); dependency.addAsEvidence("central", ma, confidence); boolean pomAnalyzed = false; for (Evidence e : dependency.getVendorEvidence()) { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.java index 2ad6d895f..ce326cf57 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.java @@ -113,7 +113,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer { for (Identifier i : dependency.getIdentifiers()) { if ("maven".contains(i.getType())) { if (i.getValue() != null && i.getValue().startsWith("org.springframework.")) { - final int endPoint = i.getValue().indexOf(":", 19); + final int endPoint = i.getValue().indexOf(':', 19); if (endPoint >= 0) { mustContain = i.getValue().substring(19, endPoint).toLowerCase(); break; @@ -472,8 +472,8 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer { */ private String trimCpeToVendor(String value) { //cpe:/a:jruby:jruby:1.0.8 - final int pos1 = value.indexOf(":", 7); //right of vendor - final int pos2 = value.indexOf(":", pos1 + 1); //right of product + final int pos1 = value.indexOf(':', 7); //right of vendor + final int pos2 = value.indexOf(':', pos1 + 1); //right of product if (pos2 < 0) { return value; } else { 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 645afce07..d21f7b503 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 @@ -18,6 +18,7 @@ package org.owasp.dependencycheck.analyzer; import java.io.File; +import org.apache.commons.io.FilenameUtils; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.dependency.Confidence; @@ -76,13 +77,7 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer { //strip any path information that may get added by ArchiveAnalyzer, etc. final File f = dependency.getActualFile(); - String fileName = f.getName(); - - //remove file extension - final int pos = fileName.lastIndexOf("."); - if (pos > 0) { - fileName = fileName.substring(0, pos); - } + final String fileName = FilenameUtils.removeExtension(f.getName()); //add version evidence final DependencyVersion version = DependencyVersionUtil.parseVersion(fileName); 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 7f806ba0a..92cce15c7 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 @@ -42,6 +42,7 @@ import java.util.jar.Manifest; import java.util.regex.Pattern; import java.util.zip.ZipEntry; import org.apache.commons.compress.utils.IOUtils; +import org.apache.commons.io.FilenameUtils; import org.jsoup.Jsoup; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; @@ -269,8 +270,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { } File externalPom = null; if (pomEntries.isEmpty()) { - String pomPath = dependency.getActualFilePath(); - pomPath = pomPath.substring(0, pomPath.lastIndexOf('.')) + ".pom"; + final String pomPath = FilenameUtils.removeExtension(dependency.getActualFilePath()) + ".pom"; externalPom = new File(pomPath); if (externalPom.isFile()) { pomEntries.add(pomPath); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java index 9c6b3aea6..c23322d76 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java @@ -104,7 +104,7 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer { */ boolean retval = false; try { - if ((!DEFAULT_URL.equals(Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL))) + if (!DEFAULT_URL.equals(Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL)) && Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED)) { LOGGER.info("Enabling Nexus analyzer"); retval = true; diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.java index 9e24f56f5..d3950c793 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.java @@ -126,7 +126,7 @@ public class NuspecAnalyzer extends AbstractFileTypeAnalyzer { */ @Override public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException { - LOGGER.debug("Checking Nuspec file {}", dependency.toString()); + LOGGER.debug("Checking Nuspec file {}", dependency); try { final NuspecParser parser = new XPathNuspecParser(); NugetPackage np = null; diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.java index e252c5481..249dd4855 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.java @@ -73,7 +73,7 @@ public class NvdCveAnalyzer implements Analyzer { * @return true or false. */ public boolean isOpen() { - return (cveDB != null); + return cveDB != null; } /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/central/CentralSearch.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/central/CentralSearch.java index a5f484c43..d4ba768c1 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/central/CentralSearch.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/central/CentralSearch.java @@ -90,7 +90,7 @@ public class CentralSearch { final URL url = new URL(rootURL + String.format("?q=1:\"%s\"&wt=xml", sha1)); - LOGGER.debug("Searching Central url {}", url.toString()); + LOGGER.debug("Searching Central url {}", url); // Determine if we need to use a proxy. The rules: // 1) If the proxy is set, AND the setting is set to true, use the proxy diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerException.java index 8b4d841aa..16be04bc5 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerException.java @@ -24,6 +24,11 @@ package org.owasp.dependencycheck.data.composer; */ public class ComposerException extends RuntimeException { + /** + * The serial version UID for serialization. + */ + private static final long serialVersionUID = 1L; + /** * Creates a ComposerException with default message. */ diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java index 15bbdcdb1..7e3c3e01e 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java @@ -149,7 +149,6 @@ public final class CpeMemoryIndex { * * @return the CPE Analyzer. */ - @SuppressWarnings("unchecked") private Analyzer createIndexingAnalyzer() { final Map fieldAnalyzers = new HashMap(); fieldAnalyzers.put(Fields.DOCUMENT_KEY, new KeywordAnalyzer()); @@ -161,7 +160,6 @@ public final class CpeMemoryIndex { * * @return the CPE Analyzer. */ - @SuppressWarnings("unchecked") private Analyzer createSearchingAnalyzer() { final Map fieldAnalyzers = new HashMap(); fieldAnalyzers.put(Fields.DOCUMENT_KEY, new KeywordAnalyzer()); @@ -173,24 +171,6 @@ public final class CpeMemoryIndex { return new PerFieldAnalyzerWrapper(new FieldAnalyzer(LuceneUtils.CURRENT_VERSION), fieldAnalyzers); } - /** - * Saves a CPE IndexEntry into the Lucene index. - * - * @param vendor the vendor to index - * @param product the product to index - * @param indexWriter the index writer to write the entry into - * @throws CorruptIndexException is thrown if the index is corrupt - * @throws IOException is thrown if an IOException occurs - */ - public void saveEntry(String vendor, String product, IndexWriter indexWriter) throws CorruptIndexException, IOException { - final Document doc = new Document(); - final Field v = new TextField(Fields.VENDOR, vendor, Field.Store.YES); - final Field p = new TextField(Fields.PRODUCT, product, Field.Store.YES); - doc.add(v); - doc.add(p); - indexWriter.addDocument(doc); - } - /** * Closes the CPE Index. */ @@ -230,9 +210,20 @@ public final class CpeMemoryIndex { final IndexWriterConfig conf = new IndexWriterConfig(LuceneUtils.CURRENT_VERSION, analyzer); indexWriter = new IndexWriter(index, conf); try { + // Tip: reuse the Document and Fields for performance... + // See "Re-use Document and Field instances" from + // http://wiki.apache.org/lucene-java/ImproveIndexingSpeed + final Document doc = new Document(); + final Field v = new TextField(Fields.VENDOR, Fields.VENDOR, Field.Store.YES); + final Field p = new TextField(Fields.PRODUCT, Fields.PRODUCT, Field.Store.YES); + doc.add(v); + doc.add(p); + final Set> data = cve.getVendorProductList(); for (Pair pair : data) { - saveEntry(pair.getLeft(), pair.getRight(), indexWriter); + v.setStringValue(pair.getLeft()); + p.setStringValue(pair.getRight()); + indexWriter.addDocument(doc); } } catch (DatabaseException ex) { LOGGER.debug("", ex); @@ -287,8 +278,9 @@ public final class CpeMemoryIndex { if (searchString == null || searchString.trim().isEmpty()) { throw new ParseException("Query is null or empty"); } + LOGGER.debug(searchString); final Query query = queryParser.parse(searchString); - return indexSearcher.search(query, maxQueryResults); + return search(query, maxQueryResults); } /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/IndexEntry.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/IndexEntry.java index 7fdd34d06..39c7fc8f0 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/IndexEntry.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/IndexEntry.java @@ -48,7 +48,7 @@ public class IndexEntry implements Serializable { */ public String getDocumentId() { if (documentId == null && vendor != null && product != null) { - documentId = vendor + ":" + product; + documentId = vendor + ':' + product; } return documentId; } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/LuceneUtils.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/LuceneUtils.java index 99707dcac..2fac02e15 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/LuceneUtils.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/LuceneUtils.java @@ -77,6 +77,7 @@ public final class LuceneUtils { case '*': case '?': case ':': + case '/': case '\\': //it is supposed to fall through here buf.append('\\'); default: diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/MavenArtifact.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/MavenArtifact.java index 7ad47b928..e69ee8d76 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/MavenArtifact.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/MavenArtifact.java @@ -94,13 +94,13 @@ public class MavenArtifact { } if (jarAvailable) { //org/springframework/spring-core/3.2.0.RELEASE/spring-core-3.2.0.RELEASE.pom - this.artifactUrl = base + groupId.replace('.', '/') + "/" + artifactId + "/" - + version + "/" + artifactId + "-" + version + ".jar"; + this.artifactUrl = base + groupId.replace('.', '/') + '/' + artifactId + '/' + + version + '/' + artifactId + '-' + version + ".jar"; } if (pomAvailable) { //org/springframework/spring-core/3.2.0.RELEASE/spring-core-3.2.0.RELEASE.pom - this.pomUrl = base + groupId.replace('.', '/') + "/" + artifactId + "/" - + version + "/" + artifactId + "-" + version + ".pom"; + this.pomUrl = base + groupId.replace('.', '/') + '/' + artifactId + '/' + + version + '/' + artifactId + '-' + version + ".pom"; } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java index 3c53504b1..e43912491 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java @@ -63,7 +63,7 @@ public class NexusSearch { this.rootURL = rootURL; try { if (null != Settings.getString(Settings.KEYS.PROXY_SERVER) - && Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY)) { + && Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY)) { useProxy = true; LOGGER.debug("Using proxy"); } else { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/ConnectionFactory.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/ConnectionFactory.java index 4378e363f..1016248c9 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/ConnectionFactory.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/ConnectionFactory.java @@ -17,11 +17,9 @@ */ package org.owasp.dependencycheck.data.nvdcve; -import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.Driver; @@ -29,7 +27,10 @@ import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import org.apache.commons.io.IOUtils; import org.owasp.dependencycheck.utils.DBUtils; +import org.owasp.dependencycheck.utils.DependencyVersion; +import org.owasp.dependencycheck.utils.DependencyVersionUtil; import org.owasp.dependencycheck.utils.Settings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -58,6 +59,10 @@ public final class ConnectionFactory { * Resource location for SQL file used to create the database schema. */ public static final String DB_STRUCTURE_UPDATE_RESOURCE = "data/upgrade_%s.sql"; + /** + * The URL that discusses upgrading non-H2 databases. + */ + public static final String UPGRADE_HELP_URL = "http://jeremylong.github.io/DependencyCheck/data/upgrade.html"; /** * The database driver used to connect to the database. */ @@ -243,22 +248,15 @@ public final class ConnectionFactory { */ private static void createTables(Connection conn) throws DatabaseException { LOGGER.debug("Creating database structure"); - InputStream is; - InputStreamReader reader; - BufferedReader in = null; + InputStream is = null; try { is = ConnectionFactory.class.getClassLoader().getResourceAsStream(DB_STRUCTURE_RESOURCE); - reader = new InputStreamReader(is, "UTF-8"); - in = new BufferedReader(reader); - final StringBuilder sb = new StringBuilder(2110); - String tmp; - while ((tmp = in.readLine()) != null) { - sb.append(tmp); - } + final String dbStructure = IOUtils.toString(is, "UTF-8"); + Statement statement = null; try { statement = conn.createStatement(); - statement.execute(sb.toString()); + statement.execute(dbStructure); } catch (SQLException ex) { LOGGER.debug("", ex); throw new DatabaseException("Unable to create database statement", ex); @@ -268,13 +266,7 @@ public final class ConnectionFactory { } catch (IOException ex) { throw new DatabaseException("Unable to create database schema", ex); } finally { - if (in != null) { - try { - in.close(); - } catch (IOException ex) { - LOGGER.trace("", ex); - } - } + IOUtils.closeQuietly(is); } } @@ -288,48 +280,54 @@ public final class ConnectionFactory { * @throws DatabaseException thrown if there is an exception upgrading the database schema */ private static void updateSchema(Connection conn, String schema) throws DatabaseException { - LOGGER.debug("Updating database structure"); - InputStream is; - InputStreamReader reader; - BufferedReader in = null; - String updateFile = null; + final String databaseProductName; try { - updateFile = String.format(DB_STRUCTURE_UPDATE_RESOURCE, schema); - is = ConnectionFactory.class.getClassLoader().getResourceAsStream(updateFile); - if (is == null) { - throw new DatabaseException(String.format("Unable to load update file '%s'", updateFile)); - } - reader = new InputStreamReader(is, "UTF-8"); - in = new BufferedReader(reader); - final StringBuilder sb = new StringBuilder(2110); - String tmp; - while ((tmp = in.readLine()) != null) { - sb.append(tmp); - } - Statement statement = null; + databaseProductName = conn.getMetaData().getDatabaseProductName(); + } catch (SQLException ex) { + throw new DatabaseException("Unable to get the database product name"); + } + if ("h2".equalsIgnoreCase(databaseProductName)) { + LOGGER.debug("Updating database structure"); + InputStream is = null; + String updateFile = null; try { - statement = conn.createStatement(); - statement.execute(sb.toString()); - } catch (SQLException ex) { - LOGGER.debug("", ex); - throw new DatabaseException("Unable to update database schema", ex); - } finally { - DBUtils.closeStatement(statement); - } - } catch (IOException ex) { - final String msg = String.format("Upgrade SQL file does not exist: %s", updateFile); - throw new DatabaseException(msg, ex); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException ex) { - LOGGER.trace("", ex); + updateFile = String.format(DB_STRUCTURE_UPDATE_RESOURCE, schema); + is = ConnectionFactory.class.getClassLoader().getResourceAsStream(updateFile); + if (is == null) { + throw new DatabaseException(String.format("Unable to load update file '%s'", updateFile)); } + final String dbStructureUpdate = IOUtils.toString(is, "UTF-8"); + + Statement statement = null; + try { + statement = conn.createStatement(); + final boolean success = statement.execute(dbStructureUpdate); + if (!success && statement.getUpdateCount() <= 0) { + throw new DatabaseException(String.format("Unable to upgrade the database schema to %s", schema)); + } + } catch (SQLException ex) { + LOGGER.debug("", ex); + throw new DatabaseException("Unable to update database schema", ex); + } finally { + DBUtils.closeStatement(statement); + } + } catch (IOException ex) { + final String msg = String.format("Upgrade SQL file does not exist: %s", updateFile); + throw new DatabaseException(msg, ex); + } finally { + IOUtils.closeQuietly(is); } + } else { + LOGGER.error("The database schema must be upgraded to use this version of dependency-check. Please see {} for more information.", UPGRADE_HELP_URL); + throw new DatabaseException("Database schema is out of date"); } } + /** + * Counter to ensure that calls to ensureSchemaVersion does not end up in an endless loop. + */ + private static int callDepth = 0; + /** * Uses the provided connection to check the specified schema version within the database. * @@ -344,10 +342,15 @@ public final class ConnectionFactory { cs = conn.prepareCall("SELECT value FROM properties WHERE id = 'version'"); rs = cs.executeQuery(); if (rs.next()) { - if (!DB_SCHEMA_VERSION.equals(rs.getString(1))) { + final DependencyVersion current = DependencyVersionUtil.parseVersion(DB_SCHEMA_VERSION); + final DependencyVersion db = DependencyVersionUtil.parseVersion(rs.getString(1)); + if (current.compareTo(db) > 0) { LOGGER.debug("Current Schema: " + DB_SCHEMA_VERSION); LOGGER.debug("DB Schema: " + rs.getString(1)); updateSchema(conn, rs.getString(1)); + if (++callDepth < 10) { + ensureSchemaVersion(conn); + } } } else { throw new DatabaseException("Database schema is missing"); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java index 9df790976..42bceef0d 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java @@ -29,8 +29,10 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; +import java.util.MissingResourceException; import java.util.Properties; import java.util.ResourceBundle; import java.util.Set; @@ -74,9 +76,17 @@ public class CveDB { */ public CveDB() throws DatabaseException { super(); - statementBundle = ResourceBundle.getBundle("data/dbStatements"); try { open(); + try { + final String databaseProductName = conn.getMetaData().getDatabaseProductName(); + LOGGER.debug("Database dialect: {}", databaseProductName); + final Locale dbDialect = new Locale(databaseProductName); + statementBundle = ResourceBundle.getBundle("data/dbStatements", dbDialect); + } catch (SQLException se) { + LOGGER.warn("Problem loading database specific dialect!", se); + statementBundle = ResourceBundle.getBundle("data/dbStatements"); + } databaseProperties = new DatabaseProperties(this); } catch (DatabaseException ex) { throw ex; @@ -252,44 +262,6 @@ public class CveDB { return prop; } - /** - * Saves a set of properties to the database. - * - * @param props a collection of properties - */ - void saveProperties(Properties props) { - PreparedStatement updateProperty = null; - PreparedStatement insertProperty = null; - try { - try { - updateProperty = getConnection().prepareStatement(statementBundle.getString("UPDATE_PROPERTY")); - insertProperty = getConnection().prepareStatement(statementBundle.getString("INSERT_PROPERTY")); - } catch (SQLException ex) { - LOGGER.warn("Unable to save properties to the database"); - LOGGER.debug("Unable to save properties to the database", ex); - return; - } - for (Entry entry : props.entrySet()) { - final String key = entry.getKey().toString(); - final String value = entry.getValue().toString(); - try { - updateProperty.setString(1, value); - updateProperty.setString(2, key); - if (updateProperty.executeUpdate() == 0) { - insertProperty.setString(1, key); - insertProperty.setString(2, value); - } - } catch (SQLException ex) { - LOGGER.warn("Unable to save property '{}' with a value of '{}' to the database", key, value); - LOGGER.debug("", ex); - } - } - } finally { - DBUtils.closeStatement(updateProperty); - DBUtils.closeStatement(insertProperty); - } - } - /** * Saves a property to the database. * @@ -297,38 +269,38 @@ public class CveDB { * @param value the property value */ void saveProperty(String key, String value) { - PreparedStatement updateProperty = null; - PreparedStatement insertProperty = null; try { try { - updateProperty = getConnection().prepareStatement(statementBundle.getString("UPDATE_PROPERTY")); - } catch (SQLException ex) { - LOGGER.warn("Unable to save properties to the database"); - LOGGER.debug("Unable to save properties to the database", ex); - return; - } - try { - updateProperty.setString(1, value); - updateProperty.setString(2, key); - if (updateProperty.executeUpdate() == 0) { - try { - insertProperty = getConnection().prepareStatement(statementBundle.getString("INSERT_PROPERTY")); - } catch (SQLException ex) { - LOGGER.warn("Unable to save properties to the database"); - LOGGER.debug("Unable to save properties to the database", ex); - return; - } - insertProperty.setString(1, key); - insertProperty.setString(2, value); - insertProperty.execute(); + final PreparedStatement mergeProperty = getConnection().prepareStatement(statementBundle.getString("MERGE_PROPERTY")); + try { + mergeProperty.setString(1, key); + mergeProperty.setString(2, value); + mergeProperty.executeUpdate(); + } finally { + DBUtils.closeStatement(mergeProperty); + } + } catch (MissingResourceException mre) { + // No Merge statement, so doing an Update/Insert... + PreparedStatement updateProperty = null; + PreparedStatement insertProperty = null; + try { + updateProperty = getConnection().prepareStatement(statementBundle.getString("UPDATE_PROPERTY")); + updateProperty.setString(1, value); + updateProperty.setString(2, key); + if (updateProperty.executeUpdate() == 0) { + insertProperty = getConnection().prepareStatement(statementBundle.getString("INSERT_PROPERTY")); + insertProperty.setString(1, key); + insertProperty.setString(2, value); + insertProperty.executeUpdate(); + } + } finally { + DBUtils.closeStatement(updateProperty); + DBUtils.closeStatement(insertProperty); } - } catch (SQLException ex) { - LOGGER.warn("Unable to save property '{}' with a value of '{}' to the database", key, value); - LOGGER.debug("", ex); } - } finally { - DBUtils.closeStatement(updateProperty); - DBUtils.closeStatement(insertProperty); + } catch (SQLException ex) { + LOGGER.warn("Unable to save property '{}' with a value of '{}' to the database", key, value); + LOGGER.debug("", ex); } } @@ -420,7 +392,7 @@ public class CveDB { if (cwe != null) { final String name = CweDB.getCweName(cwe); if (name != null) { - cwe += " " + name; + cwe += ' ' + name; } } final int cveId = rsV.getInt(1); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseProperties.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseProperties.java index f3ae9b50c..ad1cf8434 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseProperties.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseProperties.java @@ -45,6 +45,10 @@ public class DatabaseProperties { * updates).. */ public static final String MODIFIED = "Modified"; + /** + * The properties file key for the last checked field - used to store the last check time of the Modified NVD CVE xml file. + */ + public static final String LAST_CHECKED = "NVD CVE Checked"; /** * The properties file key for the last updated field - used to store the last updated time of the Modified NVD CVE xml file. */ diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/CpeUpdater.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/CpeUpdater.java index b2e7096ac..0c158a92d 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/CpeUpdater.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/CpeUpdater.java @@ -137,7 +137,7 @@ public class CpeUpdater extends BaseUpdater implements CachedWebDataSource { */ private boolean updateNeeded() { final long now = System.currentTimeMillis(); - final int days = Settings.getInt(Settings.KEYS.CVE_MODIFIED_VALID_FOR_DAYS, 30); + final int days = Settings.getInt(Settings.KEYS.CPE_MODIFIED_VALID_FOR_DAYS, 30); long timestamp = 0; final String ts = getProperties().getProperty(LAST_CPE_UPDATE); if (ts != null && ts.matches("^[0-9]+$")) { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/NvdCveUpdater.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/NvdCveUpdater.java index 570c542ea..3b3215e94 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/NvdCveUpdater.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/NvdCveUpdater.java @@ -66,9 +66,11 @@ public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource { public void update() throws UpdateException { try { openDataStores(); - final UpdateableNvdCve updateable = getUpdatesNeeded(); - if (updateable.isUpdateNeeded()) { - performUpdate(updateable); + if (checkUpdate()) { + final UpdateableNvdCve updateable = getUpdatesNeeded(); + if (updateable.isUpdateNeeded()) { + performUpdate(updateable); + } } } catch (MalformedURLException ex) { LOGGER.warn( @@ -87,6 +89,35 @@ public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource { } } + /** + * Checks if the NVD CVE XML files were last checked recently. + * As an optimization, we can avoid repetitive checks against the NVD. + * Setting CVE_CHECK_VALID_FOR_HOURS determines the duration since last check before checking again. + * A database property stores the timestamp of the last check. + * + * @return true to proceed with the check, or false to skip. + */ + private boolean checkUpdate () throws UpdateException { + boolean proceed = true; + // If the valid setting has not been specified, then we proceed to check... + final int validForHours = Settings.getInt(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, 0); + if (0 < validForHours) { + // ms Valid = valid (hours) x 60 min/hour x 60 sec/min x 1000 ms/sec + final long msValid = validForHours * 60L * 60L * 1000L; + final long lastChecked = Long.parseLong(getProperties().getProperty(DatabaseProperties.LAST_CHECKED, "0")); + final long now = System.currentTimeMillis(); + proceed = (now - lastChecked) > msValid; + if (proceed) { + getProperties().save(DatabaseProperties.LAST_CHECKED, Long.toString(now)); + } else { + LOGGER.info("Skipping NVD check since last check was within {} hours.", validForHours); + LOGGER.debug("Last NVD was at {}, and now {} is within {} ms.", + lastChecked, now, msValid); + } + } + return proceed; + } + /** * Downloads the latest NVD CVE XML file from the web and imports it into the current CVE Database. * 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 4b4d04201..333f9aa4c 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 @@ -68,8 +68,8 @@ public class DownloadTask implements Callable> { final File file2; try { - file1 = File.createTempFile("cve" + nvdCveInfo.getId() + "_", ".xml", Settings.getTempDirectory()); - file2 = File.createTempFile("cve_1_2_" + nvdCveInfo.getId() + "_", ".xml", Settings.getTempDirectory()); + file1 = File.createTempFile("cve" + nvdCveInfo.getId() + '_', ".xml", Settings.getTempDirectory()); + file2 = File.createTempFile("cve_1_2_" + nvdCveInfo.getId() + '_', ".xml", Settings.getTempDirectory()); } catch (IOException ex) { throw new UpdateException("Unable to create temporary files", ex); } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/NvdCve12Handler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/NvdCve12Handler.java index 26811ae7b..ef4f83d0e 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/NvdCve12Handler.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/NvdCve12Handler.java @@ -114,10 +114,10 @@ public class NvdCve12Handler extends DefaultHandler { in the nvd cve 2.0. */ String cpe = "cpe:/a:" + vendor + ":" + product; if (num != null) { - cpe += ":" + num; + cpe += ':' + num; } if (edition != null) { - cpe += ":" + edition; + cpe += ':' + edition; } final VulnerableSoftware vs = new VulnerableSoftware(); vs.setCpe(cpe); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Dependency.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Dependency.java index 85588f093..457bb4cb3 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Dependency.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Dependency.java @@ -341,7 +341,7 @@ public class Dependency implements Serializable, Comparable { } } if (!found) { - LOGGER.debug("Adding new maven identifier {}", mavenArtifact.toString()); + LOGGER.debug("Adding new maven identifier {}", mavenArtifact); this.addIdentifier("maven", mavenArtifact.toString(), mavenArtifact.getArtifactUrl(), Confidence.HIGHEST); } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionRule.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionRule.java index 6d91b02a1..26287e655 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionRule.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionRule.java @@ -20,6 +20,7 @@ package org.owasp.dependencycheck.suppression; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import org.apache.commons.lang3.StringUtils; import org.owasp.dependencycheck.dependency.Dependency; import org.owasp.dependencycheck.dependency.Identifier; import org.owasp.dependencycheck.dependency.Vulnerability; @@ -381,30 +382,7 @@ public class SuppressionRule { * @return true if the property type does not specify a version; otherwise false */ boolean cpeHasNoVersion(PropertyType c) { - if (c.isRegex()) { - return false; - } - if (countCharacter(c.getValue(), ':') == 3) { - return true; - } - return false; - } - - /** - * Counts the number of occurrences of the character found within the string. - * - * @param str the string to check - * @param c the character to count - * @return the number of times the character is found in the string - */ - int countCharacter(String str, char c) { - int count = 0; - int pos = str.indexOf(c) + 1; - while (pos > 0) { - count += 1; - pos = str.indexOf(c, pos) + 1; - } - return count; + return !c.isRegex() && StringUtils.countMatches(c.getValue(), ':') == 3; } /** @@ -442,43 +420,43 @@ public class SuppressionRule { final StringBuilder sb = new StringBuilder(); sb.append("SuppressionRule{"); if (filePath != null) { - sb.append("filePath=").append(filePath).append(","); + sb.append("filePath=").append(filePath).append(','); } if (sha1 != null) { - sb.append("sha1=").append(sha1).append(","); + sb.append("sha1=").append(sha1).append(','); } if (gav != null) { - sb.append("gav=").append(gav).append(","); + sb.append("gav=").append(gav).append(','); } if (cpe != null && !cpe.isEmpty()) { sb.append("cpe={"); for (PropertyType pt : cpe) { - sb.append(pt).append(","); + sb.append(pt).append(','); } - sb.append("}"); + sb.append('}'); } if (cwe != null && !cwe.isEmpty()) { sb.append("cwe={"); for (String s : cwe) { - sb.append(s).append(","); + sb.append(s).append(','); } - sb.append("}"); + sb.append('}'); } if (cve != null && !cve.isEmpty()) { sb.append("cve={"); for (String s : cve) { - sb.append(s).append(","); + sb.append(s).append(','); } - sb.append("}"); + sb.append('}'); } if (cvssBelow != null && !cvssBelow.isEmpty()) { sb.append("cvssBelow={"); for (Float s : cvssBelow) { - sb.append(s).append(","); + sb.append(s).append(','); } - sb.append("}"); + sb.append('}'); } - sb.append("}"); + sb.append('}'); return sb.toString(); } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DateUtil.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DateUtil.java index 9fbd33a4c..782b32379 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DateUtil.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DateUtil.java @@ -36,11 +36,12 @@ public final class DateUtil { * * @param date the date to be checked. * @param compareTo the date to compare to. - * @param range the range in days to be considered valid. + * @param dayRange the range in days to be considered valid. * @return whether or not the date is within the range. */ - public static boolean withinDateRange(long date, long compareTo, int range) { - final double differenceInDays = (compareTo - date) / 1000.0 / 60.0 / 60.0 / 24.0; - return differenceInDays < range; + public static boolean withinDateRange(long date, long compareTo, int dayRange) { + // ms = dayRange x 24 hours/day x 60 min/hour x 60 sec/min x 1000 ms/sec + final long msRange = dayRange * 24L * 60L * 60L * 1000L; + return (compareTo - date) < msRange; } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DependencyVersion.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DependencyVersion.java index 83df787f5..df2d9afe8 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DependencyVersion.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DependencyVersion.java @@ -115,7 +115,7 @@ public class DependencyVersion implements Iterable, Comparable.*\bhk2\b.* cpe:/a:oracle:glassfish + + + org.ow2.petals:petals-se-camel:.* + cpe:/a:apache:camel + + + + org.apache.mina:mina.* + cpe:/a:apache-ssl:apache-ssl + + + + org.apache.woden:woden.* + cpe:/a:apache-ssl:apache-ssl + + + + org.apache.geronimo.specs:.* + cpe:/a:apache:geronimo + \ No newline at end of file diff --git a/dependency-check-core/src/main/resources/dependencycheck.properties b/dependency-check-core/src/main/resources/dependencycheck.properties index 9a45d8f3f..15179b12f 100644 --- a/dependency-check-core/src/main/resources/dependencycheck.properties +++ b/dependency-check-core/src/main/resources/dependencycheck.properties @@ -18,8 +18,8 @@ engine.version.url=http://jeremylong.github.io/DependencyCheck/current.txt data.directory=[JAR]/data #if the filename has a %s it will be replaced with the current expected version data.file_name=dc.h2.db -data.version=2.9 -data.connection_string=jdbc:h2:file:%s;FILE_LOCK=SERIALIZED;AUTOCOMMIT=ON; +data.version=3.0 +data.connection_string=jdbc:h2:file:%s;FILE_LOCK=FS;AUTOCOMMIT=ON; #data.connection_string=jdbc:mysql://localhost:3306/dependencycheck # user name and password for the database connection. The inherent case is to use H2. @@ -41,13 +41,15 @@ data.driver_path= # to update the other files if we are within this timespan. Per NIST this file # holds 8 days of updates, we are using 7 just to be safe. cve.url.modified.validfordays=7 - +# the number of hours to wait before checking if updates are available from the NVD. +cve.check.validforhours=4 +#first year to pull data from the URLs below +cve.startyear=2002 # the path to the modified nvd cve xml file. cve.url-1.2.modified=https://nvd.nist.gov/download/nvdcve-Modified.xml.gz #cve.url-1.2.modified=http://nvd.nist.gov/download/nvdcve-modified.xml cve.url-2.0.modified=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-Modified.xml.gz #cve.url-2.0.modified=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml -cve.startyear=2002 cve.url-1.2.base=https://nvd.nist.gov/download/nvdcve-%d.xml.gz #cve.url-1.2.base=http://nvd.nist.gov/download/nvdcve-%d.xml cve.url-2.0.base=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz @@ -79,3 +81,22 @@ archive.scan.depth=3 # use HEAD (default) or GET as HTTP request method for query timestamp downloader.quick.query.timestamp=true + + +analyzer.jar.enabled=true +analyzer.archive.enabled=true +analyzer.node.package.enabled=true +analyzer.composer.lock.enabled=true +analyzer.python.distribution.enabled=true +analyzer.python.package.enabled=true +analyzer.ruby.gemspec.enabled=true +analyzer.autoconf.enabled=true +analyzer.cmake.enabled=true +analyzer.assembly.enabled=true +analyzer.nuspec.enabled=true +analyzer.openssl.enabled=true +analyzer.central.enabled=true +analyzer.nexus.enabled=false +#whether the nexus analyzer uses the proxy +analyzer.nexus.proxy=true + diff --git a/dependency-check-core/src/main/resources/templates/HtmlReport.vsl b/dependency-check-core/src/main/resources/templates/HtmlReport.vsl index 35f673c9e..be8b487be 100644 --- a/dependency-check-core/src/main/resources/templates/HtmlReport.vsl +++ b/dependency-check-core/src/main/resources/templates/HtmlReport.vsl @@ -578,6 +578,7 @@ arising out of or in connection with the use of this tool, the analysis performe #set($sortValue="") #foreach($id in $dependency.getIdentifiers()) + #set($cpeSort=0) #if ($id.type=="maven") #if ($mavenlink=="" || !$mavenlink.url) #set($mavenlink=$id) @@ -591,7 +592,6 @@ arising out of or in connection with the use of this tool, the analysis performe #else $enc.html($id.value) #end - #set($cpeSort=0) #if ($cpeIdConf == "") #set($cpeIdConf=$id.confidence) #set($cpeSort=$id.confidence.ordinal()) diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/BaseDBTestCase.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/BaseDBTestCase.java similarity index 96% rename from dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/BaseDBTestCase.java rename to dependency-check-core/src/test/java/org/owasp/dependencycheck/BaseDBTestCase.java index 652dc6e60..399b00703 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/BaseDBTestCase.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/BaseDBTestCase.java @@ -15,7 +15,7 @@ * * Copyright (c) 2012 Jeremy Long. All Rights Reserved. */ -package org.owasp.dependencycheck.data.nvdcve; +package org.owasp.dependencycheck; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -31,6 +31,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** + * An abstract database test case that is used to ensure the H2 DB exists prior to performing tests that utilize the data + * contained within. * * @author Jeremy Long */ diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIntegrationTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIntegrationTest.java index 68ed51f3d..e3fd59c9e 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIntegrationTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIntegrationTest.java @@ -34,7 +34,7 @@ public class EngineIntegrationTest extends BaseTest { @Before public void setUp() throws Exception { - org.owasp.dependencycheck.data.nvdcve.BaseDBTestCase.ensureDBExists(); + org.owasp.dependencycheck.BaseDBTestCase.ensureDBExists(); } @After diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzerTest.java index f456707a8..37c0de5ac 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzerTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzerTest.java @@ -34,7 +34,7 @@ public class AbstractFileTypeAnalyzerTest extends BaseTest { */ @Test public void testNewHashSet() { - Set result = AbstractFileTypeAnalyzer.newHashSet("one", "two"); + Set result = AbstractFileTypeAnalyzer.newHashSet("one", "two"); assertEquals(2, result.size()); assertTrue(result.contains("one")); assertTrue(result.contains("two")); diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerIntegrationTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerIntegrationTest.java index 7a5bf74bf..179d06a58 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerIntegrationTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerIntegrationTest.java @@ -24,7 +24,7 @@ import static org.junit.Assert.*; import org.junit.Test; import org.owasp.dependencycheck.BaseTest; import org.owasp.dependencycheck.Engine; -import org.owasp.dependencycheck.data.cpe.AbstractDatabaseTestCase; +import org.owasp.dependencycheck.BaseDBTestCase; import org.owasp.dependencycheck.dependency.Dependency; import org.owasp.dependencycheck.utils.Settings; @@ -32,7 +32,7 @@ import org.owasp.dependencycheck.utils.Settings; * * @author Jeremy Long */ -public class ArchiveAnalyzerIntegrationTest extends AbstractDatabaseTestCase { +public class ArchiveAnalyzerIntegrationTest extends BaseDBTestCase { /** * Test of getSupportedExtensions method, of class ArchiveAnalyzer. diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerTest.java new file mode 100644 index 000000000..2eb953fe5 --- /dev/null +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerTest.java @@ -0,0 +1,80 @@ +/* + * Copyright 2015 OWASP. + * + * 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. + */ +package org.owasp.dependencycheck.analyzer; + +import java.io.File; +import java.io.FileFilter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; +import static org.junit.Assume.assumeFalse; +import static org.junit.Assume.assumeNotNull; +import org.owasp.dependencycheck.BaseTest; +import org.owasp.dependencycheck.Engine; +import org.owasp.dependencycheck.dependency.Dependency; +import org.owasp.dependencycheck.utils.Settings; + +/** + * + * @author jeremy + */ +public class ArchiveAnalyzerTest extends BaseTest { + + @Before + public void setUp() { + Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, "z2, z3"); + } + + /** + * Test of analyzeFileType method, of class ArchiveAnalyzer. + */ + @Test + public void testZippableExtensions() throws Exception { + assumeFalse(isPreviouslyLoaded("org.owasp.dependencycheck.analyzer.ArchiveAnalyzer")); + ArchiveAnalyzer instance = new ArchiveAnalyzer(); + assertTrue(instance.getFileFilter().accept(new File("c:/test.zip"))); + assertTrue(instance.getFileFilter().accept(new File("c:/test.z2"))); + assertTrue(instance.getFileFilter().accept(new File("c:/test.z3"))); + assertFalse(instance.getFileFilter().accept(new File("c:/test.z4"))); + } + + private boolean isPreviouslyLoaded(String className) { + try { + Method m = ClassLoader.class.getDeclaredMethod("findLoadedClass", new Class[]{String.class}); + m.setAccessible(true); + Object t = m.invoke(Thread.currentThread().getContextClassLoader(), className); + return t != null; + } catch (NoSuchMethodException ex) { + Logger.getLogger(ArchiveAnalyzerTest.class.getName()).log(Level.SEVERE, null, ex); + } catch (SecurityException ex) { + Logger.getLogger(ArchiveAnalyzerTest.class.getName()).log(Level.SEVERE, null, ex); + } catch (IllegalAccessException ex) { + Logger.getLogger(ArchiveAnalyzerTest.class.getName()).log(Level.SEVERE, null, ex); + } catch (IllegalArgumentException ex) { + Logger.getLogger(ArchiveAnalyzerTest.class.getName()).log(Level.SEVERE, null, ex); + } catch (InvocationTargetException ex) { + Logger.getLogger(ArchiveAnalyzerTest.class.getName()).log(Level.SEVERE, null, ex); + } + return false; + } +} diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzerTest.java index fcde64fdf..f985e413a 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzerTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzerTest.java @@ -33,7 +33,7 @@ import java.util.regex.Pattern; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.*; -import org.owasp.dependencycheck.data.nvdcve.BaseDBTestCase; +import org.owasp.dependencycheck.BaseDBTestCase; /** * Unit tests for CmakeAnalyzer. diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/CPEAnalyzerIntegrationTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/CPEAnalyzerIntegrationTest.java index 6e272206e..36c6e7478 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/CPEAnalyzerIntegrationTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/CPEAnalyzerIntegrationTest.java @@ -19,7 +19,7 @@ package org.owasp.dependencycheck.analyzer; import java.io.File; import java.io.IOException; -import java.util.HashSet; +import java.util.Collections; import java.util.List; import java.util.Set; import org.apache.lucene.index.CorruptIndexException; @@ -28,7 +28,7 @@ import org.junit.Assert; import static org.junit.Assert.assertTrue; import org.junit.Test; import org.owasp.dependencycheck.BaseTest; -import org.owasp.dependencycheck.data.cpe.AbstractDatabaseTestCase; +import org.owasp.dependencycheck.BaseDBTestCase; import org.owasp.dependencycheck.data.cpe.IndexEntry; import org.owasp.dependencycheck.dependency.Confidence; import org.owasp.dependencycheck.dependency.Dependency; @@ -38,7 +38,7 @@ import org.owasp.dependencycheck.dependency.Identifier; * * @author Jeremy Long */ -public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase { +public class CPEAnalyzerIntegrationTest extends BaseDBTestCase { /** * Tests of buildSearch of class CPEAnalyzer. @@ -49,11 +49,9 @@ public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase { */ @Test public void testBuildSearch() throws IOException, CorruptIndexException, ParseException { - Set productWeightings = new HashSet(1); - productWeightings.add("struts2"); + Set productWeightings = Collections.singleton("struts2"); - Set vendorWeightings = new HashSet(1); - vendorWeightings.add("apache"); + Set vendorWeightings = Collections.singleton("apache"); String vendor = "apache software foundation"; String product = "struts 2 core"; @@ -238,11 +236,9 @@ public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase { CPEAnalyzer instance = new CPEAnalyzer(); instance.open(); - Set productWeightings = new HashSet(1); - productWeightings.add("struts2"); + Set productWeightings = Collections.singleton("struts2"); - Set vendorWeightings = new HashSet(1); - vendorWeightings.add("apache"); + Set vendorWeightings = Collections.singleton("apache"); List result = instance.searchCPE(vendor, product, productWeightings, vendorWeightings); instance.close(); diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzerIntegrationTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzerIntegrationTest.java index 8ee12448f..69e93e458 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzerIntegrationTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzerIntegrationTest.java @@ -18,13 +18,13 @@ package org.owasp.dependencycheck.analyzer; import org.junit.Test; -import org.owasp.dependencycheck.data.cpe.AbstractDatabaseTestCase; +import org.owasp.dependencycheck.BaseDBTestCase; /** * * @author Jeremy Long */ -public class DependencyBundlingAnalyzerIntegrationTest extends AbstractDatabaseTestCase { +public class DependencyBundlingAnalyzerIntegrationTest extends BaseDBTestCase { /** * Test of analyze method, of class DependencyBundlingAnalyzer. diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/HintAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/HintAnalyzerTest.java index 1f518ab27..990f24a28 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/HintAnalyzerTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/HintAnalyzerTest.java @@ -24,6 +24,7 @@ import org.junit.Before; import org.junit.Test; import org.owasp.dependencycheck.BaseTest; import org.owasp.dependencycheck.Engine; +import org.owasp.dependencycheck.BaseDBTestCase; import org.owasp.dependencycheck.dependency.Confidence; import org.owasp.dependencycheck.dependency.Dependency; import org.owasp.dependencycheck.dependency.Evidence; @@ -33,12 +34,7 @@ import org.owasp.dependencycheck.utils.Settings; * * @author Jeremy Long */ -public class HintAnalyzerTest extends BaseTest { - - @Before - public void setUp() throws Exception { - org.owasp.dependencycheck.data.nvdcve.BaseDBTestCase.ensureDBExists(); - } +public class HintAnalyzerTest extends BaseDBTestCase { /** * Test of getName method, of class HintAnalyzer. diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzerIntegrationTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzerIntegrationTest.java index 1496a4a1c..172418c49 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzerIntegrationTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzerIntegrationTest.java @@ -21,9 +21,9 @@ import java.io.File; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import org.junit.Test; +import org.owasp.dependencycheck.BaseDBTestCase; import org.owasp.dependencycheck.BaseTest; import org.owasp.dependencycheck.Engine; -import org.owasp.dependencycheck.data.cpe.AbstractDatabaseTestCase; import org.owasp.dependencycheck.dependency.Dependency; import org.owasp.dependencycheck.utils.Settings; @@ -32,7 +32,7 @@ import org.owasp.dependencycheck.utils.Settings; * * @author Jeremy Long */ -public class VulnerabilitySuppressionAnalyzerIntegrationTest extends AbstractDatabaseTestCase { +public class VulnerabilitySuppressionAnalyzerIntegrationTest extends BaseDBTestCase { /** * Test of getName method, of class VulnerabilitySuppressionAnalyzer. diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/cpe/AbstractDatabaseTestCase.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/cpe/AbstractDatabaseTestCase.java deleted file mode 100644 index a2a328964..000000000 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/cpe/AbstractDatabaseTestCase.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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) 2012 Jeremy Long. All Rights Reserved. - */ -package org.owasp.dependencycheck.data.cpe; - -import org.junit.Before; -import org.owasp.dependencycheck.BaseTest; -import org.owasp.dependencycheck.data.nvdcve.BaseDBTestCase; - -/** - * An abstract database test case that is used to ensure the H2 DB exists prior to performing tests that utilize the - * data contained within. - * - * @author Jeremy Long - */ -public abstract class AbstractDatabaseTestCase extends BaseTest { - - @Before - public void setUp() throws Exception { - BaseDBTestCase.ensureDBExists(); - } - -} diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/ConnectionFactoryTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/ConnectionFactoryTest.java new file mode 100644 index 000000000..060b31bf2 --- /dev/null +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/ConnectionFactoryTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2015 OWASP. + * + * 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. + */ +package org.owasp.dependencycheck.data.nvdcve; + +import java.sql.Connection; +import java.sql.SQLException; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; +import org.owasp.dependencycheck.BaseDBTestCase; + +/** + * + * @author jeremy + */ +public class ConnectionFactoryTest extends BaseDBTestCase { + + /** + * Test of initialize method, of class ConnectionFactory. + * + * @throws org.owasp.dependencycheck.data.nvdcve.DatabaseException + */ + @Test + public void testInitialize() throws DatabaseException, SQLException { + ConnectionFactory.initialize(); + Connection result = ConnectionFactory.getConnection(); + assertNotNull(result); + result.close(); + ConnectionFactory.cleanup(); + } +} diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/CveDBIntegrationTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/CveDBIntegrationTest.java index 72c3047c3..319136850 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/CveDBIntegrationTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/CveDBIntegrationTest.java @@ -17,6 +17,7 @@ */ package org.owasp.dependencycheck.data.nvdcve; +import org.owasp.dependencycheck.BaseDBTestCase; import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/CveDBMySQLTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/CveDBMySQLTest.java index bed456159..ba1fcba0d 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/CveDBMySQLTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/CveDBMySQLTest.java @@ -25,7 +25,9 @@ import static org.junit.Assert.assertTrue; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.owasp.dependencycheck.dependency.Vulnerability; import org.owasp.dependencycheck.dependency.VulnerableSoftware; +import org.owasp.dependencycheck.utils.Settings; /** * @@ -35,10 +37,12 @@ public class CveDBMySQLTest { @BeforeClass public static void setUpClass() { + Settings.initialize(); } @AfterClass public static void tearDownClass() { + Settings.cleanup(); } @Before @@ -93,7 +97,7 @@ public class CveDBMySQLTest { CveDB instance = new CveDB(); try { instance.open(); - List result = instance.getVulnerabilities(cpeStr); + List result = instance.getVulnerabilities(cpeStr); assertTrue(result.size() > 5); } catch (Exception ex) { System.out.println("Unable to access the My SQL database; verify that the db server is running and that the schema has been generated"); diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/DatabasePropertiesIntegrationTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/DatabasePropertiesIntegrationTest.java index 04e66f086..f505af9c9 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/DatabasePropertiesIntegrationTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/DatabasePropertiesIntegrationTest.java @@ -17,6 +17,7 @@ */ package org.owasp.dependencycheck.data.nvdcve; +import org.owasp.dependencycheck.BaseDBTestCase; import java.util.Properties; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/update/BaseUpdaterTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/update/BaseUpdaterTest.java index 1a64959f7..1fffea9c5 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/update/BaseUpdaterTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/update/BaseUpdaterTest.java @@ -18,7 +18,7 @@ package org.owasp.dependencycheck.data.update; import org.junit.Test; -import org.owasp.dependencycheck.data.nvdcve.BaseDBTestCase; +import org.owasp.dependencycheck.BaseDBTestCase; import org.owasp.dependencycheck.data.nvdcve.CveDB; import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties; import org.owasp.dependencycheck.data.update.exception.UpdateException; diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/dependency/DependencyTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/dependency/DependencyTest.java index 25210e9a7..cbccb2083 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/dependency/DependencyTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/dependency/DependencyTest.java @@ -185,7 +185,6 @@ public class DependencyTest { @Test public void testGetIdentifiers() { Dependency instance = new Dependency(); - List expResult = null; Set result = instance.getIdentifiers(); assertTrue(true); //this is just a getter setter pair. diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/reporting/ReportGeneratorIntegrationTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/reporting/ReportGeneratorIntegrationTest.java index 28dace177..6f5230ced 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/reporting/ReportGeneratorIntegrationTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/reporting/ReportGeneratorIntegrationTest.java @@ -40,7 +40,7 @@ public class ReportGeneratorIntegrationTest extends BaseTest { @Before public void setUp() throws Exception { - org.owasp.dependencycheck.data.nvdcve.BaseDBTestCase.ensureDBExists(); + org.owasp.dependencycheck.BaseDBTestCase.ensureDBExists(); } /** diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/SuppressionParserTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/SuppressionParserTest.java index 09570551b..dc0563e96 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/SuppressionParserTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/SuppressionParserTest.java @@ -61,7 +61,7 @@ public class SuppressionParserTest { //File file = new File(this.getClass().getClassLoader().getResource("suppressions.xml").getPath()); File file = BaseTest.getResourceAsFile(this, "suppressions.xml"); SuppressionParser instance = new SuppressionParser(); - List result = instance.parseSuppressionRules(file); + List result = instance.parseSuppressionRules(file); assertTrue(result.size() > 3); } } diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/SuppressionRuleTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/SuppressionRuleTest.java index f6e874304..cdc5c538a 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/SuppressionRuleTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/SuppressionRuleTest.java @@ -306,27 +306,6 @@ public class SuppressionRuleTest { assertTrue(instance.cpeHasNoVersion(c)); } - /** - * Test of countCharacter method, of class SuppressionRule. - */ - @Test - public void testCountCharacter() { - String str = "cpe:/a:microsoft:.net_framework:4.5"; - char c = ':'; - SuppressionRule instance = new SuppressionRule(); - int expResult = 4; - int result = instance.countCharacter(str, c); - assertEquals(expResult, result); - str = "::"; - expResult = 2; - result = instance.countCharacter(str, c); - assertEquals(expResult, result); - str = "these are not the characters you are looking for"; - expResult = 0; - result = instance.countCharacter(str, c); - assertEquals(expResult, result); - } - /** * Test of identifierMatches method, of class SuppressionRule. */ diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/utils/DependencyVersionTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/utils/DependencyVersionTest.java index b303f552b..fae60cbc7 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/utils/DependencyVersionTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/utils/DependencyVersionTest.java @@ -61,11 +61,11 @@ public class DependencyVersionTest { @Test public void testIterator() { DependencyVersion instance = new DependencyVersion("1.2.3"); - Iterator result = instance.iterator(); + Iterator result = instance.iterator(); assertTrue(result.hasNext()); int count = 1; while (result.hasNext()) { - String v = (String) result.next(); + String v = result.next(); assertTrue(String.valueOf(count++).equals(v)); } } diff --git a/dependency-check-core/src/main/resources/composer.lock b/dependency-check-core/src/test/resources/composer.lock similarity index 100% rename from dependency-check-core/src/main/resources/composer.lock rename to dependency-check-core/src/test/resources/composer.lock diff --git a/dependency-check-core/src/test/resources/dependencycheck.properties b/dependency-check-core/src/test/resources/dependencycheck.properties index b7cdffb69..83b5430ca 100644 --- a/dependency-check-core/src/test/resources/dependencycheck.properties +++ b/dependency-check-core/src/test/resources/dependencycheck.properties @@ -16,11 +16,9 @@ engine.version.url=http://jeremylong.github.io/DependencyCheck/current.txt # will not be used. The data.directory will be resolved and if the connection string # below contains a %s then the data.directory will replace the %s. data.directory=[JAR]/data -# if the filename has a %s it will be replaced with the current expected version. For file -# based databases the below filename will be added to the data directory above and then -# if the connection string has a %s it will be replaced by the directory/filename path. +#if the filename has a %s it will be replaced with the current expected version data.file_name=dc.h2.db -data.version=2.9 +data.version=3.0 data.connection_string=jdbc:h2:file:%s;FILE_LOCK=SERIALIZED;AUTOCOMMIT=ON; #data.connection_string=jdbc:mysql://localhost:3306/dependencycheck @@ -39,19 +37,15 @@ data.password=DC-Pass1337! data.driver_name=org.h2.Driver data.driver_path= -# the path to the cpe xml file -#cpe.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.2.xml.gz -cpe.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.3.xml.gz -# the path to the cpe meta data file. -cpe.meta.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.2.meta - # the number of days that the modified nvd cve data holds data for. We don't need # to update the other files if we are within this timespan. Per NIST this file # holds 8 days of updates, we are using 7 just to be safe. cve.url.modified.validfordays=7 - -# the path to the modified nvd cve xml file. +# the number of hours to wait before checking if updates are available from the NVD. +cve.check.validforhours=0 +#first year to pull data from the URLs below cve.startyear=2014 +# the path to the modified nvd cve xml file. cve.url-1.2.modified=https://nvd.nist.gov/download/nvdcve-Modified.xml.gz #cve.url-1.2.modified=http://nvd.nist.gov/download/nvdcve-modified.xml cve.url-2.0.modified=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-Modified.xml.gz @@ -62,6 +56,14 @@ cve.url-2.0.base=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz #cve.url-2.0.base=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml 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 @@ -74,5 +76,27 @@ analyzer.nexus.proxy=true analyzer.central.enabled=true analyzer.central.url=http://search.maven.org/solrsearch/select +# the number of nested archives that will be searched. +archive.scan.depth=3 + # use HEAD (default) or GET as HTTP request method for query timestamp downloader.quick.query.timestamp=true + + +analyzer.jar.enabled=true +analyzer.archive.enabled=true +analyzer.node.package.enabled=true +analyzer.composer.lock.enabled=true +analyzer.python.distribution.enabled=true +analyzer.python.package.enabled=true +analyzer.ruby.gemspec.enabled=true +analyzer.autoconf.enabled=true +analyzer.cmake.enabled=true +analyzer.assembly.enabled=true +analyzer.nuspec.enabled=true +analyzer.openssl.enabled=true +analyzer.central.enabled=true +analyzer.nexus.enabled=false +#whether the nexus analyzer uses the proxy +analyzer.nexus.proxy=true + diff --git a/dependency-check-gradle/README.md b/dependency-check-gradle/README.md index a1d37491e..b06d653c7 100644 --- a/dependency-check-gradle/README.md +++ b/dependency-check-gradle/README.md @@ -1,11 +1,8 @@ Dependency-Check-Gradle ========= -**Working in progress** - -This is a DependencyCheck gradle plugin designed for project which use Gradle as build script. - -Dependency-Check is a utility that attempts to detect publicly disclosed vulnerabilities contained within project dependencies. It does this by determining if there is a Common Platform Enumeration (CPE) identifier for a given dependency. If found, it will generate a report linking to the associated CVE entries. +The dependency-check gradle plugin allows projects to monitor dependent libraries for +known, published vulnerabilities. ========= @@ -24,11 +21,11 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.thoughtworks.tools:dependency-check:0.0.8' + classpath 'org.owasp:dependency-check-gradle:1.3.2' } } -apply plugin: 'dependency-check' +apply plugin: 'dependency-check-gradle' ``` ### Step 2, Run gradle task @@ -59,10 +56,10 @@ dependencyCheck { proxy { server = "127.0.0.1" // required, the server name or IP address of the proxy port = 3128 // required, the port number of the proxy - + // optional, the proxy server might require username // username = "username" - + // optional, the proxy server might require password // password = "password" } diff --git a/dependency-check-gradle/build.gradle b/dependency-check-gradle/build.gradle index 1bf6714bc..09c700fbd 100644 --- a/dependency-check-gradle/build.gradle +++ b/dependency-check-gradle/build.gradle @@ -16,6 +16,10 @@ * Copyright (c) 2015 Wei Ma. All Rights Reserved. */ + +group = 'org.owasp' +version = '1.3.2-SNAPSHOT' + buildscript { repositories { maven { @@ -43,14 +47,15 @@ targetCompatibility = 1.6 repositories { mavenCentral() + mavenLocal() } dependencies { compile( localGroovy(), gradleApi(), - 'org.owasp:dependency-check-core:1.3.1', - 'org.owasp:dependency-check-utils:1.3.1' + 'org.owasp:dependency-check-core:1.3.2-SNAPSHOT', + 'org.owasp:dependency-check-utils:1.3.2-SNAPSHOT' ) testCompile ('com.netflix.nebula:nebula-test:2.2.2'){ @@ -75,11 +80,6 @@ task integTest(type: Test) { jvmArgs '-XX:MaxPermSize=256m' } -group = 'com.thoughtworks.tools' -version = '0.0.8' - -targetCompatibility = 1.7 - apply from: 'conf/publish/local.gradle' //apply from: 'conf/publish/maven.gradle' //apply from: 'conf/publish/gradlePluginsPortal.gradle' diff --git a/dependency-check-gradle/conf/publish/maven.gradle b/dependency-check-gradle/conf/publish/maven.gradle index 462ced0f7..0cb9faf65 100644 --- a/dependency-check-gradle/conf/publish/maven.gradle +++ b/dependency-check-gradle/conf/publish/maven.gradle @@ -50,6 +50,11 @@ uploadArchives { } developers { + developer { + id 'jeremylong' + name 'Jeremy Long' + email 'jeremy.long@owasp.org' + } developer { id 'wmaintw' name 'Wei Ma' diff --git a/dependency-check-gradle/pom.xml b/dependency-check-gradle/pom.xml index 17b65e0a7..401196cba 100644 --- a/dependency-check-gradle/pom.xml +++ b/dependency-check-gradle/pom.xml @@ -22,11 +22,11 @@ Copyright (c) 2015 Wei Ma. All Rights Reserved. org.owasp dependency-check-parent - 1.3.1 + 1.3.2-SNAPSHOT dependency-check-gradle - 0.0.6 + 0.0.8 pom diff --git a/dependency-check-gradle/settings.gradle b/dependency-check-gradle/settings.gradle index b460ef63c..522f2e666 100644 --- a/dependency-check-gradle/settings.gradle +++ b/dependency-check-gradle/settings.gradle @@ -16,4 +16,4 @@ * Copyright (c) 2015 Wei Ma. All Rights Reserved. */ -rootProject.name = 'dependency-check' \ No newline at end of file +rootProject.name = 'dependency-check-gradle' \ No newline at end of file diff --git a/dependency-check-gradle/src/integTest/groovy/com/tools/security/plugin/DependencyCheckGradlePluginIntegSpec.groovy b/dependency-check-gradle/src/integTest/groovy/com/tools/security/plugin/DependencyCheckGradlePluginIntegSpec.groovy index 895571d3c..3e89f88e2 100644 --- a/dependency-check-gradle/src/integTest/groovy/com/tools/security/plugin/DependencyCheckGradlePluginIntegSpec.groovy +++ b/dependency-check-gradle/src/integTest/groovy/com/tools/security/plugin/DependencyCheckGradlePluginIntegSpec.groovy @@ -10,7 +10,7 @@ class DependencyCheckGradlePluginIntegSpec extends IntegrationSpec { def "I can add the plugin to a build with no errors"() { setup: buildFile << ''' - apply plugin: 'dependency-check' + apply plugin: 'dependencyCheck' '''.stripIndent() when: diff --git a/dependency-check-gradle/src/integTest/resources/outputDir.gradle b/dependency-check-gradle/src/integTest/resources/outputDir.gradle index 8212eeed6..e2f104e73 100644 --- a/dependency-check-gradle/src/integTest/resources/outputDir.gradle +++ b/dependency-check-gradle/src/integTest/resources/outputDir.gradle @@ -3,7 +3,7 @@ * @author Sion Williams */ apply plugin: 'java' -apply plugin: 'dependency-check' +apply plugin: 'dependencyCheck' sourceCompatibility = 1.5 version = '1.0' @@ -17,5 +17,5 @@ dependencies { } dependencyCheck { - outputDirectory = "${buildDir}/dependencyCheckReport" + reportsDirName = "reports" } \ No newline at end of file diff --git a/dependency-check-gradle/src/main/groovy/com/tools/security/extension/AnalyzerExtension.groovy b/dependency-check-gradle/src/main/groovy/com/tools/security/extension/AnalyzerExtension.groovy new file mode 100644 index 000000000..64953e7ae --- /dev/null +++ b/dependency-check-gradle/src/main/groovy/com/tools/security/extension/AnalyzerExtension.groovy @@ -0,0 +1,100 @@ +/* + * This file is part of dependency-check-gradle. + * + * 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) 2015 Jeremy Long. All Rights Reserved. + */ + +package com.tools.security.extension + +/** + * The analyzer configuration extension. Any value not configured will use the dependency-check-core defaults. + */ +class AnalyzerExtension { + + /** + * Sets whether the Archive Analyzer will be used. + */ + Boolean archiveEnabled + /** + * A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. + */ + String zipExtensions + /** + * Sets whether Jar Analyzer will be used. + */ + Boolean jarEnabled + /** + * Sets whether Central Analyzer will be used. If this analyzer is being disabled there is a good chance you also want to disable the Nexus Analyzer (see below). + */ + Boolean centralEnabled + /** + * Sets whether Nexus Analyzer will be used. This analyzer is superceded by the Central Analyzer; however, you can configure this to run against a Nexus Pro installation. + */ + Boolean nexusEnabled + /** + * Defines the Nexus Server's web service end point (example http://domain.enterprise/service/local/). If not set the Nexus Analyzer will be disabled. + */ + String nexusUrl + /** + * Whether or not the defined proxy should be used when connecting to Nexus. + */ + Boolean nexusUsesProxy + /** + * Sets whether or not the .NET Nuget Nuspec Analyzer will be used. + */ + Boolean nuspecEnabled + /** + * Sets whether or not the .NET Assembly Analyzer should be used. + */ + Boolean assemblyEnabled + /** + * The path to Mono for .NET assembly analysis on non-windows systems. + */ + String pathToMono + + + /** + * Sets whether the Python Distribution Analyzer will be used. + */ + Boolean pyDistributionEnabled + /** + * Sets whether the Python Package Analyzer will be used. + */ + Boolean pyPackageEnabled + /** + * Sets whether the Ruby Gemspec Analyzer will be used. + */ + Boolean rubygemsEnabled + /** + * Sets whether or not the openssl Analyzer should be used. + */ + Boolean opensslEnabled + /** + * Sets whether or not the CMake Analyzer should be used. + */ + Boolean cmakeEnabled + /** + * Sets whether or not the autoconf Analyzer should be used. + */ + Boolean autoconfEnabled + /** + * Sets whether or not the PHP Composer Lock File Analyzer should be used. + */ + Boolean composerEnabled + /** + * Sets whether or not the Node.js Analyzer should be used. + */ + Boolean nodeEnabled +} diff --git a/dependency-check-gradle/src/main/groovy/com/tools/security/extension/CheckExtension.groovy b/dependency-check-gradle/src/main/groovy/com/tools/security/extension/CheckExtension.groovy new file mode 100644 index 000000000..8c1647666 --- /dev/null +++ b/dependency-check-gradle/src/main/groovy/com/tools/security/extension/CheckExtension.groovy @@ -0,0 +1,70 @@ +/* + * This file is part of dependency-check-gradle. + * + * 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) 2015 Wei Ma. All Rights Reserved. + */ + +package com.tools.security.extension + +import static org.owasp.dependencycheck.reporting.ReportGenerator.Format + +/* + * Configuration extension for the dependencyCheck plugin. + * + * @author Wei Ma + * @author Jeremy Long + */ +class CheckExtension extends UpdateExtension { + /** + * Configuration for the analyzers. + */ + AnalyzerExtension analyzerExtension + + /** + * The path to the suppression file. + */ + String suppressionFile + /** + * Sets whether auto-updating of the NVD CVE/CPE data is enabled. + */ + Boolean autoUpdate + + //The following properties are not used via the settings object, instead + // they are directly used by the check task. + /** + * When set to true dependency groups that start with 'test' will not be included in the analysis. + * The default value is true. + */ + Boolean skipTestGroups = true + /** + * The report format to be generated (HTML, XML, VULN, ALL). This configuration option has + * no affect if using this within the Site plugin unless the externalReport is set to true. + * The default is HTML. + */ + Format format = Format.HTML + /** + * The name of the directory where reports will be written. Defaults to 'reports'. + */ + String reportsDirName = "reports" + /** + * 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. + */ + Float failBuildOnCVSS = 11.0 + /** + * Displays a summary of the findings. Defaults to true. + */ + Boolean showSummary = true +} diff --git a/dependency-check-gradle/src/main/groovy/com/tools/security/extension/CveExtension.groovy b/dependency-check-gradle/src/main/groovy/com/tools/security/extension/CveExtension.groovy index a91eee97f..857b63bce 100644 --- a/dependency-check-gradle/src/main/groovy/com/tools/security/extension/CveExtension.groovy +++ b/dependency-check-gradle/src/main/groovy/com/tools/security/extension/CveExtension.groovy @@ -18,10 +18,25 @@ package com.tools.security.extension -class CveExtension { +public class CveExtension { + /** + * URL for the modified CVE 1.2: + * https://nvd.nist.gov/download/nvdcve-Modified.xml.gz + **/ String url20Modified + /** + * URL for the modified CVE 1.2: + * https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-Modified.xml.gz + **/ String url12Modified - Integer startYear + /** + * URL for the modified CVE 1.2: + * https://nvd.nist.gov/download/nvdcve-%d.xml.gz + **/ String url20Base + /** + * Base URL for each year's CVE 2.0, the %d will be replaced with the year. + * https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz + **/ String url12Base } diff --git a/dependency-check-gradle/src/main/groovy/com/tools/security/extension/DataExtension.groovy b/dependency-check-gradle/src/main/groovy/com/tools/security/extension/DataExtension.groovy new file mode 100644 index 000000000..c20c64632 --- /dev/null +++ b/dependency-check-gradle/src/main/groovy/com/tools/security/extension/DataExtension.groovy @@ -0,0 +1,45 @@ +/* + * This file is part of dependency-check-gradle. + * + * 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) 2015 Jeremy Long. All Rights Reserved. + */ + +package com.tools.security.extension + +/** + * The update data configuration extension. Any value not configured will use the dependency-check-core defaults. + */ +class DataExtension extends PurgeDataExtension { + /** + * The connection string to the database. + */ + String connectionString + /** + * The user name to use when connecting to the database. + */ + String username + /** + * The password to use when connecting to the database. + */ + String password + /** + * The database dirver name (e.g. org.h2.Driver). + */ + String driver + /** + * The path to the driver (JAR) in case it is not already in the classpath. + */ + String driverPath +} diff --git a/dependency-check-gradle/src/main/groovy/com/tools/security/extension/ProxyExtension.groovy b/dependency-check-gradle/src/main/groovy/com/tools/security/extension/ProxyExtension.groovy index 97763ad76..e7bd282ad 100644 --- a/dependency-check-gradle/src/main/groovy/com/tools/security/extension/ProxyExtension.groovy +++ b/dependency-check-gradle/src/main/groovy/com/tools/security/extension/ProxyExtension.groovy @@ -17,7 +17,10 @@ */ package com.tools.security.extension - +/** + * TODO - this should not be needed, instead rely on the configured HTTP or HTTPS proxies + * https://docs.gradle.org/current/userguide/build_environment.html + */ class ProxyExtension { String server Integer port diff --git a/dependency-check-gradle/src/main/groovy/com/tools/security/extension/PurgeDataExtension.groovy b/dependency-check-gradle/src/main/groovy/com/tools/security/extension/PurgeDataExtension.groovy new file mode 100644 index 000000000..92e996362 --- /dev/null +++ b/dependency-check-gradle/src/main/groovy/com/tools/security/extension/PurgeDataExtension.groovy @@ -0,0 +1,29 @@ +/* + * This file is part of dependency-check-gradle. + * + * 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) 2015 Jeremy Long. All Rights Reserved. + */ + +package com.tools.security.extension + +/** + * The data configuration extension. Any value not configured will use the dependency-check-core defaults. + */ +class PurgeDataExtension { + /** + * The directory to store the H2 database that contains the cache of the NVD CVE data. + */ + String directory="[JAR]/../../dependency-check-data" +} diff --git a/dependency-check-gradle/src/main/groovy/com/tools/security/extension/DependencyCheckExtension.groovy b/dependency-check-gradle/src/main/groovy/com/tools/security/extension/PurgeExtension.groovy similarity index 80% rename from dependency-check-gradle/src/main/groovy/com/tools/security/extension/DependencyCheckExtension.groovy rename to dependency-check-gradle/src/main/groovy/com/tools/security/extension/PurgeExtension.groovy index e38f63dee..27bd8c831 100644 --- a/dependency-check-gradle/src/main/groovy/com/tools/security/extension/DependencyCheckExtension.groovy +++ b/dependency-check-gradle/src/main/groovy/com/tools/security/extension/PurgeExtension.groovy @@ -18,10 +18,6 @@ package com.tools.security.extension -class DependencyCheckExtension { - ProxyExtension proxyExtension - CveExtension cveExtension - - String outputDirectory = "./reports" - Boolean quickQueryTimestamp; +class PurgeExtension { + PurgeDataExtension dataExtension } diff --git a/dependency-check-gradle/src/main/groovy/com/tools/security/extension/UpdateExtension.groovy b/dependency-check-gradle/src/main/groovy/com/tools/security/extension/UpdateExtension.groovy new file mode 100644 index 000000000..0bdb0b886 --- /dev/null +++ b/dependency-check-gradle/src/main/groovy/com/tools/security/extension/UpdateExtension.groovy @@ -0,0 +1,33 @@ +/* + * This file is part of dependency-check-gradle. + * + * 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) 2015 Wei Ma. All Rights Reserved. + */ + +package com.tools.security.extension + +class UpdateExtension extends PurgeExtension { + ProxyExtension proxyExtension + CveExtension cveExtension + DataExtension dataExtension + /** + * Set to false if the proxy does not support HEAD requests. The default is true. + */ + Boolean quickQueryTimestamp + /** + * The number of hours to wait before checking for additional updates from the NVD. + */ + Integer cveValidForHours +} diff --git a/dependency-check-gradle/src/main/groovy/com/tools/security/plugin/DependencyCheck.groovy b/dependency-check-gradle/src/main/groovy/com/tools/security/plugin/DependencyCheck.groovy new file mode 100644 index 000000000..55753c43b --- /dev/null +++ b/dependency-check-gradle/src/main/groovy/com/tools/security/plugin/DependencyCheck.groovy @@ -0,0 +1,75 @@ +/* + * This file is part of dependency-check-gradle. + * + * 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) 2015 Wei Ma. All Rights Reserved. + */ + +package com.tools.security.plugin + +import com.tools.security.extension.CveExtension +import com.tools.security.extension.CheckExtension +import com.tools.security.extension.ProxyExtension +import com.tools.security.extension.DataExtension +import com.tools.security.extension.AnalyzerExtension +import com.tools.security.extension.UpdateExtension +import com.tools.security.extension.PurgeExtension +import com.tools.security.extension.PurgeDataExtension +import com.tools.security.tasks.Check +import com.tools.security.tasks.Update +import com.tools.security.tasks.Purge + +import org.gradle.api.Plugin +import org.gradle.api.Project + +class DependencyCheck implements Plugin { + private static final String CHECK_TASK = 'dependencyCheck' + private static final String UPDATE_TASK = 'dependencyCheckUpdate' + private static final String PURGE_TASK = 'dependencyCheckPurge' + + + /* configuration extensions */ + private static final String PROXY_EXTENSION_NAME = "proxy" + private static final String CVE_EXTENSION_NAME = "cve" + private static final String DATA_EXTENSION_NAME = "data" + private static final String ANALYZER_EXTENSION_NAME = "analyzer" + + @Override + void apply(Project project) { + initializeConfigurations(project) + registerTasks(project) + } + + def initializeConfigurations(Project project) { + def ext = project.extensions.create(CHECK_TASK, CheckExtension) + ext.extensions.create(PROXY_EXTENSION_NAME, ProxyExtension) + ext.extensions.create(CVE_EXTENSION_NAME, CveExtension) + ext.extensions.create(DATA_EXTENSION_NAME, DataExtension) + ext.extensions.create(ANALYZER_EXTENSION_NAME, AnalyzerExtension) + + def extu = project.extensions.create(UPDATE_TASK, UpdateExtension) + extu.extensions.create(CVE_EXTENSION_NAME, CveExtension) + extu.extensions.create(DATA_EXTENSION_NAME, DataExtension) + extu.extensions.create(PROXY_EXTENSION_NAME, ProxyExtension) + + def extp = project.extensions.create(PURGE_TASK, PurgeExtension) + extp.extensions.create(DATA_EXTENSION_NAME, PurgeDataExtension) + } + + def registerTasks(Project project) { + project.task(CHECK_TASK, type: Check) + project.task(UPDATE_TASK, type: Update) + project.task(PURGE_TASK, type: Purge) + } +} diff --git a/dependency-check-gradle/src/main/groovy/com/tools/security/plugin/DependencyCheckGradlePlugin.groovy b/dependency-check-gradle/src/main/groovy/com/tools/security/plugin/DependencyCheckGradlePlugin.groovy deleted file mode 100644 index a1f94a13c..000000000 --- a/dependency-check-gradle/src/main/groovy/com/tools/security/plugin/DependencyCheckGradlePlugin.groovy +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is part of dependency-check-gradle. - * - * 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) 2015 Wei Ma. All Rights Reserved. - */ - -package com.tools.security.plugin - -import com.tools.security.extension.CveExtension -import com.tools.security.extension.DependencyCheckExtension -import com.tools.security.extension.ProxyExtension -import com.tools.security.tasks.DependencyCheckTask -import org.gradle.api.Plugin -import org.gradle.api.Project - -class DependencyCheckGradlePlugin implements Plugin { - private static final String ROOT_EXTENSION_NAME = 'dependencyCheck' - private static final String TASK_NAME = 'dependencyCheck' - private static final String PROXY_EXTENSION_NAME = "proxy" - private static final String CVE_EXTENSION_NAME = "cve" - - @Override - void apply(Project project) { - initializeConfigurations(project) - registerTasks(project) - } - - def initializeConfigurations(Project project) { - project.extensions.create(ROOT_EXTENSION_NAME, DependencyCheckExtension) - project.dependencyCheck.extensions.create(PROXY_EXTENSION_NAME, ProxyExtension) - project.dependencyCheck.extensions.create(CVE_EXTENSION_NAME, CveExtension) - } - - def registerTasks(Project project) { - project.task(TASK_NAME, type: DependencyCheckTask) - } -} \ No newline at end of file diff --git a/dependency-check-gradle/src/main/groovy/com/tools/security/tasks/Check.groovy b/dependency-check-gradle/src/main/groovy/com/tools/security/tasks/Check.groovy new file mode 100644 index 000000000..0f87aa8bc --- /dev/null +++ b/dependency-check-gradle/src/main/groovy/com/tools/security/tasks/Check.groovy @@ -0,0 +1,292 @@ +/* + * This file is part of dependency-check-gradle. + * + * 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) 2015 Wei Ma. All Rights Reserved. + */ + +package com.tools.security.tasks + +import org.gradle.api.DefaultTask +import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.ResolvedArtifact +import org.gradle.api.tasks.TaskAction +import org.gradle.api.GradleException +import org.gradle.api.InvalidUserDataException + +import org.owasp.dependencycheck.Engine +import org.owasp.dependencycheck.data.nvdcve.CveDB +import org.owasp.dependencycheck.dependency.Dependency +import org.owasp.dependencycheck.reporting.ReportGenerator +import org.owasp.dependencycheck.utils.Settings +import org.owasp.dependencycheck.dependency.Identifier; +import org.owasp.dependencycheck.dependency.Vulnerability; + + +import static org.owasp.dependencycheck.utils.Settings.KEYS.CVE_MODIFIED_12_URL +import static org.owasp.dependencycheck.utils.Settings.KEYS.CVE_MODIFIED_20_URL +import static org.owasp.dependencycheck.utils.Settings.KEYS.CVE_SCHEMA_1_2 +import static org.owasp.dependencycheck.utils.Settings.KEYS.CVE_SCHEMA_2_0 +import static org.owasp.dependencycheck.utils.Settings.KEYS.CVE_START_YEAR +import static org.owasp.dependencycheck.utils.Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP +import static org.owasp.dependencycheck.utils.Settings.KEYS.PROXY_PASSWORD +import static org.owasp.dependencycheck.utils.Settings.KEYS.PROXY_PORT +import static org.owasp.dependencycheck.utils.Settings.KEYS.PROXY_SERVER +import static org.owasp.dependencycheck.utils.Settings.KEYS.PROXY_USERNAME +import static org.owasp.dependencycheck.utils.Settings.KEYS.AUTO_UPDATE +import static org.owasp.dependencycheck.utils.Settings.KEYS.DATA_DIRECTORY +import static org.owasp.dependencycheck.utils.Settings.KEYS.SUPPRESSION_FILE + +import static org.owasp.dependencycheck.utils.Settings.KEYS.DB_DRIVER_NAME +import static org.owasp.dependencycheck.utils.Settings.KEYS.DB_DRIVER_PATH +import static org.owasp.dependencycheck.utils.Settings.KEYS.DB_CONNECTION_STRING +import static org.owasp.dependencycheck.utils.Settings.KEYS.DB_USER +import static org.owasp.dependencycheck.utils.Settings.KEYS.DB_PASSWORD + +import static org.owasp.dependencycheck.utils.Settings.KEYS.ANALYZER_JAR_ENABLED +import static org.owasp.dependencycheck.utils.Settings.KEYS.ANALYZER_NUSPEC_ENABLED +import static org.owasp.dependencycheck.utils.Settings.KEYS.ANALYZER_CENTRAL_ENABLED +import static org.owasp.dependencycheck.utils.Settings.KEYS.ANALYZER_NEXUS_ENABLED +import static org.owasp.dependencycheck.utils.Settings.KEYS.ANALYZER_NEXUS_URL +import static org.owasp.dependencycheck.utils.Settings.KEYS.ANALYZER_NEXUS_USES_PROXY +import static org.owasp.dependencycheck.utils.Settings.KEYS.ANALYZER_ARCHIVE_ENABLED +import static org.owasp.dependencycheck.utils.Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS +import static org.owasp.dependencycheck.utils.Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED +import static org.owasp.dependencycheck.utils.Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH +import static org.owasp.dependencycheck.utils.Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED +import static org.owasp.dependencycheck.utils.Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED +import static org.owasp.dependencycheck.utils.Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED +import static org.owasp.dependencycheck.utils.Settings.KEYS.ANALYZER_OPENSSL_ENABLED +import static org.owasp.dependencycheck.utils.Settings.KEYS.ANALYZER_CMAKE_ENABLED +import static org.owasp.dependencycheck.utils.Settings.KEYS.ANALYZER_AUTOCONF_ENABLED +import static org.owasp.dependencycheck.utils.Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED +import static org.owasp.dependencycheck.utils.Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED + +/** + * Checks the projects dependencies for known vulnerabilities. + */ +class Check extends DefaultTask { + + def currentProjectName = project.getName() + def config = project.dependencyCheck + + /** + * Initializes the check task. + */ + Check() { + group = 'OWASP dependency-check' + description = 'Produce dependency security report.' + } + + /** + * Calls dependency-check-core's analysis engine to scan + * all of the projects dependencies. + */ + @TaskAction + def check() { + initializeSettings() + def engine = new Engine() + + scanDependencies(engine) + analyzeDependencies(engine) + generateReport(engine) + showSummary(engine) + checkForFailure(engine) + cleanup(engine) + } + + /** + * Initializes the settings object. If the setting is not set the + * default from dependency-check-core is used. + */ + def initializeSettings() { + Settings.initialize() + + Settings.setBooleanIfNotNull(AUTO_UPDATE, config.autoUpdate) + Settings.setStringIfNotEmpty(SUPPRESSION_FILE, config.suppressionFile) + + Settings.setStringIfNotEmpty(PROXY_SERVER, config.proxy.server) + Settings.setStringIfNotEmpty(PROXY_PORT, "${config.proxy.port}") + Settings.setStringIfNotEmpty(PROXY_USERNAME, config.proxy.username) + Settings.setStringIfNotEmpty(PROXY_PASSWORD, config.proxy.password) + //Settings.setStringIfNotEmpty(CONNECTION_TIMEOUT, connectionTimeout) + Settings.setStringIfNotNull(DATA_DIRECTORY, config.data.directory) + Settings.setStringIfNotEmpty(DB_DRIVER_NAME, config.data.driver) + Settings.setStringIfNotEmpty(DB_DRIVER_PATH, config.data.driverPath) + Settings.setStringIfNotEmpty(DB_CONNECTION_STRING, config.data.connectionString) + Settings.setStringIfNotEmpty(DB_USER, config.data.username) + Settings.setStringIfNotEmpty(DB_PASSWORD, config.data.password) + Settings.setStringIfNotEmpty(CVE_MODIFIED_12_URL, config.cve.url12Modified) + Settings.setStringIfNotEmpty(CVE_MODIFIED_20_URL, config.cve.url20Modified) + Settings.setStringIfNotEmpty(CVE_SCHEMA_1_2, config.cve.url12Base) + Settings.setStringIfNotEmpty(CVE_SCHEMA_2_0, config.cve.url20Base) + + if (config.cveValidForHours != null) { + if (config.cveValidForHours >= 0) { + Settings.setInt(CVE_CHECK_VALID_FOR_HOURS, config.cveValidForHours); + } else { + throw new InvalidUserDataException("Invalid setting: `validForHours` must be 0 or greater"); + } + } + Settings.setBooleanIfNotNull(ANALYZER_JAR_ENABLED, config.analyzer.jarEnabled) + Settings.setBooleanIfNotNull(ANALYZER_NUSPEC_ENABLED, config.analyzer.nuspecEnabled) + Settings.setBooleanIfNotNull(ANALYZER_CENTRAL_ENABLED, config.analyzer.centralEnabled) + + Settings.setBooleanIfNotNull(ANALYZER_NEXUS_ENABLED, config.analyzer.nexusEnabled) + Settings.setStringIfNotEmpty(ANALYZER_NEXUS_URL, config.analyzer.nexusUrl) + Settings.setBooleanIfNotNull(ANALYZER_NEXUS_USES_PROXY, config.analyzer.nexusUsesProxy) + + Settings.setBooleanIfNotNull(ANALYZER_ARCHIVE_ENABLED, config.analyzer.archiveEnabled) + Settings.setStringIfNotEmpty(ADDITIONAL_ZIP_EXTENSIONS, config.analyzer.zipExtensions) + Settings.setBooleanIfNotNull(ANALYZER_ASSEMBLY_ENABLED, config.analyzer.assemblyEnabled) + Settings.setStringIfNotEmpty(ANALYZER_ASSEMBLY_MONO_PATH, config.analyzer.pathToMono) + + Settings.setBooleanIfNotNull(ANALYZER_PYTHON_DISTRIBUTION_ENABLED, config.analyzer.pyDistributionEnabled) + Settings.setBooleanIfNotNull(ANALYZER_PYTHON_PACKAGE_ENABLED, config.analyzer.pyPackageEnabled) + Settings.setBooleanIfNotNull(ANALYZER_RUBY_GEMSPEC_ENABLED, config.analyzer.rubygemsEnabled) + Settings.setBooleanIfNotNull(ANALYZER_OPENSSL_ENABLED, config.analyzer.opensslEnabled) + Settings.setBooleanIfNotNull(ANALYZER_CMAKE_ENABLED, config.analyzer.cmakeEnabled) + Settings.setBooleanIfNotNull(ANALYZER_AUTOCONF_ENABLED, config.analyzer.autoconfEnabled) + Settings.setBooleanIfNotNull(ANALYZER_COMPOSER_LOCK_ENABLED, config.analyzer.composerEnabled) + Settings.setBooleanIfNotNull(ANALYZER_NODE_PACKAGE_ENABLED, config.analyzer.nodeEnabled) + } + /** + * Relases resources and removes temporary files used. + */ + def cleanup(engine) { + Settings.cleanup(true) + engine.cleanup(); + } + + /** + * Loads the projects dependencies into the dependency-check analysis engine. + */ + def scanDependencies(engine) { + logger.lifecycle("Verifying dependencies for project ${currentProjectName}") + getAllDependencies(project).each { + engine.scan(it) + } + } + + /** + * Performs the dependency-check analysis. + */ + def analyzeDependencies(Engine engine) { + logger.lifecycle("Checking for updates and analyzing vulnerabilities for dependencies") + engine.analyzeDependencies() + } + + /** + * Displays a summary of the dependency-check results to the build console. + */ + def showSummary(Engine engine) { + def vulnerabilities = engine.getDependencies().collect { Dependency dependency -> + dependency.getVulnerabilities() + }.flatten() + + logger.lifecycle("Found ${vulnerabilities.size()} vulnerabilities in project ${currentProjectName}") + if (config.showSummary) { + final StringBuilder summary = new StringBuilder() + for (Dependency d : engine.getDependencies()) { + boolean firstEntry = true + final StringBuilder ids = new StringBuilder() + for (Vulnerability v : d.getVulnerabilities()) { + if (firstEntry) { + firstEntry = false + } else { + ids.append(", ") + } + ids.append(v.getName()) + } + if (ids.length() > 0) { + summary.append(d.getFileName()).append(" (") + firstEntry = true + for (Identifier id : d.getIdentifiers()) { + if (firstEntry) { + firstEntry = false + } else { + summary.append(", ") + } + summary.append(id.getValue()) + } + summary.append(") : ").append(ids).append('\n') + } + } + if (summary.length() > 0) { + final String msg = String.format("%n%n" + + "One or more dependencies were identified with known vulnerabilities:%n%n%s" + + "%n%nSee the dependency-check report for more details.%n%n", summary.toString()) + logger.lifecycle(msg) + } + } + + } + + /** + * If configured, fails the build if a vulnerability is identified with a CVSS + * score higher then the failure threshold configured. + */ + def checkForFailure(Engine engine) { + if (config.failBuildOnCVSS>10) { + return + } + + def vulnerabilities = engine.getDependencies().collect { Dependency dependency -> + dependency.getVulnerabilities() + }.flatten() + + final StringBuilder ids = new StringBuilder(); + + vulnerabilities.each { + if (it.getCvssScore() >= config.failBuildOnCVSS) { + if (ids.length() == 0) { + ids.append(it.getName()); + } else { + ids.append(", ").append(it.getName()); + } + } + } + if (ids.length() > 0) { + final String msg = String.format("%n%nDependency-Check Failure:%n" + + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n" + + "See the dependency-check report for more details.%n%n", config.failBuildOnCVSS, ids.toString()); + throw new GradleException(msg); + } + + } + /** + * Writes the report(s) to the configured output directory. + */ + def generateReport(Engine engine) { + logger.lifecycle("Generating report for project ${currentProjectName}") + def reportGenerator = new ReportGenerator(currentProjectName, engine.dependencies, engine.analyzers, + new CveDB().databaseProperties) + + reportGenerator.generateReports("$project.buildDir/${config.reportsDirName}", config.format) + } + + /** + * Returns all dependencies associated wtihin the configured dependency groups. Test + * groups can be excluded by setting the skipTestGroups configuration to true. + */ + def getAllDependencies(project) { + return project.getConfigurations().findAll { + !config.skipTestGroups || (config.skipTestGroups && !it.getName().startsWith("test")) + }.collect { + it.getResolvedConfiguration().getResolvedArtifacts().collect { ResolvedArtifact artifact -> + artifact.getFile() + } + }.flatten().unique(); + } +} diff --git a/dependency-check-gradle/src/main/groovy/com/tools/security/tasks/DependencyCheckTask.groovy b/dependency-check-gradle/src/main/groovy/com/tools/security/tasks/DependencyCheckTask.groovy deleted file mode 100644 index e81e89e01..000000000 --- a/dependency-check-gradle/src/main/groovy/com/tools/security/tasks/DependencyCheckTask.groovy +++ /dev/null @@ -1,168 +0,0 @@ -/* - * This file is part of dependency-check-gradle. - * - * 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) 2015 Wei Ma. All Rights Reserved. - */ - -package com.tools.security.tasks - -import org.gradle.api.DefaultTask -import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.ResolvedArtifact -import org.gradle.api.tasks.TaskAction -import org.owasp.dependencycheck.Engine -import org.owasp.dependencycheck.data.nvdcve.CveDB -import org.owasp.dependencycheck.dependency.Dependency -import org.owasp.dependencycheck.reporting.ReportGenerator -import org.owasp.dependencycheck.utils.Settings - -import static org.owasp.dependencycheck.utils.Settings.KEYS.CVE_MODIFIED_12_URL -import static org.owasp.dependencycheck.utils.Settings.KEYS.CVE_MODIFIED_20_URL -import static org.owasp.dependencycheck.utils.Settings.KEYS.CVE_SCHEMA_1_2 -import static org.owasp.dependencycheck.utils.Settings.KEYS.CVE_SCHEMA_2_0 -import static org.owasp.dependencycheck.utils.Settings.KEYS.CVE_START_YEAR -import static org.owasp.dependencycheck.utils.Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP -import static org.owasp.dependencycheck.utils.Settings.KEYS.PROXY_PASSWORD -import static org.owasp.dependencycheck.utils.Settings.KEYS.PROXY_PORT -import static org.owasp.dependencycheck.utils.Settings.KEYS.PROXY_SERVER -import static org.owasp.dependencycheck.utils.Settings.KEYS.PROXY_USERNAME -import static org.owasp.dependencycheck.utils.Settings.setBoolean -import static org.owasp.dependencycheck.utils.Settings.setString - -class DependencyCheckTask extends DefaultTask { - - def currentProjectName = project.getName() - def config = project.dependencyCheck - - DependencyCheckTask() { - group = 'Dependency Check' - description = 'Produce dependency security report.' - } - - @TaskAction - def check() { - initializeSettings() - def engine = initializeEngine() - - verifyDependencies(engine) - analyzeDependencies(engine) - retrieveVulnerabilities(engine) - generateReport(engine) - - cleanup(engine) - } - - private Engine initializeEngine() { - new Engine() - } - - def initializeSettings() { - Settings.initialize() - overrideProxySetting() - overrideCveUrlSetting() - overrideDownloaderSetting() - } - - def cleanup(engine) { - Settings.cleanup(true) - engine.cleanup(); - } - - def verifyDependencies(engine) { - logger.lifecycle("Verifying dependencies for project ${currentProjectName}") - getAllDependencies(project).each { engine.scan(it) } - } - - def analyzeDependencies(Engine engine) { - logger.lifecycle("Checking for updates and analyzing vulnerabilities for dependencies") - engine.analyzeDependencies() - } - - def retrieveVulnerabilities(Engine engine) { - def vulnerabilities = engine.getDependencies().collect { Dependency dependency -> - dependency.getVulnerabilities() - }.flatten() - - logger.lifecycle("Found ${vulnerabilities.size()} vulnerabilities in project ${currentProjectName}") - } - - def generateReport(Engine engine) { - logger.lifecycle("Generating report for project ${currentProjectName}") - def reportGenerator = new ReportGenerator(currentProjectName, engine.dependencies, engine.analyzers, - new CveDB().databaseProperties) - - reportGenerator.generateReports(generateReportDirectory(currentProjectName), ReportGenerator.Format.ALL) - } - - def generateReportDirectory(String currentProjectName) { - "${config.outputDirectory}/${currentProjectName}" - } - - def overrideProxySetting() { - if (isProxySettingExist()) { - logger.lifecycle("Using proxy ${config.proxy.server}:${config.proxy.port}") - - overrideStringSetting(PROXY_SERVER, config.proxy.server) - overrideStringSetting(PROXY_PORT, "${config.proxy.port}") - overrideStringSetting(PROXY_USERNAME, config.proxy.username) - overrideStringSetting(PROXY_PASSWORD, config.proxy.password) - } - } - - def isProxySettingExist() { - config.proxy.server != null && config.proxy.port != null - } - - def getAllDependencies(project) { - return project.getConfigurations().collect { Configuration configuration -> - configuration.getResolvedConfiguration().getResolvedArtifacts().collect { ResolvedArtifact artifact -> - artifact.getFile() - } - }.flatten(); - } - - def overrideCveUrlSetting() { - overrideStringSetting(CVE_MODIFIED_20_URL, config.cve.url20Modified) - overrideStringSetting(CVE_MODIFIED_12_URL, config.cve.url12Modified) - overrideIntegerSetting(CVE_START_YEAR, config.cve.startYear) - overrideStringSetting(CVE_SCHEMA_2_0, config.cve.url20Base) - overrideStringSetting(CVE_SCHEMA_1_2, config.cve.url12Base) - } - - def overrideDownloaderSetting() { - overrideBooleanSetting(DOWNLOADER_QUICK_QUERY_TIMESTAMP, config.quickQueryTimestamp) - } - - private overrideStringSetting(String key, String providedValue) { - if (providedValue != null) { - logger.lifecycle("Setting [${key}] overrided with value [${providedValue}]") - setString(key, providedValue) - } - } - - private overrideIntegerSetting(String key, Integer providedValue) { - if (providedValue != null) { - logger.lifecycle("Setting [${key}] overrided with value [${providedValue}]") - setString(key, "${providedValue}") - } - } - - private overrideBooleanSetting(String key, Boolean providedValue) { - if (providedValue != null) { - logger.lifecycle("Setting [${key}] overrided with value [${providedValue}]") - setBoolean(key, providedValue) - } - } -} diff --git a/dependency-check-gradle/src/main/groovy/com/tools/security/tasks/Purge.groovy b/dependency-check-gradle/src/main/groovy/com/tools/security/tasks/Purge.groovy new file mode 100644 index 000000000..89e74a9a1 --- /dev/null +++ b/dependency-check-gradle/src/main/groovy/com/tools/security/tasks/Purge.groovy @@ -0,0 +1,82 @@ +/* + * This file is part of dependency-check-gradle. + * + * 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) 2015 Jeremy Long. All Rights Reserved. + */ + +package com.tools.security.tasks + +import org.gradle.api.DefaultTask +import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.ResolvedArtifact +import org.gradle.api.tasks.TaskAction +import java.io.File +import org.owasp.dependencycheck.Engine +import org.owasp.dependencycheck.data.nvdcve.CveDB +import org.owasp.dependencycheck.dependency.Dependency +import org.owasp.dependencycheck.reporting.ReportGenerator +import org.owasp.dependencycheck.utils.Settings + +import static org.owasp.dependencycheck.utils.Settings.KEYS.DATA_DIRECTORY + +/** + * Purges the local cache of the NVD CVE data. + */ +class Purge extends DefaultTask { + + def config = project.dependencyCheckPurge + + /** + * Initializes the purge task. + */ + Purge() { + group = 'OWASP dependency-check' + description = 'Purges the local cache of the NVD.' + } + + /** + * Purges the local cache of the NVD data. + */ + @TaskAction + def purge() { + initializeSettings() + def db = new File(Settings.getDataDirectory(), "dc.h2.db") + if (db.exists()) { + if (db.delete()) { + logger.info("Database file purged; local copy of the NVD has been removed") + } else { + logger.warn("Unable to delete '${db.getAbsolutePath()}'; please delete the file manually") + } + } else { + logger.warn("Unable to purge database; the database file does not exists: ${db.getAbsolutePath()}") + } + cleanup() + } + + /** + * Intializes the configuration. + */ + def initializeSettings() { + Settings.initialize() + Settings.setStringIfNotNull(DATA_DIRECTORY, config.data.directory) + } + + /** + * Relases resources and removes temporary files used. + */ + def cleanup() { + Settings.cleanup(true) + } +} diff --git a/dependency-check-gradle/src/main/groovy/com/tools/security/tasks/Update.groovy b/dependency-check-gradle/src/main/groovy/com/tools/security/tasks/Update.groovy new file mode 100644 index 000000000..93881b286 --- /dev/null +++ b/dependency-check-gradle/src/main/groovy/com/tools/security/tasks/Update.groovy @@ -0,0 +1,116 @@ +/* + * This file is part of dependency-check-gradle. + * + * 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) 2015 Jeremy Long. All Rights Reserved. + */ + +package com.tools.security.tasks + +import org.gradle.api.DefaultTask +import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.ResolvedArtifact +import org.gradle.api.tasks.TaskAction +import org.gradle.api.InvalidUserDataException +import org.owasp.dependencycheck.Engine +import org.owasp.dependencycheck.data.nvdcve.CveDB +import org.owasp.dependencycheck.dependency.Dependency +import org.owasp.dependencycheck.reporting.ReportGenerator +import org.owasp.dependencycheck.utils.Settings + +import static org.owasp.dependencycheck.utils.Settings.KEYS.CVE_MODIFIED_12_URL +import static org.owasp.dependencycheck.utils.Settings.KEYS.CVE_MODIFIED_20_URL +import static org.owasp.dependencycheck.utils.Settings.KEYS.CVE_SCHEMA_1_2 +import static org.owasp.dependencycheck.utils.Settings.KEYS.CVE_SCHEMA_2_0 +import static org.owasp.dependencycheck.utils.Settings.KEYS.CVE_START_YEAR +import static org.owasp.dependencycheck.utils.Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP +import static org.owasp.dependencycheck.utils.Settings.KEYS.PROXY_PASSWORD +import static org.owasp.dependencycheck.utils.Settings.KEYS.PROXY_PORT +import static org.owasp.dependencycheck.utils.Settings.KEYS.PROXY_SERVER +import static org.owasp.dependencycheck.utils.Settings.KEYS.PROXY_USERNAME +import static org.owasp.dependencycheck.utils.Settings.KEYS.DATA_DIRECTORY +import static org.owasp.dependencycheck.utils.Settings.KEYS.SUPPRESSION_FILE + +import static org.owasp.dependencycheck.utils.Settings.KEYS.DB_DRIVER_NAME +import static org.owasp.dependencycheck.utils.Settings.KEYS.DB_DRIVER_PATH +import static org.owasp.dependencycheck.utils.Settings.KEYS.DB_CONNECTION_STRING +import static org.owasp.dependencycheck.utils.Settings.KEYS.DB_USER +import static org.owasp.dependencycheck.utils.Settings.KEYS.DB_PASSWORD + +/** + * Updates the local cache of the NVD CVE data. + * + * @author Jeremy Long + */ +class Update extends DefaultTask { + + def config = project.dependencyCheckUpdate + + /** + * Initializes the update task. + */ + Update() { + group = 'OWASP dependency-check' + description = 'Downloads and stores updates from the NVD CVE data feeds.' + } + + /** + * Executes the update task. + */ + @TaskAction + def update() { + initializeSettings() + def engine = new Engine() + engine.doUpdates() + cleanup(engine) + } + + /** + * Initializes the settings; if the setting is not configured + * then the default value from dependency-check-core is used. + */ + def initializeSettings() { + Settings.initialize() + Settings.setStringIfNotEmpty(PROXY_SERVER, config.proxy.server) + Settings.setStringIfNotEmpty(PROXY_PORT, "${config.proxy.port}") + Settings.setStringIfNotEmpty(PROXY_USERNAME, config.proxy.username) + Settings.setStringIfNotEmpty(PROXY_PASSWORD, config.proxy.password) + //Settings.setStringIfNotEmpty(CONNECTION_TIMEOUT, connectionTimeout) + Settings.setStringIfNotNull(DATA_DIRECTORY, config.data.directory) + Settings.setStringIfNotEmpty(DB_DRIVER_NAME, config.data.driver) + Settings.setStringIfNotEmpty(DB_DRIVER_PATH, config.data.driverPath) + Settings.setStringIfNotEmpty(DB_CONNECTION_STRING, config.data.connectionString) + Settings.setStringIfNotEmpty(DB_USER, config.data.username) + Settings.setStringIfNotEmpty(DB_PASSWORD, config.data.password) + Settings.setStringIfNotEmpty(CVE_MODIFIED_12_URL, config.cve.url12Modified) + Settings.setStringIfNotEmpty(CVE_MODIFIED_20_URL, config.cve.url20Modified) + Settings.setStringIfNotEmpty(CVE_SCHEMA_1_2, config.cve.url12Base) + Settings.setStringIfNotEmpty(CVE_SCHEMA_2_0, config.cve.url20Base) + + if (config.cveValidForHours != null) { + if (config.cveValidForHours >= 0) { + Settings.setInt(CVE_CHECK_VALID_FOR_HOURS, config.cveValidForHours); + } else { + throw new InvalidUserDataException("Invalid setting: `validForHours` must be 0 or greater"); + } + } + } + /** + * Relases resources and removes temporary files used. + */ + def cleanup(engine) { + Settings.cleanup(true) + engine.cleanup(); + } +} diff --git a/dependency-check-gradle/src/main/resources/META-INF/gradle-plugins/dependency-check.properties b/dependency-check-gradle/src/main/resources/META-INF/gradle-plugins/dependencyCheck.properties similarity index 89% rename from dependency-check-gradle/src/main/resources/META-INF/gradle-plugins/dependency-check.properties rename to dependency-check-gradle/src/main/resources/META-INF/gradle-plugins/dependencyCheck.properties index 877c70050..523794cc4 100644 --- a/dependency-check-gradle/src/main/resources/META-INF/gradle-plugins/dependency-check.properties +++ b/dependency-check-gradle/src/main/resources/META-INF/gradle-plugins/dependencyCheck.properties @@ -16,4 +16,4 @@ # Copyright (c) 2015 Wei Ma. All Rights Reserved. # -implementation-class=com.tools.security.plugin.DependencyCheckGradlePlugin \ No newline at end of file +implementation-class=com.tools.security.plugin.DependencyCheck \ No newline at end of file diff --git a/dependency-check-gradle/src/site/markdown/configuration-update.md b/dependency-check-gradle/src/site/markdown/configuration-update.md new file mode 100644 index 000000000..a95a6b402 --- /dev/null +++ b/dependency-check-gradle/src/site/markdown/configuration-update.md @@ -0,0 +1,116 @@ +Tasks +==================== + +Task | Description +------------------------------------------|----------------------- +[dependencyCheck](configuration.html) | Runs dependency-check against the project and generates a report. +dependencyCheckUpdate | Updates the local cache of the NVD data from NIST. +[dependencyCheckPurge](config-purge.html) | Deletes the local copy of the NVD. This is used to force a refresh of the data. + +Configuration: dependencyCheckUpdate +==================== +The following properties can be configured for the dependencyCheckUpdate task: + +Property | Description | Default Value +---------------------|------------------------------------|------------------ +autoUpdate | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. | true +cveValidForHours | Sets the number of hours to wait before checking for new updates from the NVD. | 4 +failBuildOnCVSS | Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11; since the CVSS scores are 0-10, by default the build will never fail. | 11 +format | The report format to be generated (HTML, XML, VULN, ALL). | HTML +reportsDirName | The location to write the report(s). This directory will be located in the build directory. | reports +skipTestGroups | When set to true (the default) all dependency groups that being with 'test' will be skipped. | true +suppressionFile | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html) |   + +$H$H$H$H Example +```groovy +dependencyCheck { + autoUpdate=false + cveValidForHours=1 + format=ALL +} +``` + +$H$H$H Proxy Configuration + +Property | Description | Default Value +------------------|------------------------------------|------------------ +server | The proxy server. |   +port | The proxy port. |   +username | Defines the proxy user name. |   +password | Defines the proxy password. |   +connectionTimeout | The URL Connection Timeout. |   + +$H$H$H$H Example +```groovy +dependencyCheck { + proxy { + server=some.proxy.server + port=8989 + } +} +``` + +$H$H$H Advanced Configuration + +The following properties can be configured in the dependencyCheck task. However, they are less frequently changed. One exception +may be the cvedUrl properties, which can be used to host a mirror of the NVD within an enterprise environment. +Note, if ANY of the cve configuration group are set - they should all be set to ensure things work as expected. + +Config Group | Property | Description | Default Value +-------------|-------------------|---------------------------------------------------------------------------------------------|------------------ +cve | url12Modified | URL for the modified CVE 1.2. | https://nvd.nist.gov/download/nvdcve-Modified.xml.gz +cve | url20Modified | URL for the modified CVE 2.0. | https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-Modified.xml.gz +cve | url12Base | Base URL for each year's CVE 1.2, the %d will be replaced with the year. | https://nvd.nist.gov/download/nvdcve-%d.xml.gz +cve | url20Base | Base URL for each year's CVE 2.0, the %d will be replaced with the year. | https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz +data | directory | Sets the data directory to hold SQL CVEs contents. This should generally not be changed. |   +data | driver | The name of the database driver. Example: org.h2.Driver. |   +data | driverPath | The path to the database driver JAR file; only used if the driver is not in the class path. |   +data | connectionString | The connection string used to connect to the database. |   +data | username | The username used when connecting to the database. |   +data | password | The password used when connecting to the database. |   + +$H$H$H$H Example +```groovy +dependencyCheck { + data { + directory='d:/nvd' + } +} +``` + +$H$H$H Analyzer Configuration + +In addition to the above, the dependencyCheck plugin can be configured to enable or disable specific +analyzers by configuring the `analyzer` section. Note, specific file type analyzers will automatically +disable themselves if no file types that they support are detected - so specifically disabling the +analyzers is likely not needed. + +Property | Description | Default Value +----------------------|---------------------------------------------------------------------------|------------------ +archiveEnabled | Sets whether the Archive Analyzer will be used. | true +zipExtensions | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. |   +jarEnabled | Sets whether Jar Analyzer will be used. | true +centralEnabled | Sets whether Central Analyzer will be used. If this analyzer is being disabled there is a good chance you also want to disable the Nexus Analyzer (see below). | true +nexusEnabled | Sets whether Nexus Analyzer will be used. This analyzer is superceded by the Central Analyzer; however, you can configure this to run against a Nexus Pro installation. | true +nexusUrl | Defines the Nexus Server's web service end point (example http://domain.enterprise/service/local/). If not set the Nexus Analyzer will be disabled. |   +nexusUsesProxy | Whether or not the defined proxy should be used when connecting to Nexus. | true +pyDistributionEnabled | Sets whether the Python Distribution Analyzer will be used. | true +pyPackageEnabled | Sets whether the Python Package Analyzer will be used. | true +rubygemsEnabled | Sets whether the Ruby Gemspec Analyzer will be used. | true +opensslEnabled | Sets whether or not the openssl Analyzer should be used. | true +cmakeEnabled | Sets whether or not the CMake Analyzer should be used. | true +autoconfEnabled | Sets whether or not the autoconf Analyzer should be used. | true +composerEnabled | Sets whether or not the PHP Composer Lock File Analyzer should be used. | true +nodeEnabled | Sets whether or not the Node.js Analyzer should be used. | true +nuspecEnabled | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | true +assemblyEnabled | Sets whether or not the .NET Assembly Analyzer should be used. | true +pathToMono | The path to Mono for .NET assembly analysis on non-windows systems. |   + +$H$H$H$H Example +```groovy +dependencyCheck { + analyzer { + assemblyEnabled=false + } +} +``` diff --git a/dependency-check-gradle/src/site/markdown/configuration.md b/dependency-check-gradle/src/site/markdown/configuration.md new file mode 100644 index 000000000..6ba6c9266 --- /dev/null +++ b/dependency-check-gradle/src/site/markdown/configuration.md @@ -0,0 +1,116 @@ +Tasks +==================== + +Task | Description +--------------------------------------------|----------------------- +dependencyCheck | Runs dependency-check against the project and generates a report. +[dependencyCheckUpdate](config-update.html) | Updates the local cache of the NVD data from NIST. +[dependencyCheckPurge](config-purge.html) | Deletes the local copy of the NVD. This is used to force a refresh of the data. + +Configuration: dependencyCheck +==================== +The following properties can be configured for the dependencyCheck task: + +Property | Description | Default Value +---------------------|------------------------------------|------------------ +autoUpdate | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. | true +cveValidForHours | Sets the number of hours to wait before checking for new updates from the NVD. | 4 +failBuildOnCVSS | Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11; since the CVSS scores are 0-10, by default the build will never fail. | 11 +format | The report format to be generated (HTML, XML, VULN, ALL). | HTML +reportsDirName | The location to write the report(s). This directory will be located in the build directory. | reports +skipTestGroups | When set to true (the default) all dependency groups that being with 'test' will be skipped. | true +suppressionFile | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html) |   + +$H$H$H$H Example +```groovy +dependencyCheck { + autoUpdate=false + cveValidForHours=1 + format=ALL +} +``` + +$H$H$H Proxy Configuration + +Property | Description | Default Value +------------------|------------------------------------|------------------ +server | The proxy server. |   +port | The proxy port. |   +username | Defines the proxy user name. |   +password | Defines the proxy password. |   +connectionTimeout | The URL Connection Timeout. |   + +$H$H$H$H Example +```groovy +dependencyCheck { + proxy { + server=some.proxy.server + port=8989 + } +} +``` + +$H$H$H Advanced Configuration + +The following properties can be configured in the dependencyCheck task. However, they are less frequently changed. One exception +may be the cvedUrl properties, which can be used to host a mirror of the NVD within an enterprise environment. +Note, if ANY of the cve configuration group are set - they should all be set to ensure things work as expected. + +Config Group | Property | Description | Default Value +-------------|-------------------|---------------------------------------------------------------------------------------------|------------------ +cve | url12Modified | URL for the modified CVE 1.2. | https://nvd.nist.gov/download/nvdcve-Modified.xml.gz +cve | url20Modified | URL for the modified CVE 2.0. | https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-Modified.xml.gz +cve | url12Base | Base URL for each year's CVE 1.2, the %d will be replaced with the year. | https://nvd.nist.gov/download/nvdcve-%d.xml.gz +cve | url20Base | Base URL for each year's CVE 2.0, the %d will be replaced with the year. | https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz +data | directory | Sets the data directory to hold SQL CVEs contents. This should generally not be changed. |   +data | driver | The name of the database driver. Example: org.h2.Driver. |   +data | driverPath | The path to the database driver JAR file; only used if the driver is not in the class path. |   +data | connectionString | The connection string used to connect to the database. |   +data | username | The username used when connecting to the database. |   +data | password | The password used when connecting to the database. |   + +$H$H$H$H Example +```groovy +dependencyCheck { + data { + directory='d:/nvd' + } +} +``` + +$H$H$H Analyzer Configuration + +In addition to the above, the dependencyCheck plugin can be configured to enable or disable specific +analyzers by configuring the `analyzer` section. Note, specific file type analyzers will automatically +disable themselves if no file types that they support are detected - so specifically disabling the +analyzers is likely not needed. + +Property | Description | Default Value +----------------------|---------------------------------------------------------------------------|------------------ +archiveEnabled | Sets whether the Archive Analyzer will be used. | true +zipExtensions | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. |   +jarEnabled | Sets whether Jar Analyzer will be used. | true +centralEnabled | Sets whether Central Analyzer will be used. If this analyzer is being disabled there is a good chance you also want to disable the Nexus Analyzer (see below). | true +nexusEnabled | Sets whether Nexus Analyzer will be used. This analyzer is superceded by the Central Analyzer; however, you can configure this to run against a Nexus Pro installation. | true +nexusUrl | Defines the Nexus Server's web service end point (example http://domain.enterprise/service/local/). If not set the Nexus Analyzer will be disabled. |   +nexusUsesProxy | Whether or not the defined proxy should be used when connecting to Nexus. | true +pyDistributionEnabled | Sets whether the Python Distribution Analyzer will be used. | true +pyPackageEnabled | Sets whether the Python Package Analyzer will be used. | true +rubygemsEnabled | Sets whether the Ruby Gemspec Analyzer will be used. | true +opensslEnabled | Sets whether or not the openssl Analyzer should be used. | true +cmakeEnabled | Sets whether or not the CMake Analyzer should be used. | true +autoconfEnabled | Sets whether or not the autoconf Analyzer should be used. | true +composerEnabled | Sets whether or not the PHP Composer Lock File Analyzer should be used. | true +nodeEnabled | Sets whether or not the Node.js Analyzer should be used. | true +nuspecEnabled | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | true +assemblyEnabled | Sets whether or not the .NET Assembly Analyzer should be used. | true +pathToMono | The path to Mono for .NET assembly analysis on non-windows systems. |   + +$H$H$H$H Example +```groovy +dependencyCheck { + analyzer { + assemblyEnabled=false + } +} +``` diff --git a/dependency-check-gradle/src/site/markdown/index.md b/dependency-check-gradle/src/site/markdown/index.md deleted file mode 100644 index d7085ebb6..000000000 --- a/dependency-check-gradle/src/site/markdown/index.md +++ /dev/null @@ -1,28 +0,0 @@ -Dependency-Check Gradle Plugin -============================== - -Dependency-Check is a utility that identifies project dependencies and checks if there are any known, publicly disclosed, vulnerabilities. This tool can be part of the solution to the OWASP Top 10 2013: A9 - Using Components with Known Vulnerabilities. - -The Gradle Plugin is still a work in progress. The core dependency-check functionality works; however, the configuration options available in the other plugins still need to be completed. -For more information about the plugin, including usage, please see the github repo's [readme](https://github.com/jeremylong/DependencyCheck/blob/master/dependency-check-gradle/README.md). - - -Mailing List ------------- - -Subscribe: [dependency-check+subscribe@googlegroups.com] [subscribe] - -Post: [dependency-check@googlegroups.com] [post] - -License -------------------- - -Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt] [license] file for the full license. - -Dependency-Check makes use of several other open source libraries. Please see the [NOTICE.txt] [notices] file for more information. - - - [subscribe]: mailto:dependency-check+subscribe@googlegroups.com - [post]: mailto:dependency-check@googlegroups.com - [license]: https://github.com/jeremylong/DependencyCheck/blob/master/dependency-check-gradle/LICENSE.txt - [notices]: https://github.com/jeremylong/DependencyCheck/blob/master/dependency-check-gradle/NOTICE.txt diff --git a/dependency-check-gradle/src/site/markdown/index.md.vm b/dependency-check-gradle/src/site/markdown/index.md.vm new file mode 100644 index 000000000..1653d3e88 --- /dev/null +++ b/dependency-check-gradle/src/site/markdown/index.md.vm @@ -0,0 +1,60 @@ +Usage +============================== +The OWASP dependency-check-gradle plugin provides monitoring of the projects dependent +libraries; creating a report of known vulnerable components that are included in the build. + +It is important to understand that the first time this task is executed it may +take 5-20 minutes as it downloads and processes the data from the National +Vulnerability Database (NVD) hosted by NIST: https://nvd.nist.gov + +After the first batch download, as long as the plugin is executed at least once every +seven days the update will only take a few seconds. + +#set( $H = '#' ) + +$H$H$H Step 1, Apply dependency-check-gradle plugin +Install from Maven central repo + +```groovy +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath 'org.owasp:dependency-check-gradle:${project.version}' + } +} + +apply plugin: 'dependencyCheck' +``` + +$H$H$H Step 2, Run the dependencyCheck task + +Once gradle plugin applied, run following gradle task to check dependencies: + +``` +gradle dependencyCheck --info +``` + +The reports will be generated automatically under `buildDir/reports` folder. + + +Mailing List +------------ + +Subscribe: [dependency-check+subscribe@googlegroups.com] [subscribe] + +Post: [dependency-check@googlegroups.com] [post] + +License +------------------- + +Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt] [license] file for the full license. + +Dependency-Check makes use of several other open source libraries. Please see the [NOTICE.txt] [notices] file for more information. + + + [subscribe]: mailto:dependency-check+subscribe@googlegroups.com + [post]: mailto:dependency-check@googlegroups.com + [license]: https://github.com/jeremylong/DependencyCheck/blob/master/dependency-check-gradle/LICENSE.txt + [notices]: https://github.com/jeremylong/DependencyCheck/blob/master/dependency-check-gradle/NOTICE.txt diff --git a/dependency-check-gradle/src/test/groovy/com/tools/security/plugin/DependencyCheckGradlePluginSpec.groovy b/dependency-check-gradle/src/test/groovy/com/tools/security/plugin/DependencyCheckGradlePluginSpec.groovy index 43ddd93b0..4d793c351 100644 --- a/dependency-check-gradle/src/test/groovy/com/tools/security/plugin/DependencyCheckGradlePluginSpec.groovy +++ b/dependency-check-gradle/src/test/groovy/com/tools/security/plugin/DependencyCheckGradlePluginSpec.groovy @@ -22,7 +22,7 @@ import nebula.test.PluginProjectSpec import org.gradle.api.Task class DependencyCheckGradlePluginSpec extends PluginProjectSpec { - static final String PLUGIN_ID = 'dependency-check' + static final String PLUGIN_ID = 'dependency-check-gradle' @Override String getPluginName() { diff --git a/dependency-check-jenkins/pom.xml b/dependency-check-jenkins/pom.xml index 8a013f002..81f1aba65 100644 --- a/dependency-check-jenkins/pom.xml +++ b/dependency-check-jenkins/pom.xml @@ -3,7 +3,7 @@ org.owasp dependency-check-parent - 1.3.1 + 1.3.2-SNAPSHOT dependency-check-jenkins Dependency-Check Jenkins Plugin diff --git a/dependency-check-maven/pom.xml b/dependency-check-maven/pom.xml index b18d81a04..dd8a462c9 100644 --- a/dependency-check-maven/pom.xml +++ b/dependency-check-maven/pom.xml @@ -22,7 +22,7 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.3.1 + 1.3.2-SNAPSHOT dependency-check-maven diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java index b6ca59a9a..e6a1e41d9 100644 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java +++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java @@ -29,6 +29,7 @@ import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProject; import org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer; @@ -45,7 +46,7 @@ import org.owasp.dependencycheck.utils.Settings; */ @Mojo( name = "aggregate", - defaultPhase = LifecyclePhase.COMPILE, + defaultPhase = LifecyclePhase.VERIFY, /*aggregator = true,*/ threadSafe = true, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, @@ -173,15 +174,14 @@ public class AggregateMojo extends BaseDependencyCheckMojo { } } } + final Set addedDescendants = new HashSet(); for (MavenProject dec : descendants) { for (String mod : dec.getModules()) { try { File mpp = new File(dec.getBasedir(), mod); mpp = mpp.getCanonicalFile(); - if (mpp.compareTo(p.getBasedir()) == 0 && descendants.add(p)) { - if (getLog().isDebugEnabled()) { - getLog().debug(String.format("Decendent module %s added", p.getName())); - } + if (mpp.compareTo(p.getBasedir()) == 0) { + addedDescendants.add(p); } } catch (IOException ex) { if (getLog().isDebugEnabled()) { @@ -190,6 +190,11 @@ public class AggregateMojo extends BaseDependencyCheckMojo { } } } + for (MavenProject addedDescendant : addedDescendants) { + if (descendants.add(addedDescendant) && getLog().isDebugEnabled()) { + getLog().debug(String.format("Decendent module %s added", addedDescendant.getName())); + } + } } } while (size != 0 && size != descendants.size()); if (getLog().isDebugEnabled()) { @@ -257,6 +262,13 @@ public class AggregateMojo extends BaseDependencyCheckMojo { return true; //aggregate always returns true for now - we can look at a more complicated/acurate solution later } + /** + * The name of the report in the site. + */ + @SuppressWarnings("CanBeFinal") + @Parameter(property = "name", defaultValue = "dependency-check:aggregate", required = true) + private String name = "dependency-check:aggregate"; + /** * Returns the report name. * @@ -265,7 +277,7 @@ public class AggregateMojo extends BaseDependencyCheckMojo { */ @Override public String getName(Locale locale) { - return "dependency-check:aggregate"; + return name; } /** 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 1f67556cb..0a0fe288f 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 @@ -26,7 +26,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.io.OutputStream; import java.util.List; import java.util.Locale; import org.apache.maven.artifact.Artifact; @@ -106,16 +105,16 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma * is true. */ @SuppressWarnings("CanBeFinal") - @Parameter(property = "autoupdate", defaultValue = "true", required = true) - private boolean autoUpdate = true; + @Parameter(property = "autoupdate") + private Boolean autoUpdate; /** * Generate aggregate reports in multi-module projects. * * @deprecated use the aggregate goal instead */ - @Parameter(property = "aggregate", defaultValue = "false") + @Parameter(property = "aggregate") @Deprecated - private boolean aggregate; + 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. @@ -139,74 +138,106 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma /** * The Connection Timeout. */ - @SuppressWarnings("CanBeFinal") @Parameter(property = "connectionTimeout", defaultValue = "", required = false) - private String connectionTimeout = null; + private String connectionTimeout; /** * The path to the suppression file. */ - @SuppressWarnings("CanBeFinal") @Parameter(property = "suppressionFile", defaultValue = "", required = false) - private String suppressionFile = null; + private String suppressionFile; /** * Flag indicating whether or not to show a summary in the output. */ - @SuppressWarnings("CanBeFinal") @Parameter(property = "showSummary", defaultValue = "true", required = false) private boolean showSummary = true; /** * Whether or not the Jar Analyzer is enabled. */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "jarAnalyzerEnabled", defaultValue = "true", required = false) - private boolean jarAnalyzerEnabled = true; + @Parameter(property = "jarAnalyzerEnabled", required = false) + private Boolean jarAnalyzerEnabled; /** * Whether or not the Archive Analyzer is enabled. */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "archiveAnalyzerEnabled", defaultValue = "true", required = false) - private boolean archiveAnalyzerEnabled = true; + @Parameter(property = "archiveAnalyzerEnabled", required = false) + private Boolean archiveAnalyzerEnabled; + + /** + * Sets whether the Python Distribution Analyzer will be used. + */ + @Parameter(property = "pyDistributionAnalyzerEnabled", required = false) + private Boolean pyDistributionAnalyzerEnabled; + /** + * Sets whether the Python Package Analyzer will be used. + */ + @Parameter(property = "pyPackageAnalyzerEnabled", required = false) + private Boolean pyPackageAnalyzerEnabled; + /** + * Sets whether the Ruby Gemspec Analyzer will be used. + */ + @Parameter(property = "rubygemsAnalyzerEnabled", required = false) + private Boolean rubygemsAnalyzerEnabled; + /** + * Sets whether or not the openssl Analyzer should be used. + */ + @Parameter(property = "opensslAnalyzerEnabled", required = false) + private Boolean opensslAnalyzerEnabled; + /** + * Sets whether or not the CMake Analyzer should be used. + */ + @Parameter(property = "cmakeAnalyzerEnabled", required = false) + private Boolean cmakeAnalyzerEnabled; + /** + * Sets whether or not the autoconf Analyzer should be used. + */ + @Parameter(property = "autoconfAnalyzerEnabled", required = false) + private Boolean autoconfAnalyzerEnabled; + /** + * Sets whether or not the PHP Composer Lock File Analyzer should be used. + */ + @Parameter(property = "composerAnalyzerEnabled", required = false) + private Boolean composerAnalyzerEnabled; + /** + * Sets whether or not the Node.js Analyzer should be used. + */ + @Parameter(property = "nodeAnalyzerEnabled", required = false) + private Boolean nodeAnalyzerEnabled; /** * Whether or not the .NET Assembly Analyzer is enabled. */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "assemblyAnalyzerEnabled", defaultValue = "true", required = false) - private boolean assemblyAnalyzerEnabled = true; + @Parameter(property = "assemblyAnalyzerEnabled", required = false) + private Boolean assemblyAnalyzerEnabled; /** * Whether or not the .NET Nuspec Analyzer is enabled. */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "nuspecAnalyzerEnabled", defaultValue = "true", required = false) - private boolean nuspecAnalyzerEnabled = true; + @Parameter(property = "nuspecAnalyzerEnabled", required = false) + private Boolean nuspecAnalyzerEnabled; /** * Whether or not the Central Analyzer is enabled. */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "centralAnalyzerEnabled", defaultValue = "true", required = false) - private boolean centralAnalyzerEnabled = true; + @Parameter(property = "centralAnalyzerEnabled", required = false) + private Boolean centralAnalyzerEnabled; /** * Whether or not the Nexus Analyzer is enabled. */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "nexusAnalyzerEnabled", defaultValue = "true", required = false) - private boolean nexusAnalyzerEnabled = true; + @Parameter(property = "nexusAnalyzerEnabled", required = false) + private Boolean nexusAnalyzerEnabled; /** * The URL of a Nexus server's REST API end point (http://domain/nexus/service/local). */ - @Parameter(property = "nexusUrl", defaultValue = "", required = false) + @Parameter(property = "nexusUrl", required = false) private String nexusUrl; /** * Whether or not the configured proxy is used to connect to Nexus. */ - @Parameter(property = "nexusUsesProxy", defaultValue = "true", required = false) - private boolean nexusUsesProxy = true; + @Parameter(property = "nexusUsesProxy", required = false) + private Boolean nexusUsesProxy; /** * The database connection string. */ @@ -246,6 +277,12 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma */ @Parameter(property = "zipExtensions", required = false) private String zipExtensions; + /** + * Skip Dependency Check altogether. + */ + @SuppressWarnings("CanBeFinal") + @Parameter(property = "dependency-check.skip", defaultValue = "false", required = false) + private boolean skip = false; /** * Skip Analysis for Test Scope Dependencies. */ @@ -289,6 +326,11 @@ 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. + */ + @Parameter(property = "cveValidForHours", defaultValue = "", required = false) + private Integer cveValidForHours; /** * The path to mono for .NET Assembly analysis on non-windows systems. @@ -325,9 +367,13 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma */ @Override public void execute() throws MojoExecutionException, MojoFailureException { - validateAggregate(); - project.setContextValue(getOutputDirectoryContextKey(), this.outputDirectory); - runCheck(); + if (skip) { + getLog().info("Skipping " + getName(Locale.US)); + } else { + validateAggregate(); + project.setContextValue(getOutputDirectoryContextKey(), this.outputDirectory); + runCheck(); + } } /** @@ -337,7 +383,7 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma * @throws MojoExecutionException thrown if aggregate is set to true */ private void validateAggregate() throws MojoExecutionException { - if (aggregate) { + if (aggregate != null && aggregate) { final String msg = "Aggregate configuration detected - as of dependency-check 1.2.8 this no longer supported. " + "Please use the aggregate goal instead."; throw new MojoExecutionException(msg); @@ -583,8 +629,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma } } } + Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate); - Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); if (externalReport != null) { getLog().warn("The 'externalReport' option was set; this configuration option has been removed. " + "Please update the dependency-check-maven plugin's configuration"); @@ -599,85 +645,49 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma Settings.setString(Settings.KEYS.PROXY_PORT, Integer.toString(proxy.getPort())); final String userName = proxy.getUsername(); final String password = proxy.getPassword(); - if (userName != null) { - Settings.setString(Settings.KEYS.PROXY_USERNAME, userName); - } - if (password != null) { - Settings.setString(Settings.KEYS.PROXY_PASSWORD, password); - } - + Settings.setStringIfNotNull(Settings.KEYS.PROXY_USERNAME, userName); + Settings.setStringIfNotNull(Settings.KEYS.PROXY_PASSWORD, password); } - if (connectionTimeout != null && !connectionTimeout.isEmpty()) { - Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); - } - if (suppressionFile != null && !suppressionFile.isEmpty()) { - Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); - } + Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); + Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); //File Type Analyzer Settings - //JAR ANALYZER - Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled); - //NUSPEC ANALYZER - Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled); - //NEXUS ANALYZER - Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled); - //NEXUS ANALYZER - Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled); - if (nexusUrl != null && !nexusUrl.isEmpty()) { - Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); - } - Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy); - //ARCHIVE ANALYZER - Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled); - if (zipExtensions != null && !zipExtensions.isEmpty()) { - Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions); - } - //ASSEMBLY ANALYZER - Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled); - if (pathToMono != null && !pathToMono.isEmpty()) { - Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); - } + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled); + Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled); + Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions); + Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); + + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, rubygemsAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled); + Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled); //Database configuration - if (databaseDriverName != null && !databaseDriverName.isEmpty()) { - Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); - } - if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) { - Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); - } - if (connectionString != null && !connectionString.isEmpty()) { - Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString); - } - if (databaseUser != null && !databaseUser.isEmpty()) { - Settings.setString(Settings.KEYS.DB_USER, databaseUser); - } - if (databasePassword != null && !databasePassword.isEmpty()) { - Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword); - } - // Data Directory - if (dataDirectory != null && !dataDirectory.isEmpty()) { - Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory); - } + Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser); + Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword); - // Scope Exclusion - Settings.setBoolean(Settings.KEYS.SKIP_TEST_SCOPE, skipTestScope); - Settings.setBoolean(Settings.KEYS.SKIP_RUNTIME_SCOPE, skipRuntimeScope); - Settings.setBoolean(Settings.KEYS.SKIP_PROVIDED_SCOPE, skipProvidedScope); + Settings.setStringIfNotEmpty(Settings.KEYS.DATA_DIRECTORY, dataDirectory); + + Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified); + Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified); + Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base); + Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base); + Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours); - // CVE Data Mirroring - if (cveUrl12Modified != null && !cveUrl12Modified.isEmpty()) { - Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified); - } - if (cveUrl20Modified != null && !cveUrl20Modified.isEmpty()) { - Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified); - } - if (cveUrl12Base != null && !cveUrl12Base.isEmpty()) { - Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base); - } - if (cveUrl20Base != null && !cveUrl20Base.isEmpty()) { - Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base); - } } /** @@ -918,20 +928,11 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma parent.getAbsolutePath())); } - OutputStream os = null; - OutputStream bos = null; ObjectOutputStream out = null; try { if (dependencies != null) { - os = new FileOutputStream(file); - bos = new BufferedOutputStream(os); - out = new ObjectOutputStream(bos); + out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file))); out.writeObject(dependencies); - out.flush(); - - //call reset to prevent resource leaks per - //https://www.securecoding.cert.org/confluence/display/java/SER10-J.+Avoid+memory+and+resource+leaks+during+serialization - out.reset(); } if (getLog().isDebugEnabled()) { getLog().debug(String.format("Serialized data file written to '%s' for %s, referenced by key %s", @@ -954,24 +955,6 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma } } } - if (bos != null) { - try { - bos.close(); - } catch (IOException ex) { - if (getLog().isDebugEnabled()) { - getLog().debug("ignore", ex); - } - } - } - if (os != null) { - try { - os.close(); - } catch (IOException ex) { - if (getLog().isDebugEnabled()) { - getLog().debug("ignore", ex); - } - } - } } } } diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java index 21b0b70f0..f3197a31a 100644 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java +++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java @@ -23,6 +23,7 @@ import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.owasp.dependencycheck.data.nvdcve.DatabaseException; import org.owasp.dependencycheck.utils.Settings; @@ -34,7 +35,7 @@ import org.owasp.dependencycheck.utils.Settings; */ @Mojo( name = "check", - defaultPhase = LifecyclePhase.COMPILE, + defaultPhase = LifecyclePhase.VERIFY, threadSafe = true, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, requiresOnline = true @@ -89,6 +90,13 @@ public class CheckMojo extends BaseDependencyCheckMojo { Settings.cleanup(); } + /** + * The name of the report in the site. + */ + @SuppressWarnings("CanBeFinal") + @Parameter(property = "name", defaultValue = "dependency-check", required = true) + private String name = "dependency-check"; + /** * Returns the report name. * @@ -97,7 +105,7 @@ public class CheckMojo extends BaseDependencyCheckMojo { */ @Override public String getName(Locale locale) { - return "dependency-check"; + return name; } /** diff --git a/dependency-check-maven/src/site/markdown/configuration.md b/dependency-check-maven/src/site/markdown/configuration.md index 7bc6afcd7..31ad3484f 100644 --- a/dependency-check-maven/src/site/markdown/configuration.md +++ b/dependency-check-maven/src/site/markdown/configuration.md @@ -14,15 +14,17 @@ The following properties can be set on the dependency-check-maven plugin. Property | Description | Default Value ---------------------|------------------------------------|------------------ -aggregate | Deprecated - use the aggregate goal instead. |   autoUpdate | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. | true -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' +cveValidForHours | Sets the number of hours to wait before checking for new updates from the NVD. | 4 failBuildOnCVSS | Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail. | 11 format | The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the Site plugin unless the externalReport is set to true. | HTML -suppressionFile | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html) |   -skipTestScope | Should be skip analysis for artifacts with Test Scope | true +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 +skipRuntimeScope | Should be 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) |   Analyzer Configuration ==================== @@ -32,18 +34,26 @@ Note, that specific analyzers will automatically disable themselves if no file types that they support are detected - so specifically disabling them may not be needed. -Property | Description | Default Value -------------------------|---------------------------------------------------------------------------|------------------ -archiveAnalyzerEnabled | Sets whether the Archive Analyzer will be used. | true -zipExtensions | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. |   -jarAnalyzer | Sets whether Jar Analyzer will be used. | true -centralAnalyzerEnabled | Sets whether Central Analyzer will be used. If this analyzer is being disabled there is a good chance you also want to disable the Nexus Analyzer (see below). | true -nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. This analyzer is superceded by the Central Analyzer; however, you can configure this to run against a Nexus Pro installation. | true -nexusUrl | Defines the Nexus Server's web service end point (example http://domain.enterprise/service/local/). If not set the Nexus Analyzer will be disabled. |   -nexusUsesProxy | Whether or not the defined proxy should be used when connecting to Nexus. | true -nuspecAnalyzerEnabled | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | true -assemblyAnalyzerEnabled | Sets whether or not the .NET Assembly Analyzer should be used. | true -pathToMono | The path to Mono for .NET assembly analysis on non-windows systems. |   +Property | Description | Default Value +------------------------------|---------------------------------------------------------------------------|------------------ +archiveAnalyzerEnabled | Sets whether the Archive Analyzer will be used. | true +zipExtensions | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. |   +jarAnalyzer | Sets whether Jar Analyzer will be used. | true +centralAnalyzerEnabled | Sets whether Central Analyzer will be used. If this analyzer is being disabled there is a good chance you also want to disable the Nexus Analyzer (see below). | true +nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. This analyzer is superceded by the Central Analyzer; however, you can configure this to run against a Nexus Pro installation. | true +nexusUrl | Defines the Nexus Server's web service end point (example http://domain.enterprise/service/local/). If not set the Nexus Analyzer will be disabled. |   +nexusUsesProxy | Whether or not the defined proxy should be used when connecting to Nexus. | true +pyDistributionAnalyzerEnabled | Sets whether the Python Distribution Analyzer will be used. | true +pyPackageAnalyzerEnabled | Sets whether the Python Package Analyzer will be used. | true +rubygemsAnalyzerEnabled | Sets whether the Ruby Gemspec Analyzer will be used. | true +opensslAnalyzerEnabled | Sets whether or not the openssl Analyzer should be used. | true +cmakeAnalyzerEnabled | Sets whether or not the CMake Analyzer should be used. | true +autoconfAnalyzerEnabled | Sets whether or not the autoconf Analyzer should be used. | true +composerAnalyzerEnabled | Sets whether or not the PHP Composer Lock File Analyzer should be used. | true +nodeAnalyzerEnabled | Sets whether or not the Node.js Analyzer should be used. | true +nuspecAnalyzerEnabled | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | true +assemblyAnalyzerEnabled | Sets whether or not the .NET Assembly Analyzer should be used. | true +pathToMono | The path to Mono for .NET assembly analysis on non-windows systems. |   Advanced Configuration ==================== @@ -52,10 +62,10 @@ may be the cvedUrl properties, which can be used to host a mirror of the NVD wit Property | Description | Default Value ---------------------|---------------------------------------------------------------------------------------------|------------------ -cveUrl12Modified | URL for the modified CVE 1.2. | http://nvd.nist.gov/download/nvdcve-modified.xml -cveUrl20Modified | URL for the modified CVE 2.0. | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml -cveUrl12Base | Base URL for each year's CVE 1.2, the %d will be replaced with the year. | http://nvd.nist.gov/download/nvdcve-%d.xml -cveUrl20Base | Base URL for each year's CVE 2.0, the %d will be replaced with the year. | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml +cveUrl12Modified | URL for the modified CVE 1.2. | https://nvd.nist.gov/download/nvdcve-Modified.xml.gz +cveUrl20Modified | URL for the modified CVE 2.0. | https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-Modified.xml.gz +cveUrl12Base | Base URL for each year's CVE 1.2, the %d will be replaced with the year. | https://nvd.nist.gov/download/nvdcve-%d.xml.gz +cveUrl20Base | Base URL for each year's CVE 2.0, the %d will be replaced with the year. | https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz connectionTimeout | Sets the URL Connection Timeout used when downloading external data. |   dataDirectory | Sets the data directory to hold SQL CVEs contents. This should generally not be changed. |   databaseDriverName | The name of the database driver. Example: org.h2.Driver. |   diff --git a/dependency-check-maven/src/test/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.java b/dependency-check-maven/src/test/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.java index 4a025fda1..f66e34939 100644 --- a/dependency-check-maven/src/test/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.java +++ b/dependency-check-maven/src/test/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.java @@ -51,7 +51,7 @@ public class BaseDependencyCheckMojoTest extends BaseTest { */ public boolean canRun() { String version = System.getProperty("java.version"); - int length = version.indexOf(".", version.indexOf(".") + 1); + int length = version.indexOf('.', version.indexOf('.') + 1); version = version.substring(0, length); double v = Double.parseDouble(version); diff --git a/dependency-check-utils/pom.xml b/dependency-check-utils/pom.xml index 4e1f1ce52..33b781909 100644 --- a/dependency-check-utils/pom.xml +++ b/dependency-check-utils/pom.xml @@ -21,7 +21,7 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved. org.owasp dependency-check-parent - 1.3.1 + 1.3.2-SNAPSHOT dependency-check-utils diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Checksum.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Checksum.java index 97b254e80..62c0bf4ad 100644 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Checksum.java +++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Checksum.java @@ -57,7 +57,6 @@ public final class Checksum { * @throws IOException when the file does not exist * @throws NoSuchAlgorithmException when an algorithm is specified that does not exist */ - @SuppressWarnings("empty-statement") public static byte[] getChecksum(String algorithm, File file) throws NoSuchAlgorithmException, IOException { MessageDigest digest = MessageDigest.getInstance(algorithm); FileInputStream fis = null; @@ -79,12 +78,6 @@ public final class Checksum { digest.update(byteBuffer); start += amountToRead; } - -// BufferedInputStream bis = new BufferedInputStream(fis); -// DigestInputStream dis = new DigestInputStream(bis, digest); -// //yes, we are reading in a buffer for performance reasons - 1 byte at a time is SLOW -// byte[] buffer = new byte[8192]; -// while (dis.read(buffer) != -1); } finally { if (fis != null) { try { diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java index b066bb884..84fa670c0 100644 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java +++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java @@ -17,6 +17,7 @@ */ package org.owasp.dependencycheck.utils; +import org.apache.commons.io.FilenameUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -58,12 +59,8 @@ public final class FileUtils { * @return the file extension. */ public static String getFileExtension(String fileName) { - String ret = null; - final int pos = fileName.lastIndexOf("."); - if (pos >= 0) { - ret = fileName.substring(pos + 1, fileName.length()).toLowerCase(); - } - return ret; + final String fileExt = FilenameUtils.getExtension(fileName); + return null == fileExt || fileExt.isEmpty() ? null : fileExt.toLowerCase(); } /** @@ -73,9 +70,8 @@ public final class FileUtils { * @return true if the file was deleted successfully, otherwise false */ public static boolean delete(File file) { - boolean success = true; - if (!org.apache.commons.io.FileUtils.deleteQuietly(file)) { - success = false; + final boolean success = org.apache.commons.io.FileUtils.deleteQuietly(file); + if (!success) { LOGGER.debug("Failed to delete file: {}; attempting to delete on exit.", file.getPath()); file.deleteOnExit(); } 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 5edec7187..2cabc9b87 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 @@ -117,6 +117,10 @@ public final class Settings { * The properties key for the URL to retrieve the recently modified and added CVE entries (last 8 days). */ public static final String CVE_MODIFIED_VALID_FOR_DAYS = "cve.url.modified.validfordays"; + /** + * The properties key to control the skipping of the check for CVE updates. + */ + public static final String CVE_CHECK_VALID_FOR_HOURS = "cve.check.validforhours"; /** * The properties key for the telling us how many cve.url.* URLs exists. This is used in combination with CVE_BASE_URL to * be able to retrieve the URLs for all of the files that make up the NVD CVE listing. @@ -236,7 +240,7 @@ public final class Settings { /** * The properties key for using the proxy to reach Nexus. */ - public static final String ANALYZER_NEXUS_PROXY = "analyzer.nexus.proxy"; + public static final String ANALYZER_NEXUS_USES_PROXY = "analyzer.nexus.proxy"; /** * The properties key for whether the Central analyzer is enabled. */ @@ -261,19 +265,6 @@ public final class Settings { * The additional configured zip file extensions, if available. */ public static final String ADDITIONAL_ZIP_EXTENSIONS = "extensions.zip"; - /** - * The properties key for whether Test Scope dependencies should be skipped. - */ - public static final String SKIP_TEST_SCOPE = "skip.test.scope"; - /** - * The properties key for whether Runtime Scope dependencies should be skipped. - */ - public static final String SKIP_RUNTIME_SCOPE = "skip.runtime.scope"; - /** - * The properties key for whether Provided Scope dependencies should be skipped. - */ - public static final String SKIP_PROVIDED_SCOPE = "skip.provided.scope"; - /** * The key to obtain the path to the VFEED data file. */ @@ -461,6 +452,30 @@ public final class Settings { LOGGER.debug("Setting: {}='{}'", key, value); } + /** + * Sets a property value only if the value is not null. + * + * @param key the key for the property + * @param value the value for the property + */ + public static void setStringIfNotNull(String key, String value) { + if (null != value) { + setString(key, value); + } + } + + /** + * Sets a property value only if the value is not null and not empty. + * + * @param key the key for the property + * @param value the value for the property + */ + public static void setStringIfNotEmpty(String key, String value) { + if (null != value && !value.isEmpty()) { + setString(key, value); + } + } + /** * Sets a property value. * @@ -468,14 +483,44 @@ public final class Settings { * @param value the value for the property */ public static void setBoolean(String key, boolean value) { - if (value) { - localSettings.get().props.setProperty(key, Boolean.TRUE.toString()); - } else { - localSettings.get().props.setProperty(key, Boolean.FALSE.toString()); + setString(key, Boolean.toString(value)); + } + + /** + * Sets a property value only if the value is not null. + * + * @param key the key for the property + * @param value the value for the property + */ + public static void setBooleanIfNotNull(String key, Boolean value) { + if (null != value) { + setBoolean(key, value); } + } + + /** + * Sets a property value. + * + * @param key the key for the property + * @param value the value for the property + */ + public static void setInt(String key, int value) { + localSettings.get().props.setProperty(key, String.valueOf(value)); LOGGER.debug("Setting: {}='{}'", key, value); } + /** + * Sets a property value only if the value is not null. + * + * @param key the key for the property + * @param value the value for the property + */ + public static void setIntIfNotNull(String key, Integer value) { + if (null != value) { + setInt(key, value); + } + } + /** * Merges a new properties file into the current properties. This method allows for the loading of a user provided properties * file.

@@ -672,13 +717,11 @@ public final class Settings { * @throws InvalidSettingException is thrown if there is an error retrieving the setting */ public static int getInt(String key) throws InvalidSettingException { - int value; try { - value = Integer.parseInt(Settings.getString(key)); + return Integer.parseInt(Settings.getString(key)); } catch (NumberFormatException ex) { throw new InvalidSettingException("Could not convert property '" + key + "' to an int.", ex); } - return value; } /** @@ -712,13 +755,11 @@ public final class Settings { * @throws InvalidSettingException is thrown if there is an error retrieving the setting */ public static long getLong(String key) throws InvalidSettingException { - long value; try { - value = Long.parseLong(Settings.getString(key)); + return Long.parseLong(Settings.getString(key)); } catch (NumberFormatException ex) { - throw new InvalidSettingException("Could not convert property '" + key + "' to an int.", ex); + throw new InvalidSettingException("Could not convert property '" + key + "' to a long.", ex); } - return value; } /** @@ -731,13 +772,7 @@ public final class Settings { * @throws InvalidSettingException is thrown if there is an error retrieving the setting */ public static boolean getBoolean(String key) throws InvalidSettingException { - boolean value; - try { - value = Boolean.parseBoolean(Settings.getString(key)); - } catch (NumberFormatException ex) { - throw new InvalidSettingException("Could not convert property '" + key + "' to an int.", ex); - } - return value; + return Boolean.parseBoolean(Settings.getString(key)); } /** @@ -751,17 +786,7 @@ public final class Settings { * @throws InvalidSettingException is thrown if there is an error retrieving the setting */ public static boolean getBoolean(String key, boolean defaultValue) throws InvalidSettingException { - boolean value; - try { - final String strValue = Settings.getString(key); - if (strValue == null) { - return defaultValue; - } - value = Boolean.parseBoolean(strValue); - } catch (NumberFormatException ex) { - throw new InvalidSettingException("Could not convert property '" + key + "' to an int.", ex); - } - return value; + return Boolean.parseBoolean(Settings.getString(key, Boolean.toString(defaultValue))); } /** diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java index 85e6457fe..c11e3ecf9 100644 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java +++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/URLConnectionFactory.java @@ -52,7 +52,6 @@ public final class URLConnectionFactory { @SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE", justification = "Just being extra safe") public static HttpURLConnection createHttpURLConnection(URL url) throws URLConnectionFailureException { HttpURLConnection conn = null; - Proxy proxy; final String proxyUrl = Settings.getString(Settings.KEYS.PROXY_SERVER); try { if (proxyUrl != null) { @@ -74,7 +73,7 @@ public final class URLConnectionFactory { Authenticator.setDefault(auth); } - proxy = new Proxy(Proxy.Type.HTTP, address); + final Proxy proxy = new Proxy(Proxy.Type.HTTP, address); conn = (HttpURLConnection) url.openConnection(proxy); } else { conn = (HttpURLConnection) url.openConnection(); diff --git a/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/FileUtilsTest.java b/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/FileUtilsTest.java index 68bb9b7e9..f6fc832b7 100644 --- a/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/FileUtilsTest.java +++ b/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/FileUtilsTest.java @@ -35,8 +35,8 @@ public class FileUtilsTest extends BaseTest { */ @Test public void testGetFileExtension() { - String[] fileName = {"something-0.9.5.jar", "lib2-1.1.js"}; - String[] expResult = {"jar", "js"}; + String[] fileName = {"something-0.9.5.jar", "lib2-1.1.js", "dir.tmp/noext"}; + String[] expResult = {"jar", "js", null}; for (int i = 0; i < fileName.length; i++) { String result = FileUtils.getFileExtension(fileName[i]); diff --git a/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/SettingsTest.java b/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/SettingsTest.java index 63caba59a..03a545816 100644 --- a/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/SettingsTest.java +++ b/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/SettingsTest.java @@ -77,6 +77,32 @@ public class SettingsTest extends BaseTest { Assert.assertEquals(expResults, value); } + /** + * Test of setStringIfNotNull method, of class Settings. + */ + @Test + public void testSetStringIfNotNull() { + String key = "nullableProperty"; + String value = "someValue"; + Settings.setString(key, value); + Settings.setStringIfNotNull(key, null); // NO-OP + String expResults = Settings.getString(key); + Assert.assertEquals(expResults, value); + } + + /** + * Test of setStringIfNotNull method, of class Settings. + */ + @Test + public void testSetStringIfNotEmpty() { + String key = "optionalProperty"; + String value = "someValue"; + Settings.setString(key, value); + Settings.setStringIfNotEmpty(key, ""); // NO-OP + String expResults = Settings.getString(key); + Assert.assertEquals(expResults, value); + } + /** * Test of getString method, of class Settings. */ diff --git a/dependency-check-utils/src/test/resources/dependencycheck.properties b/dependency-check-utils/src/test/resources/dependencycheck.properties index 6c156df32..49f47d480 100644 --- a/dependency-check-utils/src/test/resources/dependencycheck.properties +++ b/dependency-check-utils/src/test/resources/dependencycheck.properties @@ -17,7 +17,7 @@ engine.version.url=http://jeremylong.github.io/DependencyCheck/current.txt # below contains a %s then the data.directory will replace the %s. data.directory=[JAR]/data data.file_name=dc.h2.db -data.version=2.9 +data.version=3.0 data.connection_string=jdbc:h2:file:%s;FILE_LOCK=SERIALIZED;AUTOCOMMIT=ON; #data.connection_string=jdbc:h2:file:%s;AUTO_SERVER=TRUE;AUTOCOMMIT=ON; #data.connection_string=jdbc:mysql://localhost:3306/dependencycheck diff --git a/pom.xml b/pom.xml index e6ea7a499..9d8a82e56 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long org.owasp dependency-check-parent - 1.3.1 + 1.3.2-SNAPSHOT pom @@ -127,9 +127,9 @@ Copyright (c) 2012 - Jeremy Long 4.7.2 - 1.7.12 + 1.7.13 1.1.3 - 2.16 + 2.17 2.7 3.5 @@ -159,7 +159,7 @@ Copyright (c) 2012 - Jeremy Long org.apache.maven.plugins maven-assembly-plugin - 2.5.5 + 2.6 org.apache.maven.plugins @@ -189,7 +189,7 @@ Copyright (c) 2012 - Jeremy Long org.apache.maven.plugins maven-failsafe-plugin - 2.18.1 + 2.19 org.apache.maven.plugins @@ -209,7 +209,7 @@ Copyright (c) 2012 - Jeremy Long org.apache.maven.plugins maven-release-plugin - 2.5.2 + 2.5.3 org.apache.maven.plugins @@ -351,6 +351,7 @@ Copyright (c) 2012 - Jeremy Long org.apache.maven.plugins maven-dependency-plugin + 2.10 org.apache.maven.plugins @@ -404,7 +405,7 @@ Copyright (c) 2012 - Jeremy Long org.apache.maven.plugins maven-surefire-report-plugin - 2.18.1 + 2.19 @@ -474,7 +475,7 @@ Copyright (c) 2012 - Jeremy Long com.google.code.findbugs annotations - 3.0.0 + 3.0.1u2 com.h2database @@ -606,7 +607,7 @@ Copyright (c) 2012 - Jeremy Long org.jmockit jmockit - 1.19 + 1.20 test @@ -640,7 +641,6 @@ Copyright (c) 2012 - Jeremy Long com.google.code.findbugs annotations - 3.0.0 provided diff --git a/src/site/markdown/data/database.md b/src/site/markdown/data/database.md index 3992d4973..b41b7fb61 100644 --- a/src/site/markdown/data/database.md +++ b/src/site/markdown/data/database.md @@ -32,6 +32,11 @@ To setup a centralized database the following generalized steps can be used: Depending on the database being used, you may need to customize the [dbStatements.properties](https://github.com/jeremylong/DependencyCheck/blob/master/dependency-check-core/src/main/resources/data/dbStatements.properties). +Alternatively to modifying the dbStatements.properties it is now possible to use a dialect file to support other databases. +See [dbStatements_h2.properties](https://github.com/jeremylong/DependencyCheck/blob/master/dependency-check-core/src/main/resources/data/dbStatements_h2.properties) +as an example. + +Also, if using an external database you will need to manually upgrade the schema. See [database upgrades](./upgrade.html) for more information. As always, feel free to open an [issue](https://github.com/jeremylong/DependencyCheck/issues) or post a question to the [dependency-check google group](https://groups.google.com/forum/#!forum/dependency-check). diff --git a/src/site/markdown/data/upgrade.md b/src/site/markdown/data/upgrade.md new file mode 100644 index 000000000..abf5f1f97 --- /dev/null +++ b/src/site/markdown/data/upgrade.md @@ -0,0 +1,8 @@ +Database Upgrades +================= +If using an external database server, such as MySQL, a DBA must manually perform +the database upgrades. Currently, a copy of the initialization and upgrade scripts +for MySQL can be found in the [github repository](https://github.com/jeremylong/DependencyCheck/tree/master/dependency-check-core/src/main/resources/data). + +If you want to use an external database other then MySQL please open an issue in our [issue tracker](https://github.com/jeremylong/DependencyCheck/issues) +as a dialect properties file will need to be created. \ No newline at end of file