merge upstream

This commit is contained in:
bjiang
2016-06-15 13:54:49 -04:00
73 changed files with 2070 additions and 836 deletions

2
.travis.yml Normal file
View File

@@ -0,0 +1,2 @@
language: java
jdk: oraclejdk7

View File

@@ -1,4 +1,4 @@
[![Build Status](https://dependency-check.ci.cloudbees.com/buildStatus/icon?job=dependency-check)](https://dependency-check.ci.cloudbees.com/job/dependency-check/)
[![Build Status](https://travis-ci.org/jeremylong/DependencyCheck.svg?branch=master)](https://travis-ci.org/jeremylong/DependencyCheck) [![Apache 2.0 License](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0.txt)
Dependency-Check
================
@@ -22,18 +22,18 @@ The latest CLI can be downloaded from bintray's
On *nix
```
$ ./bin/dependency-check.sh -h
$ ./bin/dependency-check.sh --app Testing --out . --scan [path to jar files to be scanned]
$ ./bin/dependency-check.sh --project Testing --out . --scan [path to jar files to be scanned]
```
On Windows
```
> bin/dependency-check.bat -h
> bin/dependency-check.bat --app Testing --out . --scan [path to jar files to be scanned]
> bin/dependency-check.bat --project Testing --out . --scan [path to jar files to be scanned]
```
On Mac with [Homebrew](http://brew.sh)
```
$ brew update && brew install dependency-check
$ dependency-check -h
$ dependency-check --app Testing --out . --scan [path to jar files to be scanned]
$ dependency-check --project Testing --out . --scan [path to jar files to be scanned]
```
### Maven Plugin
@@ -85,13 +85,13 @@ On *nix
```
$ mvn install
$ ./dependency-check-cli/target/release/bin/dependency-check.sh -h
$ ./dependency-check-cli/target/release/bin/dependency-check.sh --app Testing --out . --scan ./src/test/resources
$ ./dependency-check-cli/target/release/bin/dependency-check.sh --project Testing --out . --scan ./src/test/resources
```
On Windows
```
> mvn install
> dependency-check-cli/target/release/bin/dependency-check.bat -h
> dependency-check-cli/target/release/bin/dependency-check.bat --app Testing --out . --scan ./src/test/resources
> dependency-check-cli/target/release/bin/dependency-check.bat --project Testing --out . --scan ./src/test/resources
```
Then load the resulting 'DependencyCheck-Report.html' into your favorite browser.

View File

@@ -20,7 +20,7 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.3.7-SNAPSHOT</version>
<version>1.4.0-SNAPSHOT</version>
</parent>
<artifactId>dependency-check-ant</artifactId>

View File

@@ -86,8 +86,8 @@ public class Check extends Update {
}
/**
* Returns the path. If the path has not been initialized yet, this class is synchronized, and will instantiate the path
* object.
* Returns the path. If the path has not been initialized yet, this class is
* synchronized, and will instantiate the path object.
*
* @return the path
*/
@@ -109,7 +109,8 @@ public class Check extends Update {
}
/**
* Add a reference to a Path, FileSet, DirSet, or FileList defined elsewhere.
* Add a reference to a Path, FileSet, DirSet, or FileList defined
* elsewhere.
*
* @param r the reference to a path, fileset, dirset or filelist.
*/
@@ -121,7 +122,8 @@ public class Check extends Update {
}
/**
* If this is a reference, this method will add the referenced resource collection to the collection of paths.
* If this is a reference, this method will add the referenced resource
* collection to the collection of paths.
*
* @throws BuildException if the reference is not to a resource collection
*/
@@ -196,7 +198,8 @@ public class Check extends Update {
}
/**
* Specifies the destination directory for the generated Dependency-Check report.
* Specifies the destination directory for the generated Dependency-Check
* report.
*/
private String reportOutputDirectory = ".";
@@ -218,9 +221,11 @@ public class Check extends Update {
this.reportOutputDirectory = reportOutputDirectory;
}
/**
* Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which
* means since the CVSS scores are 0-10, by default the build will never fail and the CVSS score is set to 11. The valid range
* for the fail build on CVSS is 0 to 11, where anything above 10 will not cause the build to fail.
* Specifies if the build should be failed if a CVSS score above a specified
* level is identified. The default is 11 which means since the CVSS scores
* are 0-10, by default the build will never fail and the CVSS score is set
* to 11. The valid range for the fail build on CVSS is 0 to 11, where
* anything above 10 will not cause the build to fail.
*/
private float failBuildOnCVSS = 11;
@@ -242,8 +247,8 @@ public class Check extends Update {
this.failBuildOnCVSS = failBuildOnCVSS;
}
/**
* Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. Default
* is true.
* Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not
* recommended that this be turned to false. Default is true.
*/
private Boolean autoUpdate;
@@ -295,7 +300,8 @@ public class Check extends Update {
}
/**
* The report format to be generated (HTML, XML, VULN, ALL). Default is HTML.
* The report format to be generated (HTML, XML, VULN, ALL). Default is
* HTML.
*/
private String reportFormat = "HTML";
@@ -361,6 +367,29 @@ public class Check extends Update {
this.showSummary = showSummary;
}
/**
* Whether experimental analyzers are enabled.
*/
private Boolean enableExperimental;
/**
* Get the value of enableExperimental.
*
* @return the value of enableExperimental
*/
public Boolean isEnableExperimental() {
return enableExperimental;
}
/**
* Set the value of enableExperimental.
*
* @param enableExperimental new value of enableExperimental
*/
public void setEnableExperimental(Boolean enableExperimental) {
this.enableExperimental = enableExperimental;
}
/**
* Whether or not the Jar Analyzer is enabled.
*/
@@ -621,7 +650,8 @@ public class Check extends Update {
/**
* Set the value of pyDistributionAnalyzerEnabled.
*
* @param pyDistributionAnalyzerEnabled new value of pyDistributionAnalyzerEnabled
* @param pyDistributionAnalyzerEnabled new value of
* pyDistributionAnalyzerEnabled
*/
public void setPyDistributionAnalyzerEnabled(Boolean pyDistributionAnalyzerEnabled) {
this.pyDistributionAnalyzerEnabled = pyDistributionAnalyzerEnabled;
@@ -674,7 +704,8 @@ public class Check extends Update {
}
/**
* The URL of a Nexus server's REST API end point (http://domain/nexus/service/local).
* The URL of a Nexus server's REST API end point
* (http://domain/nexus/service/local).
*/
private String nexusUrl;
@@ -719,8 +750,8 @@ public class Check extends Update {
}
/**
* Additional ZIP File extensions to add analyze. This should be a comma-separated list of file extensions to treat like ZIP
* files.
* Additional ZIP File extensions to add analyze. This should be a
* comma-separated list of file extensions to treat like ZIP files.
*/
private String zipExtensions;
@@ -830,7 +861,8 @@ public class Check extends Update {
}
/**
* Validate the configuration to ensure the parameters have been properly configured/initialized.
* Validate the configuration to ensure the parameters have been properly
* configured/initialized.
*
* @throws BuildException if the task was not configured correctly.
*/
@@ -844,8 +876,9 @@ public class Check extends Update {
}
/**
* Takes the properties supplied and updates the dependency-check settings. Additionally, this sets the system properties
* required to change the proxy server, port, and connection timeout.
* Takes the properties supplied and updates the dependency-check settings.
* Additionally, this sets the system properties required to change the
* proxy server, port, and connection timeout.
*
* @throws BuildException thrown when an invalid setting is configured.
*/
@@ -854,6 +887,7 @@ public class Check extends Update {
super.populateSettings();
Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate);
Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental);
Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled);
Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled);
Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled);
@@ -875,11 +909,12 @@ public class Check extends Update {
}
/**
* Checks to see if a vulnerability has been identified with a CVSS score that is above the threshold set in the
* configuration.
* Checks to see if a vulnerability has been identified with a CVSS score
* that is above the threshold set in the configuration.
*
* @param dependencies the list of dependency objects
* @throws BuildException thrown if a CVSS score is found that is higher then the threshold set
* @throws BuildException thrown if a CVSS score is found that is higher
* then the threshold set
*/
private void checkForFailure(List<Dependency> dependencies) throws BuildException {
final StringBuilder ids = new StringBuilder();
@@ -903,7 +938,8 @@ public class Check extends Update {
}
/**
* Generates a warning message listing a summary of dependencies and their associated CPE and CVE entries.
* Generates a warning message listing a summary of dependencies and their
* associated CPE and CVE entries.
*
* @param dependencies a list of dependency objects
*/
@@ -943,7 +979,8 @@ public class Check extends Update {
}
/**
* An enumeration of supported report formats: "ALL", "HTML", "XML", "VULN", etc..
* An enumeration of supported report formats: "ALL", "HTML", "XML", "VULN",
* etc..
*/
public static class ReportFormats extends EnumeratedAttribute {

View File

@@ -23,16 +23,18 @@ import org.slf4j.ILoggerFactory;
import org.slf4j.spi.LoggerFactoryBinder;
/**
* The binding of org.slf4j.LoggerFactory class with an actual instance of org.slf4j.ILoggerFactory is performed using information
* returned by this class.
* The binding of org.slf4j.LoggerFactory class with an actual instance of
* org.slf4j.ILoggerFactory is performed using information returned by this
* class.
*
* @author colezlaw
*/
//CSOFF: FinalClass
public class StaticLoggerBinder implements LoggerFactoryBinder {
//CSON: FinalClass
/**
* The unique instance of this class
*
*/
private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
@@ -46,7 +48,8 @@ public class StaticLoggerBinder implements LoggerFactoryBinder {
}
/**
* Ant tasks have the log method we actually want to call. So we hang onto the task as a delegate
* Ant tasks have the log method we actually want to call. So we hang onto
* the task as a delegate
*/
private Task task = null;
@@ -61,16 +64,24 @@ public class StaticLoggerBinder implements LoggerFactoryBinder {
}
/**
* Declare the version of the SLF4J API this implementation is compiled against. The value of this filed is usually modified
* with each release.
* Declare the version of the SLF4J API this implementation is compiled
* against. The value of this filed is usually modified with each release.
*/
// to avoid constant folding by the compiler, this field must *not* be final
//CSOFF: StaticVariableName
//CSOFF: VisibilityModifier
public static String REQUESTED_API_VERSION = "1.7.12"; // final
//CSON: VisibilityModifier
//CSON: StaticVariableName
/**
* The logger factory class string.
*/
private static final String LOGGER_FACTORY_CLASS = AntLoggerFactory.class.getName();
/**
* The ILoggerFactory instance returned by the {@link #getLoggerFactory} method should always be the smae object
* The ILoggerFactory instance returned by the {@link #getLoggerFactory}
* method should always be the smae object
*/
private ILoggerFactory loggerFactory;

View File

@@ -27,7 +27,7 @@ the project's dependencies.
Configuration: dependency-check Task
--------------------
The following properties can be set on the dependency-check-update task.
The following properties can be set on the dependency-check task.
Property | Description | Default Value
----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------
@@ -38,11 +38,12 @@ projectName | The name of the project being scanned.
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) | &nbsp;
proxyServer | The Proxy Server. | &nbsp;
proxyServer | The Proxy Server; see the [proxy configuration](../data/proxy.html) page for more information. | &nbsp;
proxyPort | The Proxy Port. | &nbsp;
proxyUsername | Defines the proxy user name. | &nbsp;
proxyPassword | Defines the proxy password. | &nbsp;
connectionTimeout | The URL Connection Timeout. | &nbsp;
enableExperimental | Enable the [experimental analyzers](../analyzers/index.html). If not enabled the experimental analyzers (see below) will not be loaded or used. | false
Analyzer Configuration
====================
@@ -52,26 +53,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
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. | &nbsp;
jarAnalyzer | Sets whether the Jar Analyzer will be used. | true
jarAnalyzer | Sets whether the Jar Analyzer will be used. | true
centralAnalyzerEnabled | Sets whether the Central Analyzer will be used. **Disabling this analyzer is not recommended as it could lead to false negatives (e.g. libraries that have vulnerabilities may not be reported correctly).** 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 web service endpoint (example http://domain.enterprise/nexus/service/local/). If not set the Nexus Analyzer will be disabled. | &nbsp;
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. | &nbsp;
nexusUsesProxy | Whether or not the defined proxy should be used when connecting to Nexus. | true
pyDistributionAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Python Distribution Analyzer will be used. | true
pyPackageAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Python Package Analyzer will be used. | true
rubygemsAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Ruby Gemspec Analyzer will be used. | true
opensslAnalyzerEnabled | Sets whether the openssl Analyzer should be used. | true
cmakeAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) CMake Analyzer should be used. | true
autoconfAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) autoconf Analyzer should be used. | true
composerAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) PHP Composer Lock File Analyzer should be used. | true
nodeAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Node.js Analyzer should be used. | true
nuspecAnalyzerEnabled | Sets whether the .NET Nuget Nuspec Analyzer will be used. | true
assemblyAnalyzerEnabled | Sets whether the .NET Assembly Analyzer should be used. | true
pathToMono | The path to Mono for .NET assembly analysis on non-windows systems. | &nbsp;
Advanced Configuration
====================

View File

@@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.3.7-SNAPSHOT</version>
<version>1.4.0-SNAPSHOT</version>
</parent>
<artifactId>dependency-check-cli</artifactId>

View File

@@ -280,6 +280,7 @@ public class App {
final String cveBase12 = cli.getBaseCve12Url();
final String cveBase20 = cli.getBaseCve20Url();
final Integer cveValidForHours = cli.getCveValidForHours();
final boolean experimentalEnabled = cli.isExperimentalEnabled();
if (propertiesFile != null) {
try {
@@ -318,6 +319,7 @@ public class App {
Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours);
//File Type Analyzer Settings
Settings.setBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, experimentalEnabled);
Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !cli.isJarDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, !cli.isArchiveDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, !cli.isPythonDistributionDisabled());

View File

@@ -58,7 +58,8 @@ public final class CliParser {
* Parses the arguments passed in and captures the results for later use.
*
* @param args the command line arguments
* @throws FileNotFoundException is thrown when a 'file' argument does not point to a file that exists.
* @throws FileNotFoundException is thrown when a 'file' argument does not
* point to a file that exists.
* @throws ParseException is thrown when a Parse Exception occurs.
*/
public void parse(String[] args) throws FileNotFoundException, ParseException {
@@ -85,9 +86,10 @@ public final class CliParser {
/**
* Validates that the command line arguments are valid.
*
* @throws FileNotFoundException if there is a file specified by either the SCAN or CPE command line arguments that does not
* exist.
* @throws ParseException is thrown if there is an exception parsing the command line.
* @throws FileNotFoundException if there is a file specified by either the
* SCAN or CPE command line arguments that does not exist.
* @throws ParseException is thrown if there is an exception parsing the
* command line.
*/
private void validateArgs() throws FileNotFoundException, ParseException {
if (isUpdateOnly() || isRunScan()) {
@@ -141,12 +143,14 @@ public final class CliParser {
}
/**
* Validates whether or not the path(s) points at a file that exists; if the path(s) does not point to an existing file a
* FileNotFoundException is thrown.
* Validates whether or not the path(s) points at a file that exists; if the
* path(s) does not point to an existing file a FileNotFoundException is
* thrown.
*
* @param paths the paths to validate if they exists
* @param optType the option being validated (e.g. scan, out, etc.)
* @throws FileNotFoundException is thrown if one of the paths being validated does not exist.
* @throws FileNotFoundException is thrown if one of the paths being
* validated does not exist.
*/
private void validatePathExists(String[] paths, String optType) throws FileNotFoundException {
for (String path : paths) {
@@ -155,12 +159,14 @@ public final class CliParser {
}
/**
* Validates whether or not the path points at a file that exists; if the path does not point to an existing file a
* FileNotFoundException is thrown.
* Validates whether or not the path points at a file that exists; if the
* path does not point to an existing file a FileNotFoundException is
* thrown.
*
* @param path the paths to validate if they exists
* @param argumentName the argument being validated (e.g. scan, out, etc.)
* @throws FileNotFoundException is thrown if the path being validated does not exist.
* @throws FileNotFoundException is thrown if the path being validated does
* not exist.
*/
private void validatePathExists(String path, String argumentName) throws FileNotFoundException {
if (path == null) {
@@ -181,12 +187,10 @@ public final class CliParser {
throw new FileNotFoundException(msg);
}
}
} else {
if (!f.exists()) {
isValid = false;
final String msg = String.format("Invalid '%s' argument: '%s'", argumentName, path);
throw new FileNotFoundException(msg);
}
} else if (!f.exists()) {
isValid = false;
final String msg = String.format("Invalid '%s' argument: '%s'", argumentName, path);
throw new FileNotFoundException(msg);
}
} else if (path.startsWith("//") || path.startsWith("\\\\")) {
isValid = false;
@@ -196,7 +200,8 @@ public final class CliParser {
}
/**
* Generates an Options collection that is used to parse the command line and to display the help message.
* Generates an Options collection that is used to parse the command line
* and to display the help message.
*
* @return the command line options used for parsing the command line
*/
@@ -272,6 +277,10 @@ public final class CliParser {
.desc("The number of hours to wait before checking for new updates from the NVD.")
.build();
final Option experimentalEnabled = Option.builder().longOpt(ARGUMENT.EXPERIMENTAL)
.desc("Enables the experimental analzers.")
.build();
//This is an option group because it can be specified more then once.
final OptionGroup og = new OptionGroup();
og.addOption(path);
@@ -292,12 +301,14 @@ public final class CliParser {
.addOption(props)
.addOption(verboseLog)
.addOption(suppressionFile)
.addOption(cveValidForHours);
.addOption(cveValidForHours)
.addOption(experimentalEnabled);
}
/**
* Adds the advanced command line options to the given options collection. These are split out for purposes of being able to
* display two different help messages.
* Adds the advanced command line options to the given options collection.
* These are split out for purposes of being able to display two different
* help messages.
*
* @param options a collection of command line arguments
* @throws IllegalArgumentException thrown if there is an exception
@@ -466,8 +477,10 @@ public final class CliParser {
}
/**
* Adds the deprecated command line options to the given options collection. These are split out for purposes of not including
* them in the help message. We need to add the deprecated options so as not to break existing scripts.
* Adds the deprecated command line options to the given options collection.
* These are split out for purposes of not including them in the help
* message. We need to add the deprecated options so as not to break
* existing scripts.
*
* @param options a collection of command line arguments
* @throws IllegalArgumentException thrown if there is an exception
@@ -514,7 +527,8 @@ public final class CliParser {
}
/**
* Returns the symbolic link depth (how deeply symbolic links will be followed).
* Returns the symbolic link depth (how deeply symbolic links will be
* followed).
*
* @return the symbolic link depth
*/
@@ -534,7 +548,8 @@ public final class CliParser {
/**
* Returns true if the disableJar command line argument was specified.
*
* @return true if the disableJar command line argument was specified; otherwise false
* @return true if the disableJar command line argument was specified;
* otherwise false
*/
public boolean isJarDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_JAR);
@@ -543,7 +558,8 @@ public final class CliParser {
/**
* Returns true if the disableArchive command line argument was specified.
*
* @return true if the disableArchive command line argument was specified; otherwise false
* @return true if the disableArchive command line argument was specified;
* otherwise false
*/
public boolean isArchiveDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_ARCHIVE);
@@ -552,7 +568,8 @@ public final class CliParser {
/**
* Returns true if the disableNuspec command line argument was specified.
*
* @return true if the disableNuspec command line argument was specified; otherwise false
* @return true if the disableNuspec command line argument was specified;
* otherwise false
*/
public boolean isNuspecDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_NUSPEC);
@@ -561,16 +578,19 @@ public final class CliParser {
/**
* Returns true if the disableAssembly command line argument was specified.
*
* @return true if the disableAssembly command line argument was specified; otherwise false
* @return true if the disableAssembly command line argument was specified;
* otherwise false
*/
public boolean isAssemblyDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_ASSEMBLY);
}
/**
* Returns true if the disableBundleAudit command line argument was specified.
* Returns true if the disableBundleAudit command line argument was
* specified.
*
* @return true if the disableBundleAudit command line argument was specified; otherwise false
* @return true if the disableBundleAudit command line argument was
* specified; otherwise false
*/
public boolean isBundleAuditDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_BUNDLE_AUDIT);
@@ -579,7 +599,8 @@ public final class CliParser {
/**
* Returns true if the disablePyDist command line argument was specified.
*
* @return true if the disablePyDist command line argument was specified; otherwise false
* @return true if the disablePyDist command line argument was specified;
* otherwise false
*/
public boolean isPythonDistributionDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_DIST);
@@ -588,7 +609,8 @@ public final class CliParser {
/**
* Returns true if the disablePyPkg command line argument was specified.
*
* @return true if the disablePyPkg command line argument was specified; otherwise false
* @return true if the disablePyPkg command line argument was specified;
* otherwise false
*/
public boolean isPythonPackageDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_PKG);
@@ -597,7 +619,8 @@ public final class CliParser {
/**
* Returns whether the Ruby gemspec analyzer is disabled.
*
* @return true if the {@link ARGUMENT#DISABLE_RUBYGEMS} command line argument was specified; otherwise false
* @return true if the {@link ARGUMENT#DISABLE_RUBYGEMS} command line
* argument was specified; otherwise false
*/
public boolean isRubyGemspecDisabled() {
return (null != line) && line.hasOption(ARGUMENT.DISABLE_RUBYGEMS);
@@ -606,7 +629,8 @@ public final class CliParser {
/**
* Returns true if the disableCmake command line argument was specified.
*
* @return true if the disableCmake command line argument was specified; otherwise false
* @return true if the disableCmake command line argument was specified;
* otherwise false
*/
public boolean isCmakeDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_CMAKE);
@@ -615,7 +639,8 @@ public final class CliParser {
/**
* Returns true if the disableAutoconf command line argument was specified.
*
* @return true if the disableAutoconf command line argument was specified; otherwise false
* @return true if the disableAutoconf command line argument was specified;
* otherwise false
*/
public boolean isAutoconfDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_AUTOCONF);
@@ -624,7 +649,8 @@ public final class CliParser {
/**
* Returns true if the disableComposer command line argument was specified.
*
* @return true if the disableComposer command line argument was specified; otherwise false
* @return true if the disableComposer command line argument was specified;
* otherwise false
*/
public boolean isComposerDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_COMPOSER);
@@ -633,7 +659,8 @@ public final class CliParser {
/**
* Returns true if the disableNexus command line argument was specified.
*
* @return true if the disableNexus command line argument was specified; otherwise false
* @return true if the disableNexus command line argument was specified;
* otherwise false
*/
public boolean isNexusDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS);
@@ -642,7 +669,8 @@ public final class CliParser {
/**
* Returns true if the disableOpenSSL command line argument was specified.
*
* @return true if the disableOpenSSL command line argument was specified; otherwise false
* @return true if the disableOpenSSL command line argument was specified;
* otherwise false
*/
public boolean isOpenSSLDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_OPENSSL);
@@ -651,7 +679,8 @@ public final class CliParser {
/**
* Returns true if the disableNodeJS command line argument was specified.
*
* @return true if the disableNodeJS command line argument was specified; otherwise false
* @return true if the disableNodeJS command line argument was specified;
* otherwise false
*/
public boolean isNodeJsDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_NODE_JS);
@@ -660,7 +689,8 @@ public final class CliParser {
/**
* Returns true if the disableCentral command line argument was specified.
*
* @return true if the disableCentral command line argument was specified; otherwise false
* @return true if the disableCentral command line argument was specified;
* otherwise false
*/
public boolean isCentralDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_CENTRAL);
@@ -669,7 +699,8 @@ public final class CliParser {
/**
* Returns the url to the nexus server if one was specified.
*
* @return the url to the nexus server; if none was specified this will return null;
* @return the url to the nexus server; if none was specified this will
* return null;
*/
public String getNexusUrl() {
if (line == null || !line.hasOption(ARGUMENT.NEXUS_URL)) {
@@ -680,9 +711,11 @@ public final class CliParser {
}
/**
* Returns true if the Nexus Analyzer should use the configured proxy to connect to Nexus; otherwise false is returned.
* Returns true if the Nexus Analyzer should use the configured proxy to
* connect to Nexus; otherwise false is returned.
*
* @return true if the Nexus Analyzer should use the configured proxy to connect to Nexus; otherwise false
* @return true if the Nexus Analyzer should use the configured proxy to
* connect to Nexus; otherwise false
*/
public boolean isNexusUsesProxy() {
// If they didn't specify whether Nexus needs to use the proxy, we should
@@ -722,7 +755,8 @@ public final class CliParser {
}
/**
* Retrieves the file command line parameter(s) specified for the 'scan' argument.
* Retrieves the file command line parameter(s) specified for the 'scan'
* argument.
*
* @return the file paths specified on the command line for scan
*/
@@ -731,7 +765,8 @@ public final class CliParser {
}
/**
* Retrieves the list of excluded file patterns specified by the 'exclude' argument.
* Retrieves the list of excluded file patterns specified by the 'exclude'
* argument.
*
* @return the excluded file patterns
*/
@@ -740,7 +775,8 @@ public final class CliParser {
}
/**
* Returns the directory to write the reports to specified on the command line.
* Returns the directory to write the reports to specified on the command
* line.
*
* @return the path to the reports directory.
*/
@@ -749,7 +785,8 @@ public final class CliParser {
}
/**
* Returns the path to Mono for .NET Assembly analysis on non-windows systems.
* Returns the path to Mono for .NET Assembly analysis on non-windows
* systems.
*
* @return the path to Mono
*/
@@ -767,7 +804,8 @@ public final class CliParser {
}
/**
* Returns the output format specified on the command line. Defaults to HTML if no format was specified.
* Returns the output format specified on the command line. Defaults to HTML
* if no format was specified.
*
* @return the output format name.
*/
@@ -934,9 +972,11 @@ public final class CliParser {
}
/**
* Checks if the auto update feature has been disabled. If it has been disabled via the command line this will return false.
* Checks if the auto update feature has been disabled. If it has been
* disabled via the command line this will return false.
*
* @return <code>true</code> if auto-update is allowed; otherwise <code>false</code>
* @return <code>true</code> if auto-update is allowed; otherwise
* <code>false</code>
*/
public boolean isAutoUpdate() {
return line != null && !line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE);
@@ -945,7 +985,8 @@ public final class CliParser {
/**
* Checks if the update only flag has been set.
*
* @return <code>true</code> if the update only flag has been set; otherwise <code>false</code>.
* @return <code>true</code> if the update only flag has been set; otherwise
* <code>false</code>.
*/
public boolean isUpdateOnly() {
return line != null && line.hasOption(ARGUMENT.UPDATE_ONLY);
@@ -954,14 +995,16 @@ public final class CliParser {
/**
* Checks if the purge NVD flag has been set.
*
* @return <code>true</code> if the purge nvd flag has been set; otherwise <code>false</code>.
* @return <code>true</code> if the purge nvd flag has been set; otherwise
* <code>false</code>.
*/
public boolean isPurge() {
return line != null && line.hasOption(ARGUMENT.PURGE_NVD);
}
/**
* Returns the database driver name if specified; otherwise null is returned.
* Returns the database driver name if specified; otherwise null is
* returned.
*
* @return the database driver name if specified; otherwise null is returned
*/
@@ -970,7 +1013,8 @@ public final class CliParser {
}
/**
* Returns the database driver path if specified; otherwise null is returned.
* Returns the database driver path if specified; otherwise null is
* returned.
*
* @return the database driver name if specified; otherwise null is returned
*/
@@ -979,34 +1023,41 @@ public final class CliParser {
}
/**
* Returns the database connection string if specified; otherwise null is returned.
* Returns the database connection string if specified; otherwise null is
* returned.
*
* @return the database connection string if specified; otherwise null is returned
* @return the database connection string if specified; otherwise null is
* returned
*/
public String getConnectionString() {
return line.getOptionValue(ARGUMENT.CONNECTION_STRING);
}
/**
* Returns the database database user name if specified; otherwise null is returned.
* Returns the database database user name if specified; otherwise null is
* returned.
*
* @return the database database user name if specified; otherwise null is returned
* @return the database database user name if specified; otherwise null is
* returned
*/
public String getDatabaseUser() {
return line.getOptionValue(ARGUMENT.DB_NAME);
}
/**
* Returns the database database password if specified; otherwise null is returned.
* Returns the database database password if specified; otherwise null is
* returned.
*
* @return the database database password if specified; otherwise null is returned
* @return the database database password if specified; otherwise null is
* returned
*/
public String getDatabasePassword() {
return line.getOptionValue(ARGUMENT.DB_PASSWORD);
}
/**
* Returns the additional Extensions if specified; otherwise null is returned.
* Returns the additional Extensions if specified; otherwise null is
* returned.
*
* @return the additional Extensions; otherwise null is returned
*/
@@ -1028,7 +1079,17 @@ public final class CliParser {
}
/**
* A collection of static final strings that represent the possible command line arguments.
* Returns true if the experimental analyzers are enabled.
*
* @return true if the experimental analyzers are enabled; otherwise false
*/
public boolean isExperimentalEnabled() {
return line.hasOption(ARGUMENT.EXPERIMENTAL);
}
/**
* A collection of static final strings that represent the possible command
* line arguments.
*/
public static class ARGUMENT {
@@ -1041,50 +1102,61 @@ public final class CliParser {
*/
public static final String SCAN_SHORT = "s";
/**
* The long CLI argument name specifying that the CPE/CVE/etc. data should not be automatically updated.
* The long CLI argument name specifying that the CPE/CVE/etc. data
* should not be automatically updated.
*/
public static final String DISABLE_AUTO_UPDATE = "noupdate";
/**
* The short CLI argument name specifying that the CPE/CVE/etc. data should not be automatically updated.
* The short CLI argument name specifying that the CPE/CVE/etc. data
* should not be automatically updated.
*/
public static final String DISABLE_AUTO_UPDATE_SHORT = "n";
/**
* The long CLI argument name specifying that only the update phase should be executed; no scan should be run.
* The long CLI argument name specifying that only the update phase
* should be executed; no scan should be run.
*/
public static final String UPDATE_ONLY = "updateonly";
/**
* The long CLI argument name specifying that only the update phase should be executed; no scan should be run.
* The long CLI argument name specifying that only the update phase
* should be executed; no scan should be run.
*/
public static final String PURGE_NVD = "purge";
/**
* The long CLI argument name specifying the directory to write the reports to.
* The long CLI argument name specifying the directory to write the
* reports to.
*/
public static final String OUT = "out";
/**
* The short CLI argument name specifying the directory to write the reports to.
* The short CLI argument name specifying the directory to write the
* reports to.
*/
public static final String OUT_SHORT = "o";
/**
* The long CLI argument name specifying the output format to write the reports to.
* The long CLI argument name specifying the output format to write the
* reports to.
*/
public static final String OUTPUT_FORMAT = "format";
/**
* The short CLI argument name specifying the output format to write the reports to.
* The short CLI argument name specifying the output format to write the
* reports to.
*/
public static final String OUTPUT_FORMAT_SHORT = "f";
/**
* The long CLI argument name specifying the name of the project to be scanned.
* The long CLI argument name specifying the name of the project to be
* scanned.
*/
public static final String PROJECT = "project";
/**
* The long CLI argument name specifying the name of the application to be scanned.
* The long CLI argument name specifying the name of the application to
* be scanned.
*
* @deprecated project should be used instead
*/
@Deprecated
public static final String APP_NAME = "app";
/**
* The short CLI argument name specifying the name of the application to be scanned.
* The short CLI argument name specifying the name of the application to
* be scanned.
*
* @deprecated project should be used instead
*/
@@ -1142,11 +1214,13 @@ public final class CliParser {
*/
public static final String CONNECTION_TIMEOUT = "connectiontimeout";
/**
* The short CLI argument name for setting the location of an additional properties file.
* The short CLI argument name for setting the location of an additional
* properties file.
*/
public static final String PROP_SHORT = "P";
/**
* The CLI argument name for setting the location of an additional properties file.
* The CLI argument name for setting the location of an additional
* properties file.
*/
public static final String PROP = "propertyfile";
/**
@@ -1170,7 +1244,8 @@ public final class CliParser {
*/
public static final String CVE_BASE_20 = "cveUrl20Base";
/**
* The short CLI argument name for setting the location of the data directory.
* The short CLI argument name for setting the location of the data
* directory.
*/
public static final String DATA_DIRECTORY_SHORT = "d";
/**
@@ -1178,20 +1253,24 @@ public final class CliParser {
*/
public static final String VERBOSE_LOG = "log";
/**
* The short CLI argument name for setting the location of the data directory.
* The short CLI argument name for setting the location of the data
* directory.
*/
public static final String VERBOSE_LOG_SHORT = "l";
/**
* The CLI argument name for setting the depth of symbolic links that will be followed.
* The CLI argument name for setting the depth of symbolic links that
* will be followed.
*/
public static final String SYM_LINK_DEPTH = "symLink";
/**
* The CLI argument name for setting the location of the suppression file.
* The CLI argument name for setting the location of the suppression
* file.
*/
public static final String SUPPRESSION_FILE = "suppression";
/**
* The CLI argument name for setting the location of the suppression file.
* The CLI argument name for setting the location of the suppression
* file.
*/
public static final String CVE_VALID_FOR_HOURS = "cveValidForHours";
/**
@@ -1259,7 +1338,8 @@ public final class CliParser {
*/
public static final String NEXUS_URL = "nexus";
/**
* Whether or not the defined proxy should be used when connecting to Nexus.
* Whether or not the defined proxy should be used when connecting to
* Nexus.
*/
public static final String NEXUS_USES_PROXY = "nexusUsesProxy";
/**
@@ -1279,11 +1359,13 @@ public final class CliParser {
*/
public static final String DB_DRIVER = "dbDriverName";
/**
* The CLI argument name for setting the path to the database driver; in case it is not on the class path.
* The CLI argument name for setting the path to the database driver; in
* case it is not on the class path.
*/
public static final String DB_DRIVER_PATH = "dbDriverPath";
/**
* The CLI argument name for setting the path to mono for .NET Assembly analysis on non-windows systems.
* The CLI argument name for setting the path to mono for .NET Assembly
* analysis on non-windows systems.
*/
public static final String PATH_TO_MONO = "mono";
/**
@@ -1295,8 +1377,13 @@ public final class CliParser {
*/
public static final String EXCLUDE = "exclude";
/**
* The CLI argument name for setting the path to bundle-audit for Ruby bundle analysis.
* The CLI argument name for setting the path to bundle-audit for Ruby
* bundle analysis.
*/
public static final String PATH_TO_BUNDLE_AUDIT = "bundleAudit";
/**
* The CLI argument to enable the experimental analyzers.
*/
private static final String EXPERIMENTAL = "enableExperimental";
}
}

View File

@@ -18,7 +18,7 @@ Short | Argument&nbsp;Name&nbsp;&nbsp; | Parameter | Description | Requir
| \-\-advancedHelp | | Print the advanced help message. | Optional
\-v | \-\-version | | Print the version information. | Optional
| \-\-cveValidForHours | \<hours\> | The number of hours to wait before checking for new updates from the NVD. The default is 4 hours. | Optional
| \-\-experimental | | Enable the [experimental analyzers](../analyzers/index.html). If not set the analyzers marked as experimental below will not be loaded or used. | Optional
Advanced Options
================
@@ -30,18 +30,18 @@ Short | Argument&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Paramete
| \-\-cveUrl20Base | \<url\> | 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 | \<file\> | Specifies a file that contains properties to use instead of applicaion defaults. | &nbsp;
| \-\-updateonly | | If set only the update phase of dependency-check will be executed; no scan will be executed and no report will be generated. | &nbsp;
| \-\-disablePyDist | | Sets whether the Python Distribution Analyzer will be used. | false
| \-\-disablePyPkg | | Sets whether the Python Package Analyzer will be used. | false
| \-\-disableNodeJS | | Sets whether the Node.js Package Analyzer will be used. | false
| \-\-disableRubygems | | Sets whether the Ruby Gemspec Analyzer will be used. | false
| \-\-disableBundleAudit | | Sets whether the Ruby Bundler Audit Analyzer will be used. | false
| \-\-disableAutoconf | | Sets whether the Autoconf Analyzer will be used. | false
| \-\-disablePyDist | | Sets whether the [experimental](../analyzers/index.html) Python Distribution Analyzer will be used. | false
| \-\-disablePyPkg | | Sets whether the [experimental](../analyzers/index.html) Python Package Analyzer will be used. | false
| \-\-disableNodeJS | | Sets whether the [experimental](../analyzers/index.html) Node.js Package Analyzer will be used. | false
| \-\-disableRubygems | | Sets whether the [experimental](../analyzers/index.html) Ruby Gemspec Analyzer will be used. | false
| \-\-disableBundleAudit | | Sets whether the [experimental](../analyzers/index.html) Ruby Bundler Audit Analyzer will be used. | false
| \-\-disableAutoconf | | Sets whether the [experimental](../analyzers/index.html) Autoconf Analyzer will be used. | false
| \-\-disableOpenSSL | | Sets whether the OpenSSL Analyzer will be used. | false
| \-\-disableCmake | | Sets whether the Cmake Analyzer will be disabled. | false
| \-\-disableCmake | | Sets whether the [experimental](../analyzers/index.html) Cmake Analyzer will be disabled. | false
| \-\-disableArchive | | Sets whether the Archive Analyzer will be disabled. | false
| \-\-zipExtensions | \<strings\> | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. | &nbsp;
| \-\-disableJar | | Sets whether the Jar Analyzer will be disabled. | false
| \-\-disableComposer | | Sets whether the PHP Composer Lock File Analyzer will be disabled. | false
| \-\-disableComposer | | Sets whether the [experimental](../analyzers/index.html) PHP Composer Lock File Analyzer will be disabled. | false
| \-\-disableCentral | | Sets whether the Central Analyzer will be used. **Disabling this analyzer is not recommended as it could lead to false negatives (e.g. libraries that have vulnerabilities may not be reported correctly).** If this analyzer is being disabled there is a good chance you also want to disable the Nexus Analyzer. | false
| \-\-disableNexus | | Sets whether the Nexus Analyzer will be used. Note, this has been superceded by the Central Analyzer. However, you can configure the Nexus URL to utilize an internally hosted Nexus Pro server. | false
| \-\-nexus | \<url\> | The url to the Nexus Server's web service end point (example: http://domain.enterprise/nexus/service/local/). If not set the Nexus Analyzer will be disabled. | &nbsp;
@@ -50,7 +50,7 @@ Short | Argument&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Paramete
| \-\-disableAssembly | | Sets whether or not the .NET Assembly Analyzer should be used. | false
| \-\-mono | \<path\> | The path to Mono for .NET Assembly analysis on non-windows systems. | &nbsp;
| \-\-bundleAudit | | The path to the bundle-audit executable. | &nbsp;
| \-\-proxyserver | \<server\> | The proxy server to use when downloading resources. | &nbsp;
| \-\-proxyserver | \<server\> | The proxy server to use when downloading resources; see the [proxy configuration](../data/proxy.html) page for more information. | &nbsp;
| \-\-proxyport | \<port\> | The proxy port to use when downloading resources. | &nbsp;
| \-\-connectiontimeout | \<timeout\> | The connection timeout (in milliseconds) to use when downloading resources. | &nbsp;
| \-\-proxypass | \<pass\> | The proxy password to use when downloading resources. | &nbsp;

View File

@@ -20,7 +20,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.3.7-SNAPSHOT</version>
<version>1.4.0-SNAPSHOT</version>
</parent>
<artifactId>dependency-check-core</artifactId>
@@ -83,9 +83,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</testResource>
<testResource>
<directory>${basedir}/src/test/resources</directory>
<excludes>
<exclude>**/mysql-connector-java-5.1.27-bin.jar</exclude>
</excludes>
<filtering>false</filtering>
</testResource>
</testResources>

View File

@@ -126,9 +126,8 @@ public class Engine implements FileFilter {
}
final AnalyzerService service = new AnalyzerService(serviceClassLoader);
final Iterator<Analyzer> iterator = service.getAnalyzers();
while (iterator.hasNext()) {
final Analyzer a = iterator.next();
final List<Analyzer> iterator = service.getAnalyzers();
for (Analyzer a : iterator) {
analyzers.get(a.getAnalysisPhase()).add(a);
if (a instanceof FileTypeAnalyzer) {
this.fileTypeAnalyzers.add((FileTypeAnalyzer) a);

View File

@@ -24,7 +24,6 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.regex.Pattern;
import org.owasp.dependencycheck.suppression.SuppressionParseException;
import org.owasp.dependencycheck.suppression.SuppressionParser;
@@ -38,7 +37,8 @@ import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
/**
* Abstract base suppression analyzer that contains methods for parsing the suppression xml file.
* Abstract base suppression analyzer that contains methods for parsing the
* suppression xml file.
*
* @author Jeremy Long
*/
@@ -173,7 +173,8 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
*
* @param message the exception message
* @param exception the cause of the exception
* @throws SuppressionParseException throws the generated SuppressionParseException
* @throws SuppressionParseException throws the generated
* SuppressionParseException
*/
private void throwSuppressionParseException(String message, Exception exception) throws SuppressionParseException {
LOGGER.warn(message);

View File

@@ -17,8 +17,13 @@
*/
package org.owasp.dependencycheck.analyzer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ServiceLoader;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.LoggerFactory;
/**
* The Analyzer Service Loader. This class loads all services that implement
@@ -27,11 +32,15 @@ import java.util.ServiceLoader;
* @author Jeremy Long
*/
public class AnalyzerService {
/**
* The Logger for use throughout the class.
*/
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(AnalyzerService.class);
/**
* The service loader for analyzers.
*/
private final ServiceLoader<Analyzer> loader;
private final ServiceLoader<Analyzer> service;
/**
* Creates a new instance of AnalyzerService.
@@ -39,15 +48,31 @@ public class AnalyzerService {
* @param classLoader the ClassLoader to use when dynamically loading Analyzer and Update services
*/
public AnalyzerService(ClassLoader classLoader) {
loader = ServiceLoader.load(Analyzer.class, classLoader);
service = ServiceLoader.load(Analyzer.class, classLoader);
}
/**
* Returns an Iterator for all instances of the Analyzer interface.
* Returns a list of all instances of the Analyzer interface.
*
* @return an iterator of Analyzers.
* @return a list of Analyzers.
*/
public Iterator<Analyzer> getAnalyzers() {
return loader.iterator();
public List<Analyzer> getAnalyzers() {
final List<Analyzer> analyzers = new ArrayList<Analyzer>();
final Iterator<Analyzer> iterator = service.iterator();
boolean experimentalEnabled = false;
try {
experimentalEnabled = Settings.getBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, false);
} catch (InvalidSettingException ex) {
LOGGER.error("invalide experimental setting", ex);
}
while (iterator.hasNext()) {
final Analyzer a = iterator.next();
if (!experimentalEnabled && a.getClass().isAnnotationPresent(Experimental.class)) {
continue;
}
LOGGER.debug("Loaded Analyzer {}", a.getName());
analyzers.add(a);
}
return analyzers;
}
}

View File

@@ -43,6 +43,7 @@ import java.util.regex.Pattern;
* @author Dale Visser
* @see <a href="https://www.gnu.org/software/autoconf/">Autoconf - GNU Project - Free Software Foundation (FSF)</a>
*/
@Experimental
public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
/**

View File

@@ -50,6 +50,7 @@ import java.util.regex.Pattern;
*
* @author Dale Visser
*/
@Experimental
public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
/**

View File

@@ -51,8 +51,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* CPEAnalyzer is a utility class that takes a project dependency and attempts to discern if there is an associated CPE. It uses
* the evidence contained within the dependency to search the Lucene index.
* CPEAnalyzer is a utility class that takes a project dependency and attempts
* to discern if there is an associated CPE. It uses the evidence contained
* within the dependency to search the Lucene index.
*
* @author Jeremy Long
*/
@@ -71,15 +72,18 @@ public class CPEAnalyzer implements Analyzer {
*/
static final String WEIGHTING_BOOST = "^5";
/**
* A string representation of a regular expression defining characters utilized within the CPE Names.
* A string representation of a regular expression defining characters
* utilized within the CPE Names.
*/
static final String CLEANSE_CHARACTER_RX = "[^A-Za-z0-9 ._-]";
/**
* A string representation of a regular expression used to remove all but alpha characters.
* A string representation of a regular expression used to remove all but
* alpha characters.
*/
static final String CLEANSE_NONALPHA_RX = "[^A-Za-z]*";
/**
* The additional size to add to a new StringBuilder to account for extra data that will be written into the string.
* The additional size to add to a new StringBuilder to account for extra
* data that will be written into the string.
*/
static final int STRING_BUILDER_BUFFER = 20;
/**
@@ -129,9 +133,10 @@ public class CPEAnalyzer implements Analyzer {
/**
* Opens the data source.
*
* @throws IOException when the Lucene directory to be queried does not exist or is corrupt.
* @throws DatabaseException when the database throws an exception. This usually occurs when the database is in use by another
* process.
* @throws IOException when the Lucene directory to be queried does not
* exist or is corrupt.
* @throws DatabaseException when the database throws an exception. This
* usually occurs when the database is in use by another process.
*/
public void open() throws IOException, DatabaseException {
if (!isOpen()) {
@@ -170,8 +175,9 @@ public class CPEAnalyzer implements Analyzer {
}
/**
* Searches the data store of CPE entries, trying to identify the CPE for the given dependency based on the evidence contained
* within. The dependency passed in is updated with any identified CPE values.
* Searches the data store of CPE entries, trying to identify the CPE for
* the given dependency based on the evidence contained within. The
* dependency passed in is updated with any identified CPE values.
*
* @param dependency the dependency to search for CPE entries on.
* @throws CorruptIndexException is thrown when the Lucene index is corrupt.
@@ -192,8 +198,8 @@ public class CPEAnalyzer implements Analyzer {
LOGGER.debug("product search: {}", products);
}
if (!vendors.isEmpty() && !products.isEmpty()) {
final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getProductEvidence().getWeighting(),
dependency.getVendorEvidence().getWeighting());
final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getVendorEvidence().getWeighting(),
dependency.getProductEvidence().getWeighting());
if (entries == null) {
continue;
}
@@ -215,9 +221,10 @@ public class CPEAnalyzer implements Analyzer {
}
/**
* Returns the text created by concatenating the text and the values from the EvidenceCollection (filtered for a specific
* confidence). This attempts to prevent duplicate terms from being added.<br/<br/> Note, if the evidence is longer then 200
* characters it will be truncated.
* Returns the text created by concatenating the text and the values from
* the EvidenceCollection (filtered for a specific confidence). This
* attempts to prevent duplicate terms from being added.<br/<br/> Note, if
* the evidence is longer then 200 characters it will be truncated.
*
* @param text the base text.
* @param ec an EvidenceCollection
@@ -248,17 +255,19 @@ public class CPEAnalyzer implements Analyzer {
/**
* <p>
* Searches the Lucene CPE index to identify possible CPE entries associated with the supplied vendor, product, and
* version.</p>
* Searches the Lucene CPE index to identify possible CPE entries associated
* with the supplied vendor, product, and version.</p>
*
* <p>
* If either the vendorWeightings or productWeightings lists have been populated this data is used to add weighting factors to
* the search.</p>
* If either the vendorWeightings or productWeightings lists have been
* populated this data is used to add weighting factors to the search.</p>
*
* @param vendor the text used to search the vendor field
* @param product the text used to search the product field
* @param vendorWeightings a list of strings to use to add weighting factors to the vendor field
* @param productWeightings Adds a list of strings that will be used to add weighting factors to the product search
* @param vendorWeightings a list of strings to use to add weighting factors
* to the vendor field
* @param productWeightings Adds a list of strings that will be used to add
* weighting factors to the product search
* @return a list of possible CPE values
*/
protected List<IndexEntry> searchCPE(String vendor, String product,
@@ -297,16 +306,20 @@ public class CPEAnalyzer implements Analyzer {
/**
* <p>
* Builds a Lucene search string by properly escaping data and constructing a valid search query.</p>
* Builds a Lucene search string by properly escaping data and constructing
* a valid search query.</p>
*
* <p>
* If either the possibleVendor or possibleProducts lists have been populated this data is used to add weighting factors to
* the search string generated.</p>
* If either the possibleVendor or possibleProducts lists have been
* populated this data is used to add weighting factors to the search string
* generated.</p>
*
* @param vendor text to search the vendor field
* @param product text to search the product field
* @param vendorWeighting a list of strings to apply to the vendor to boost the terms weight
* @param productWeightings a list of strings to apply to the product to boost the terms weight
* @param vendorWeighting a list of strings to apply to the vendor to boost
* the terms weight
* @param productWeightings a list of strings to apply to the product to
* boost the terms weight
* @return the Lucene query
*/
protected String buildSearch(String vendor, String product,
@@ -327,13 +340,17 @@ public class CPEAnalyzer implements Analyzer {
}
/**
* This method constructs a Lucene query for a given field. The searchText is split into separate words and if the word is
* within the list of weighted words then an additional weighting is applied to the term as it is appended into the query.
* This method constructs a Lucene query for a given field. The searchText
* is split into separate words and if the word is within the list of
* weighted words then an additional weighting is applied to the term as it
* is appended into the query.
*
* @param sb a StringBuilder that the query text will be appended to.
* @param field the field within the Lucene index that the query is searching.
* @param field the field within the Lucene index that the query is
* searching.
* @param searchText text used to construct the query.
* @param weightedText a list of terms that will be considered higher importance when searching.
* @param weightedText a list of terms that will be considered higher
* importance when searching.
* @return if the append was successful.
*/
private boolean appendWeightedSearch(StringBuilder sb, String field, String searchText, Set<String> weightedText) {
@@ -379,7 +396,8 @@ public class CPEAnalyzer implements Analyzer {
}
/**
* Removes characters from the input text that are not used within the CPE index.
* Removes characters from the input text that are not used within the CPE
* index.
*
* @param text is the text to remove the characters from.
* @return the text having removed some characters.
@@ -389,7 +407,8 @@ public class CPEAnalyzer implements Analyzer {
}
/**
* Compares two strings after lower casing them and removing the non-alpha characters.
* Compares two strings after lower casing them and removing the non-alpha
* characters.
*
* @param l string one to compare.
* @param r string two to compare.
@@ -406,8 +425,9 @@ public class CPEAnalyzer implements Analyzer {
}
/**
* Ensures that the CPE Identified matches the dependency. This validates that the product, vendor, and version information
* for the CPE are contained within the dependencies evidence.
* Ensures that the CPE Identified matches the dependency. This validates
* that the product, vendor, and version information for the CPE are
* contained within the dependencies evidence.
*
* @param entry a CPE entry.
* @param dependency the dependency that the CPE entries could be for.
@@ -474,11 +494,13 @@ public class CPEAnalyzer implements Analyzer {
}
/**
* Analyzes a dependency and attempts to determine if there are any CPE identifiers for this dependency.
* Analyzes a dependency and attempts to determine if there are any CPE
* identifiers for this dependency.
*
* @param dependency The Dependency to analyze.
* @param engine The analysis engine
* @throws AnalysisException is thrown if there is an issue analyzing the dependency.
* @throws AnalysisException is thrown if there is an issue analyzing the
* dependency.
*/
@Override
public synchronized void analyze(Dependency dependency, Engine engine) throws AnalysisException {
@@ -494,15 +516,19 @@ public class CPEAnalyzer implements Analyzer {
}
/**
* Retrieves a list of CPE values from the CveDB based on the vendor and product passed in. The list is then validated to find
* only CPEs that are valid for the given dependency. It is possible that the CPE identified is a best effort "guess" based on
* the vendor, product, and version information.
* Retrieves a list of CPE values from the CveDB based on the vendor and
* product passed in. The list is then validated to find only CPEs that are
* valid for the given dependency. It is possible that the CPE identified is
* a best effort "guess" based on the vendor, product, and version
* information.
*
* @param dependency the Dependency being analyzed
* @param vendor the vendor for the CPE being analyzed
* @param product the product for the CPE being analyzed
* @param currentConfidence the current confidence being used during analysis
* @return <code>true</code> if an identifier was added to the dependency; otherwise <code>false</code>
* @param currentConfidence the current confidence being used during
* analysis
* @return <code>true</code> if an identifier was added to the dependency;
* otherwise <code>false</code>
* @throws UnsupportedEncodingException is thrown if UTF-8 is not supported
*/
protected boolean determineIdentifiers(Dependency dependency, String vendor, String product,
@@ -512,10 +538,11 @@ public class CPEAnalyzer implements Analyzer {
Confidence bestGuessConf = null;
boolean hasBroadMatch = false;
final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>();
//TODO the following algorithm incorrectly identifies things as a lower version
// if there lower confidence evidence when the current (highest) version number
// is newer then anything in the NVD.
for (Confidence conf : Confidence.values()) {
// if (conf.compareTo(currentConfidence) > 0) {
// break;
// }
for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) {
final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue());
if (evVer == null) {
@@ -537,15 +564,13 @@ public class CPEAnalyzer implements Analyzer {
final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8"));
final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf);
collected.add(match);
} else {
//TODO the following isn't quite right is it? need to think about this guessing game a bit more.
if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size()
&& evVer.matchesAtLeastThreeLevels(dbVer)) {
if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) {
if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) {
bestGuess = dbVer;
bestGuessConf = conf;
}
} else //TODO the following isn't quite right is it? need to think about this guessing game a bit more.
if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size()
&& evVer.matchesAtLeastThreeLevels(dbVer)) {
if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) {
if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) {
bestGuess = dbVer;
bestGuessConf = conf;
}
}
}
@@ -604,14 +629,16 @@ public class CPEAnalyzer implements Analyzer {
*/
BEST_GUESS,
/**
* The entire vendor/product group must be added (without a guess at version) because there is a CVE with a VS that only
* specifies vendor/product.
* The entire vendor/product group must be added (without a guess at
* version) because there is a CVE with a VS that only specifies
* vendor/product.
*/
BROAD_MATCH
}
/**
* A simple object to hold an identifier and carry information about the confidence in the identifier.
* A simple object to hold an identifier and carry information about the
* confidence in the identifier.
*/
private static class IdentifierMatch implements Comparable<IdentifierMatch> {
@@ -621,8 +648,10 @@ public class CPEAnalyzer implements Analyzer {
* @param type the type of identifier (such as CPE)
* @param value the value of the identifier
* @param url the URL of the identifier
* @param identifierConfidence the confidence in the identifier: best guess or exact match
* @param evidenceConfidence the confidence of the evidence used to find the identifier
* @param identifierConfidence the confidence in the identifier: best
* guess or exact match
* @param evidenceConfidence the confidence of the evidence used to find
* the identifier
*/
IdentifierMatch(String type, String value, String url, IdentifierConfidence identifierConfidence, Confidence evidenceConfidence) {
this.identifier = new Identifier(type, value, url);
@@ -753,7 +782,8 @@ public class CPEAnalyzer implements Analyzer {
//</editor-fold>
/**
* Standard implementation of compareTo that compares identifier confidence, evidence confidence, and then the identifier.
* Standard implementation of compareTo that compares identifier
* confidence, evidence confidence, and then the identifier.
*
* @param o the IdentifierMatch to compare to
* @return the natural ordering of IdentifierMatch

View File

@@ -41,6 +41,7 @@ import java.security.MessageDigest;
*
* @author colezlaw
*/
@Experimental
public class ComposerLockAnalyzer extends AbstractFileTypeAnalyzer {
/**

View File

@@ -35,11 +35,14 @@ import org.slf4j.LoggerFactory;
/**
* <p>
* This analyzer ensures dependencies that should be grouped together, to remove excess noise from the report, are grouped. An
* example would be Spring, Spring Beans, Spring MVC, etc. If they are all for the same version and have the same relative path
* then these should be grouped into a single dependency under the core/main library.</p>
* This analyzer ensures dependencies that should be grouped together, to remove
* excess noise from the report, are grouped. An example would be Spring, Spring
* Beans, Spring MVC, etc. If they are all for the same version and have the
* same relative path then these should be grouped into a single dependency
* under the core/main library.</p>
* <p>
* Note, this grouping only works on dependencies with identified CVE entries</p>
* Note, this grouping only works on dependencies with identified CVE
* entries</p>
*
* @author Jeremy Long
*/
@@ -92,12 +95,14 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
//</editor-fold>
/**
* Analyzes a set of dependencies. If they have been found to have the same base path and the same set of identifiers they are
* likely related. The related dependencies are bundled into a single reportable item.
* Analyzes a set of dependencies. If they have been found to have the same
* base path and the same set of identifiers they are likely related. The
* related dependencies are bundled into a single reportable item.
*
* @param ignore this analyzer ignores the dependency being analyzed
* @param engine the engine that is scanning the dependencies
* @throws AnalysisException is thrown if there is an error reading the JAR file.
* @throws AnalysisException is thrown if there is an error reading the JAR
* file.
*/
@Override
public void analyze(Dependency ignore, Engine engine) throws AnalysisException {
@@ -167,10 +172,11 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
* Adds the relatedDependency to the dependency's related dependencies.
*
* @param dependency the main dependency
* @param relatedDependency a collection of dependencies to be removed from the main analysis loop, this is the source of
* dependencies to remove
* @param dependenciesToRemove a collection of dependencies that will be removed from the main analysis loop, this function
* adds to this collection
* @param relatedDependency a collection of dependencies to be removed from
* the main analysis loop, this is the source of dependencies to remove
* @param dependenciesToRemove a collection of dependencies that will be
* removed from the main analysis loop, this function adds to this
* collection
*/
private void mergeDependencies(final Dependency dependency, final Dependency relatedDependency, final Set<Dependency> dependenciesToRemove) {
dependency.addRelatedDependency(relatedDependency);
@@ -186,7 +192,8 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
}
/**
* Attempts to trim a maven repo to a common base path. This is typically [drive]\[repo_location]\repository\[path1]\[path2].
* Attempts to trim a maven repo to a common base path. This is typically
* [drive]\[repo_location]\repository\[path1]\[path2].
*
* @param path the path to trim
* @return a string representing the base path.
@@ -211,11 +218,13 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
}
/**
* Returns true if the file names (and version if it exists) of the two dependencies are sufficiently similar.
* Returns true if the file names (and version if it exists) of the two
* dependencies are sufficiently similar.
*
* @param dependency1 a dependency2 to compare
* @param dependency2 a dependency2 to compare
* @return true if the identifiers in the two supplied dependencies are equal
* @return true if the identifiers in the two supplied dependencies are
* equal
*/
private boolean fileNameMatch(Dependency dependency1, Dependency dependency2) {
if (dependency1 == null || dependency1.getFileName() == null
@@ -243,11 +252,13 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
}
/**
* Returns true if the CPE identifiers in the two supplied dependencies are equal.
* Returns true if the CPE identifiers in the two supplied dependencies are
* equal.
*
* @param dependency1 a dependency2 to compare
* @param dependency2 a dependency2 to compare
* @return true if the identifiers in the two supplied dependencies are equal
* @return true if the identifiers in the two supplied dependencies are
* equal
*/
private boolean cpeIdentifiersMatch(Dependency dependency1, Dependency dependency2) {
if (dependency1 == null || dependency1.getIdentifiers() == null
@@ -317,37 +328,53 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
}
return false;
}
/**
* Bundling Ruby gems that are identified from different .gemspec files but denote the same package path.
* This happens when Ruby bundler installs an app's dependencies by running "bundle install".
* Bundling Ruby gems that are identified from different .gemspec files but
* denote the same package path. This happens when Ruby bundler installs an
* application's dependencies by running "bundle install".
*
* @param dependency1 dependency to compare
* @param dependency2 dependency to compare
* @return true if the the dependencies being analyzed appear to be the
* same; otherwise false
*/
private boolean isSameRubyGem(Dependency dependency1, Dependency dependency2) {
if (dependency1 == null || dependency2 == null ||
!dependency1.getFileName().endsWith(".gemspec") ||
!dependency2.getFileName().endsWith(".gemspec") ||
dependency1.getPackagePath() == null ||
dependency2.getPackagePath() == null) {
if (dependency1 == null || dependency2 == null
|| !dependency1.getFileName().endsWith(".gemspec")
|| !dependency2.getFileName().endsWith(".gemspec")
|| dependency1.getPackagePath() == null
|| dependency2.getPackagePath() == null) {
return false;
}
if (dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath()))
return true;
if (dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath())) {
return true;
}
return false;
return false;
}
/**
* Ruby gems installed by "bundle install" can have zero or more *.gemspec files, all of which have the same packagePath and should be grouped.
* If one of these gemspec is from <parent>/specifications/*.gemspec, because it is a stub with fully resolved gem meta-data
* created by Ruby bundler, this dependency should be the main one. Otherwise, use dependency2 as main.
*
* This method returns null if any dependency is not from *.gemspec, or the two do not have the same packagePath.
* In this case, they should not be grouped.
* Ruby gems installed by "bundle install" can have zero or more *.gemspec
* files, all of which have the same packagePath and should be grouped. If
* one of these gemspec is from <parent>/specifications/*.gemspec, because
* it is a stub with fully resolved gem meta-data created by Ruby bundler,
* this dependency should be the main one. Otherwise, use dependency2 as
* main.
*
* This method returns null if any dependency is not from *.gemspec, or the
* two do not have the same packagePath. In this case, they should not be
* grouped.
*
* @param dependency1 dependency to compare
* @param dependency2 dependency to compare
* @return the main dependency; or null if a gemspec is not included in the
* analysis
*/
private Dependency getMainGemspecDependency(Dependency dependency1, Dependency dependency2) {
if (isSameRubyGem(dependency1, dependency2)) {
final File lFile = dependency1.getActualFile();
File left = lFile.getParentFile();
if (isSameRubyGem(dependency1, dependency2)) {
final File lFile = dependency1.getActualFile();
final File left = lFile.getParentFile();
if (left != null && left.getName().equalsIgnoreCase("specifications")) {
return dependency1;
}
@@ -384,12 +411,13 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
}
/**
* This is likely a very broken attempt at determining if the 'left' dependency is the 'core' library in comparison to the
* 'right' library.
* This is likely a very broken attempt at determining if the 'left'
* dependency is the 'core' library in comparison to the 'right' library.
*
* @param left the dependency to test
* @param right the dependency to test against
* @return a boolean indicating whether or not the left dependency should be considered the "core" version.
* @return a boolean indicating whether or not the left dependency should be
* considered the "core" version.
*/
boolean isCore(Dependency left, Dependency right) {
final String leftName = left.getFileName().toLowerCase();
@@ -425,11 +453,13 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
}
/**
* Compares the SHA1 hashes of two dependencies to determine if they are equal.
* Compares the SHA1 hashes of two dependencies to determine if they are
* equal.
*
* @param dependency1 a dependency object to compare
* @param dependency2 a dependency object to compare
* @return true if the sha1 hashes of the two dependencies match; otherwise false
* @return true if the sha1 hashes of the two dependencies match; otherwise
* false
*/
private boolean hashesMatch(Dependency dependency1, Dependency dependency2) {
if (dependency1 == null || dependency2 == null || dependency1.getSha1sum() == null || dependency2.getSha1sum() == null) {
@@ -439,12 +469,13 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
}
/**
* Determines if the jar is shaded and the created pom.xml identified the same CPE as the jar - if so, the pom.xml dependency
* should be removed.
* Determines if the jar is shaded and the created pom.xml identified the
* same CPE as the jar - if so, the pom.xml dependency should be removed.
*
* @param dependency a dependency to check
* @param nextDependency another dependency to check
* @return true if on of the dependencies is a pom.xml and the identifiers between the two collections match; otherwise false
* @return true if on of the dependencies is a pom.xml and the identifiers
* between the two collections match; otherwise false
*/
private boolean isShadedJar(Dependency dependency, Dependency nextDependency) {
final String mainName = dependency.getFileName().toLowerCase();
@@ -458,12 +489,13 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
}
/**
* Determines which path is shortest; if path lengths are equal then we use compareTo of the string method to determine if the
* first path is smaller.
* Determines which path is shortest; if path lengths are equal then we use
* compareTo of the string method to determine if the first path is smaller.
*
* @param left the first path to compare
* @param right the second path to compare
* @return <code>true</code> if the leftPath is the shortest; otherwise <code>false</code>
* @return <code>true</code> if the leftPath is the shortest; otherwise
* <code>false</code>
*/
protected boolean firstPathIsShortest(String left, String right) {
final String leftPath = left.replace('\\', '/');

View File

@@ -0,0 +1,34 @@
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2016 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.analyzer;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation used to flag an analyzer as experimental.
*
* @author jeremy long
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Experimental {
}

View File

@@ -67,11 +67,13 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer {
}
//</editor-fold>
// Python init files
private static final NameFileFilter IGNORED_FILES = new NameFileFilter(new String[] {
/**
* Python init files
*/
private static final NameFileFilter IGNORED_FILES = new NameFileFilter(new String[]{
"__init__.py",
"__init__.pyc",
"__init__.pyo"
"__init__.pyo",
});
/**
@@ -79,7 +81,8 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer {
*
* @param dependency the dependency to analyze.
* @param engine the engine that is scanning the dependencies
* @throws AnalysisException is thrown if there is an error reading the JAR file.
* @throws AnalysisException is thrown if there is an error reading the JAR
* file.
*/
@Override
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
@@ -105,13 +108,6 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer {
fileName, Confidence.MEDIUM);
}
//add as vendor and product evidence
// if (fileName.contains("-")) {
// dependency.getProductEvidence().addEvidence("file", "name",
// fileName, Confidence.HIGHEST);
// dependency.getVendorEvidence().addEvidence("file", "name",
// fileName, Confidence.HIGHEST);
// } else
if (!IGNORED_FILES.accept(f)) {
dependency.getProductEvidence().addEvidence("file", "name",
fileName, Confidence.HIGH);

View File

@@ -29,7 +29,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -60,7 +59,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Used to load a JAR file and collect information that can be used to determine the associated CPE.
* Used to load a JAR file and collect information that can be used to determine
* the associated CPE.
*
* @author Jeremy Long
*/
@@ -72,7 +72,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
*/
private static final Logger LOGGER = LoggerFactory.getLogger(JarAnalyzer.class);
/**
* The count of directories created during analysis. This is used for creating temporary directories.
* The count of directories created during analysis. This is used for
* creating temporary directories.
*/
private static int dirCount = 0;
/**
@@ -80,7 +81,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
*/
private static final String NEWLINE = System.getProperty("line.separator");
/**
* A list of values in the manifest to ignore as they only result in false positives.
* A list of values in the manifest to ignore as they only result in false
* positives.
*/
private static final Set<String> IGNORE_VALUES = newHashSet(
"Sun Java System Application Server");
@@ -123,7 +125,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
"ipojo-extension",
"eclipse-sourcereferences");
/**
* Deprecated Jar manifest attribute, that is, nonetheless, useful for analysis.
* Deprecated Jar manifest attribute, that is, nonetheless, useful for
* analysis.
*/
@SuppressWarnings("deprecation")
private static final String IMPLEMENTATION_VENDOR_ID = Attributes.Name.IMPLEMENTATION_VENDOR_ID
@@ -203,7 +206,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
//</editor-fold>
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/
@@ -213,12 +217,13 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Loads a specified JAR file and collects information from the manifest and checksums to identify the correct CPE
* information.
* Loads a specified JAR file and collects information from the manifest and
* checksums to identify the correct CPE information.
*
* @param dependency the dependency to analyze.
* @param engine the engine that is scanning the dependencies
* @throws AnalysisException is thrown if there is an error reading the JAR file.
* @throws AnalysisException is thrown if there is an error reading the JAR
* file.
*/
@Override
public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
@@ -242,13 +247,15 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Attempts to find a pom.xml within the JAR file. If found it extracts information and adds it to the evidence. This will
* attempt to interpolate the strings contained within the pom.properties if one exists.
* Attempts to find a pom.xml within the JAR file. If found it extracts
* information and adds it to the evidence. This will attempt to interpolate
* the strings contained within the pom.properties if one exists.
*
* @param dependency the dependency being analyzed
* @param classes a collection of class name information
* @param engine the analysis engine, used to add additional dependencies
* @throws AnalysisException is thrown if there is an exception parsing the pom
* @throws AnalysisException is thrown if there is an exception parsing the
* pom
* @return whether or not evidence was added to the dependency
*/
protected boolean analyzePOM(Dependency dependency, List<ClassNameInformation> classes, Engine engine) throws AnalysisException {
@@ -329,12 +336,14 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Given a path to a pom.xml within a JarFile, this method attempts to load a sibling pom.properties if one exists.
* Given a path to a pom.xml within a JarFile, this method attempts to load
* a sibling pom.properties if one exists.
*
* @param path the path to the pom.xml within the JarFile
* @param jar the JarFile to load the pom.properties from
* @return a Properties object or null if no pom.properties was found
* @throws IOException thrown if there is an exception reading the pom.properties
* @throws IOException thrown if there is an exception reading the
* pom.properties
*/
private Properties retrievePomProperties(String path, final JarFile jar) throws IOException {
Properties pomProperties = null;
@@ -361,7 +370,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Searches a JarFile for pom.xml entries and returns a listing of these entries.
* Searches a JarFile for pom.xml entries and returns a listing of these
* entries.
*
* @param jar the JarFile to search
* @return a list of pom.xml entries
@@ -388,8 +398,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
* @param jar the jar file to extract the pom from
* @param dependency the dependency being analyzed
* @return returns the POM object
* @throws AnalysisException is thrown if there is an exception extracting or parsing the POM
* {@link org.owasp.dependencycheck.xml.pom.Model} object
* @throws AnalysisException is thrown if there is an exception extracting
* or parsing the POM {@link org.owasp.dependencycheck.xml.pom.Model} object
*/
private Model extractPom(String path, JarFile jar, Dependency dependency) throws AnalysisException {
InputStream input = null;
@@ -447,9 +457,10 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
*
* @param dependency the dependency to set data on
* @param pom the information from the pom
* @param classes a collection of ClassNameInformation - containing data about the fully qualified class names within the JAR
* file being analyzed
* @return true if there was evidence within the pom that we could use; otherwise false
* @param classes a collection of ClassNameInformation - containing data
* about the fully qualified class names within the JAR file being analyzed
* @return true if there was evidence within the pom that we could use;
* otherwise false
*/
public static boolean setPomEvidence(Dependency dependency, Model pom, List<ClassNameInformation> classes) {
boolean foundSomething = false;
@@ -565,9 +576,9 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
addMatchingValues(classes, trimmedDescription, dependency.getVendorEvidence());
addMatchingValues(classes, trimmedDescription, dependency.getProductEvidence());
}
String projectURL = pom.getProjectURL();
if(projectURL != null && !projectURL.trim().isEmpty()) {
final String projectURL = pom.getProjectURL();
if (projectURL != null && !projectURL.trim().isEmpty()) {
dependency.getVendorEvidence().addEvidence("pom", "url", projectURL, Confidence.HIGHEST);
}
@@ -576,12 +587,15 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Analyzes the path information of the classes contained within the JarAnalyzer to try and determine possible vendor or
* product names. If any are found they are stored in the packageVendor and packageProduct hashSets.
* Analyzes the path information of the classes contained within the
* JarAnalyzer to try and determine possible vendor or product names. If any
* are found they are stored in the packageVendor and packageProduct
* hashSets.
*
* @param classNames a list of class names
* @param dependency a dependency to analyze
* @param addPackagesAsEvidence a flag indicating whether or not package names should be added as evidence.
* @param addPackagesAsEvidence a flag indicating whether or not package
* names should be added as evidence.
*/
protected void analyzePackageNames(List<ClassNameInformation> classNames,
Dependency dependency, boolean addPackagesAsEvidence) {
@@ -616,11 +630,13 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
/**
* <p>
* Reads the manifest from the JAR file and collects the entries. Some vendorKey entries are:</p>
* Reads the manifest from the JAR file and collects the entries. Some
* vendorKey entries are:</p>
* <ul><li>Implementation Title</li>
* <li>Implementation Version</li> <li>Implementation Vendor</li>
* <li>Implementation VendorId</li> <li>Bundle Name</li> <li>Bundle Version</li> <li>Bundle Vendor</li> <li>Bundle
* Description</li> <li>Main Class</li> </ul>
* <li>Implementation VendorId</li> <li>Bundle Name</li> <li>Bundle
* Version</li> <li>Bundle Vendor</li> <li>Bundle Description</li> <li>Main
* Class</li> </ul>
* However, all but a handful of specific entries are read in.
*
* @param dependency A reference to the dependency
@@ -628,14 +644,15 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
* @return whether evidence was identified parsing the manifest
* @throws IOException if there is an issue reading the JAR file
*/
protected boolean parseManifest(Dependency dependency, List<ClassNameInformation> classInformation) throws IOException {
protected boolean parseManifest(Dependency dependency,
List<ClassNameInformation> classInformation)
throws IOException {
boolean foundSomething = false;
JarFile jar = null;
try {
jar = new JarFile(dependency.getActualFilePath());
final Manifest manifest = jar.getManifest();
if (manifest == null) {
//don't log this for javadoc or sources jar files
if (!dependency.getFileName().toLowerCase().endsWith("-sources.jar")
&& !dependency.getFileName().toLowerCase().endsWith("-javadoc.jar")
&& !dependency.getFileName().toLowerCase().endsWith("-src.jar")
@@ -652,7 +669,6 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
String source = "Manifest";
String specificationVersion = null;
boolean hasImplementationVersion = false;
Attributes atts = manifest.getMainAttributes();
for (Entry<Object, Object> entry : atts.entrySet()) {
String key = entry.getKey().toString();
@@ -683,7 +699,6 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
} else if (key.equalsIgnoreCase(BUNDLE_DESCRIPTION)) {
foundSomething = true;
addDescription(dependency, value, "manifest", key);
//productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
addMatchingValues(classInformation, value, productEvidence);
} else if (key.equalsIgnoreCase(BUNDLE_NAME)) {
foundSomething = true;
@@ -702,11 +717,6 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
//skipping main class as if this has important information to add
// it will be added during class name analysis... if other fields
// have the information from the class name then they will get added...
// foundSomething = true;
// productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
// vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
// addMatchingValues(classInformation, value, vendorEvidence);
// addMatchingValues(classInformation, value, productEvidence);
} else {
key = key.toLowerCase();
if (!IGNORE_KEYS.contains(key)
@@ -720,7 +730,6 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
&& !value.trim().startsWith("scm:")
&& !isImportPackage(key, value)
&& !isPackage(key, value)) {
foundSomething = true;
if (key.contains("version")) {
if (!key.contains("specification")) {
@@ -753,21 +762,19 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
addMatchingValues(classInformation, value, productEvidence);
} else if (key.contains("license")) {
addLicense(dependency, value);
} else if (key.contains("description")) {
addDescription(dependency, value, "manifest", key);
} else {
if (key.contains("description")) {
addDescription(dependency, value, "manifest", key);
} else {
productEvidence.addEvidence(source, key, value, Confidence.LOW);
vendorEvidence.addEvidence(source, key, value, Confidence.LOW);
addMatchingValues(classInformation, value, vendorEvidence);
addMatchingValues(classInformation, value, productEvidence);
if (value.matches(".*\\d.*")) {
final StringTokenizer tokenizer = new StringTokenizer(value, " ");
while (tokenizer.hasMoreElements()) {
final String s = tokenizer.nextToken();
if (s.matches("^[0-9.]+$")) {
versionEvidence.addEvidence(source, key, s, Confidence.LOW);
}
productEvidence.addEvidence(source, key, value, Confidence.LOW);
vendorEvidence.addEvidence(source, key, value, Confidence.LOW);
addMatchingValues(classInformation, value, vendorEvidence);
addMatchingValues(classInformation, value, productEvidence);
if (value.matches(".*\\d.*")) {
final StringTokenizer tokenizer = new StringTokenizer(value, " ");
while (tokenizer.hasMoreElements()) {
final String s = tokenizer.nextToken();
if (s.matches("^[0-9.]+$")) {
versionEvidence.addEvidence(source, key, s, Confidence.LOW);
}
}
}
@@ -776,11 +783,10 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
}
final Map<String, Attributes> entries = manifest.getEntries();
for (Iterator<String> it = entries.keySet().iterator(); it.hasNext();) {
final String name = it.next();
for (Map.Entry<String, Attributes> item : manifest.getEntries().entrySet()) {
final String name = item.getKey();
source = "manifest: " + name;
atts = entries.get(name);
atts = item.getValue();
for (Entry<Object, Object> entry : atts.entrySet()) {
final String key = entry.getKey().toString();
final String value = atts.getValue(key);
@@ -815,15 +821,18 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Adds a description to the given dependency. If the description contains one of the following strings beyond 100 characters,
* then the description used will be trimmed to that position:
* <ul><li>"such as"</li><li>"like "</li><li>"will use "</li><li>"* uses "</li></ul>
* Adds a description to the given dependency. If the description contains
* one of the following strings beyond 100 characters, then the description
* used will be trimmed to that position:
* <ul><li>"such as"</li><li>"like "</li><li>"will use "</li><li>"* uses
* "</li></ul>
*
* @param dependency a dependency
* @param description the description
* @param source the source of the evidence
* @param key the "name" of the evidence
* @return if the description is trimmed, the trimmed version is returned; otherwise the original description is returned
* @return if the description is trimmed, the trimmed version is returned;
* otherwise the original description is returned
*/
public static String addDescription(Dependency dependency, String description, String source, String key) {
if (dependency.getDescription() == null) {
@@ -894,7 +903,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Initializes the JarAnalyzer.
*
* @throws Exception is thrown if there is an exception creating a temporary directory
* @throws Exception is thrown if there is an exception creating a temporary
* directory
*/
@Override
public void initializeFileTypeAnalyzer() throws Exception {
@@ -925,11 +935,13 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Determines if the key value pair from the manifest is for an "import" type entry for package names.
* Determines if the key value pair from the manifest is for an "import"
* type entry for package names.
*
* @param key the key from the manifest
* @param value the value from the manifest
* @return true or false depending on if it is believed the entry is an "import" entry
* @return true or false depending on if it is believed the entry is an
* "import" entry
*/
private boolean isImportPackage(String key, String value) {
final Pattern packageRx = Pattern.compile("^([a-zA-Z0-9_#\\$\\*\\.]+\\s*[,;]\\s*)+([a-zA-Z0-9_#\\$\\*\\.]+\\s*)?$");
@@ -938,8 +950,9 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Cycles through an enumeration of JarEntries, contained within the dependency, and returns a list of the class names. This
* does not include core Java package names (i.e. java.* or javax.*).
* Cycles through an enumeration of JarEntries, contained within the
* dependency, and returns a list of the class names. This does not include
* core Java package names (i.e. java.* or javax.*).
*
* @param dependency the dependency being analyzed
* @return an list of fully qualified class names
@@ -975,12 +988,16 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Cycles through the list of class names and places the package levels 0-3 into the provided maps for vendor and product.
* This is helpful when analyzing vendor/product as many times this is included in the package name.
* Cycles through the list of class names and places the package levels 0-3
* into the provided maps for vendor and product. This is helpful when
* analyzing vendor/product as many times this is included in the package
* name.
*
* @param classNames a list of class names
* @param vendor HashMap of possible vendor names from package names (e.g. owasp)
* @param product HashMap of possible product names from package names (e.g. dependencycheck)
* @param vendor HashMap of possible vendor names from package names (e.g.
* owasp)
* @param product HashMap of possible product names from package names (e.g.
* dependencycheck)
*/
private void analyzeFullyQualifiedClassNames(List<ClassNameInformation> classNames,
Map<String, Integer> vendor, Map<String, Integer> product) {
@@ -1007,8 +1024,9 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Adds an entry to the specified collection and sets the Integer (e.g. the count) to 1. If the entry already exists in the
* collection then the Integer is incremented by 1.
* Adds an entry to the specified collection and sets the Integer (e.g. the
* count) to 1. If the entry already exists in the collection then the
* Integer is incremented by 1.
*
* @param collection a collection of strings and their occurrence count
* @param key the key to add to the collection
@@ -1022,9 +1040,10 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Cycles through the collection of class name information to see if parts of the package names are contained in the provided
* value. If found, it will be added as the HIGHEST confidence evidence because we have more then one source corroborating the
* value.
* Cycles through the collection of class name information to see if parts
* of the package names are contained in the provided value. If found, it
* will be added as the HIGHEST confidence evidence because we have more
* then one source corroborating the value.
*
* @param classes a collection of class name information
* @param value the value to check to see if it contains a package name
@@ -1047,7 +1066,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Simple check to see if the attribute from a manifest is just a package name.
* Simple check to see if the attribute from a manifest is just a package
* name.
*
* @param key the key of the value to check
* @param value the value to check
@@ -1061,7 +1081,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Extracts the license information from the pom and adds it to the dependency.
* Extracts the license information from the pom and adds it to the
* dependency.
*
* @param pom the pom object
* @param dependency the dependency to add license information too
@@ -1108,9 +1129,11 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
/**
* <p>
* Stores information about a given class name. This class will keep the fully qualified class name and a list of the
* important parts of the package structure. Up to the first four levels of the package structure are stored, excluding a
* leading "org" or "com". Example:</p>
* Stores information about a given class name. This class will keep the
* fully qualified class name and a list of the important parts of the
* package structure. Up to the first four levels of the package
* structure are stored, excluding a leading "org" or "com".
* Example:</p>
* <code>ClassNameInformation obj = new ClassNameInformation("org.owasp.dependencycheck.analyzer.JarAnalyzer");
* System.out.println(obj.getName());
* for (String p : obj.getPackageStructure())
@@ -1169,7 +1192,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
this.name = name;
}
/**
* Up to the first four levels of the package structure, excluding a leading "org" or "com".
* Up to the first four levels of the package structure, excluding a
* leading "org" or "com".
*/
private final ArrayList<String> packageStructure = new ArrayList<String>();

View File

@@ -45,6 +45,7 @@ import javax.json.JsonValue;
*
* @author Dale Visser
*/
@Experimental
public class NodePackageAnalyzer extends AbstractFileTypeAnalyzer {
/**

View File

@@ -39,6 +39,9 @@ import java.util.regex.Pattern;
*/
public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Hexadecimal.
*/
private static final int HEXADECIMAL = 16;
/**
* Filename to analyze. All other .h files get removed from consideration.
@@ -49,17 +52,47 @@ public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
* Filter that detects files named "__init__.py".
*/
private static final FileFilter OPENSSLV_FILTER = FileFilterBuilder.newInstance().addFilenames(OPENSSLV_H).build();
/**
* Open SSL Version number pattern.
*/
private static final Pattern VERSION_PATTERN = Pattern.compile(
"define\\s+OPENSSL_VERSION_NUMBER\\s+0x([0-9a-zA-Z]{8})L", Pattern.DOTALL
| Pattern.CASE_INSENSITIVE);
/**
* The offset of the major version number.
*/
private static final int MAJOR_OFFSET = 28;
/**
* The mask for the minor version number.
*/
private static final long MINOR_MASK = 0x0ff00000L;
/**
* The offset of the minor version number.
*/
private static final int MINOR_OFFSET = 20;
/**
* The max for the fix version.
*/
private static final long FIX_MASK = 0x000ff000L;
/**
* The offset for the fix version.
*/
private static final int FIX_OFFSET = 12;
/**
* The mask for the patch version.
*/
private static final long PATCH_MASK = 0x00000ff0L;
/**
* The offset for the patch version.
*/
private static final int PATCH_OFFSET = 4;
/**
* Number of letters.
*/
private static final int NUM_LETTERS = 26;
/**
* The status mask.
*/
private static final int STATUS_MASK = 0x0000000f;
/**
@@ -124,7 +157,8 @@ public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
*
* @param dependency the dependency being analyzed
* @param engine the engine being used to perform the scan
* @throws AnalysisException thrown if there is an unrecoverable error analyzing the dependency
* @throws AnalysisException thrown if there is an unrecoverable error
* analyzing the dependency
*/
@Override
protected void analyzeFileType(Dependency dependency, Engine engine)
@@ -167,6 +201,11 @@ public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
}
}
/**
* Returns the setting for the analyzer enabled setting key.
*
* @return the setting for the analyzer enabled setting key
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_OPENSSL_ENABLED;

View File

@@ -50,6 +50,7 @@ import org.owasp.dependencycheck.utils.UrlStringUtils;
*
* @author Dale Visser
*/
@Experimental
public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
/**

View File

@@ -39,10 +39,12 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Used to analyze a Python package, and collect information that can be used to determine the associated CPE.
* Used to analyze a Python package, and collect information that can be used to
* determine the associated CPE.
*
* @author Dale Visser
*/
@Experimental
public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
/**
@@ -166,7 +168,8 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
*
* @param dependency the dependency being analyzed
* @param engine the engine being used to perform the scan
* @throws AnalysisException thrown if there is an unrecoverable error analyzing the dependency
* @throws AnalysisException thrown if there is an unrecoverable error
* analyzing the dependency
*/
@Override
protected void analyzeFileType(Dependency dependency, Engine engine)
@@ -175,21 +178,20 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
final File parent = file.getParentFile();
final String parentName = parent.getName();
if (INIT_PY_FILTER.accept(file)) {
//by definition, the containing folder of __init__.py is considered the package, even the file is empty:
//"The __init__.py files are required to make Python treat the directories as containing packages"
//see section "6.4 Packages" from https://docs.python.org/2/tutorial/modules.html;
//by definition, the containing folder of __init__.py is considered the package, even the file is empty:
//"The __init__.py files are required to make Python treat the directories as containing packages"
//see section "6.4 Packages" from https://docs.python.org/2/tutorial/modules.html;
dependency.setDisplayFileName(parentName + "/__init__.py");
dependency.getProductEvidence().addEvidence(file.getName(),
"PackageName", parentName, Confidence.HIGHEST);
final File[] fileList = parent.listFiles(PY_FILTER);
if (fileList != null) {
for (final File sourceFile : fileList) {
analyzeFileContents(dependency, sourceFile);
}
}
}
else {
} else {
// copy, alter and set in case some other thread is iterating over
final List<Dependency> dependencies = new ArrayList<Dependency>(
engine.getDependencies());
@@ -199,8 +201,9 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* This should gather information from leading docstrings, file comments, and assignments to __version__, __title__,
* __summary__, __uri__, __url__, __home*page__, __author__, and their all caps equivalents.
* This should gather information from leading docstrings, file comments,
* and assignments to __version__, __title__, __summary__, __uri__, __url__,
* __home*page__, __author__, and their all caps equivalents.
*
* @param dependency the dependency being analyzed
* @param file the file name to analyze
@@ -291,7 +294,8 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Gather evidence from a Python source file using the given string assignment regex pattern.
* Gather evidence from a Python source file using the given string
* assignment regex pattern.
*
* @param pattern to scan contents with
* @param contents of Python source file

View File

@@ -27,7 +27,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
@@ -48,6 +47,7 @@ import org.slf4j.LoggerFactory;
*
* @author Dale Visser
*/
@Experimental
public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
private static final Logger LOGGER = LoggerFactory.getLogger(RubyBundleAuditAnalyzer.class);
@@ -61,17 +61,31 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
* The phase that this analyzer is intended to run in.
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_INFORMATION_COLLECTION;
private static final FileFilter FILTER
= FileFilterBuilder.newInstance().addFilenames("Gemfile.lock").build();
/**
* The filter defining which files will be analyzed.
*/
private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames("Gemfile.lock").build();
/**
* Name.
*/
public static final String NAME = "Name: ";
/**
* Version.
*/
public static final String VERSION = "Version: ";
/**
* Advisory.
*/
public static final String ADVISORY = "Advisory: ";
/**
* Criticality.
*/
public static final String CRITICALITY = "Criticality: ";
public CveDB cvedb;
//instance.open();
//Vulnerability result = instance.getVulnerability("CVE-2015-3225");
/**
* The DAL.
*/
private CveDB cvedb;
/**
* @return a filter that accepts files named Gemfile.lock
@@ -84,7 +98,10 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Launch bundle-audit.
*
* @param folder directory that contains bundle audit
* @return a handle to the process
* @throws AnalysisException thrown when there is an issue launching bundle
* audit
*/
private Process launchBundleAudit(File folder) throws AnalysisException {
if (!folder.isDirectory()) {
@@ -134,7 +151,7 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
throw ae;
}
int exitValue = process.waitFor();
final int exitValue = process.waitFor();
if (0 == exitValue) {
LOGGER.warn("Unexpected exit code from bundle-audit process. Disabling {}: {}", ANALYZER_NAME, exitValue);
setEnabled(false);
@@ -206,6 +223,13 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
*/
private boolean needToDisableGemspecAnalyzer = true;
/**
* Determines if the analyzer can analyze the given file type.
*
* @param dependency the dependency to determine if it can analyze
* @param engine the dependency-check engine
* @throws AnalysisException thrown if there is an analysis exception.
*/
@Override
protected void analyzeFileType(Dependency dependency, Engine engine)
throws AnalysisException {
@@ -213,11 +237,10 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
boolean failed = true;
final String className = RubyGemspecAnalyzer.class.getName();
for (FileTypeAnalyzer analyzer : engine.getFileTypeAnalyzers()) {
if (analyzer instanceof RubyBundlerAnalyzer) {
if (analyzer instanceof RubyBundlerAnalyzer) {
((RubyBundlerAnalyzer) analyzer).setEnabled(false);
LOGGER.info("Disabled " + RubyBundlerAnalyzer.class.getName() + " to avoid noisy duplicate results.");
}
else if (analyzer instanceof RubyGemspecAnalyzer) {
} else if (analyzer instanceof RubyGemspecAnalyzer) {
((RubyGemspecAnalyzer) analyzer).setEnabled(false);
LOGGER.info("Disabled " + className + " to avoid noisy duplicate results.");
failed = false;
@@ -236,10 +259,11 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
throw new AnalysisException("bundle-audit process interrupted", ie);
}
BufferedReader rdr = null;
BufferedReader errReader = null;
try {
BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"));
errReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"));
while (errReader.ready()) {
String error = errReader.readLine();
final String error = errReader.readLine();
LOGGER.warn(error);
}
rdr = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
@@ -247,6 +271,13 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
} catch (IOException ioe) {
LOGGER.warn("bundle-audit failure", ioe);
} finally {
if (errReader != null) {
try {
errReader.close();
} catch (IOException ioe) {
LOGGER.warn("bundle-audit close failure", ioe);
}
}
if (null != rdr) {
try {
rdr.close();
@@ -258,6 +289,14 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Processes the bundler audit output.
*
* @param original the dependency
* @param engine the dependency-check engine
* @param rdr the reader of the report
* @throws IOException thrown if the report cannot be read.
*/
private void processBundlerAuditOutput(Dependency original, Engine engine, BufferedReader rdr) throws IOException {
final String parentName = original.getActualFile().getParentFile().getName();
final String fileName = original.getFileName();
@@ -280,7 +319,7 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
dependency = map.get(gem);
LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
} else if (nextLine.startsWith(VERSION)) {
vulnerability = createVulnerability(parentName, dependency, vulnerability, gem, nextLine);
vulnerability = createVulnerability(parentName, dependency, gem, nextLine);
} else if (nextLine.startsWith(ADVISORY)) {
setVulnerabilityName(parentName, dependency, vulnerability, nextLine);
} else if (nextLine.startsWith(CRITICALITY)) {
@@ -290,7 +329,9 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
} else if (nextLine.startsWith("Description:")) {
appendToDescription = true;
if (null != vulnerability) {
vulnerability.setDescription("*** Vulnerability obtained from bundle-audit verbose report. Title link may not work. CPE below is guessed. CVSS score is estimated (-1.0 indicates unknown). See link below for full details. *** ");
vulnerability.setDescription("*** Vulnerability obtained from bundle-audit verbose report. "
+ "Title link may not work. CPE below is guessed. CVSS score is estimated (-1.0 "
+ " indicates unknown). See link below for full details. *** ");
}
} else if (appendToDescription) {
if (null != vulnerability) {
@@ -300,6 +341,14 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
}
}
/**
* Sets the vulnerability name.
*
* @param parentName the parent name
* @param dependency the dependency
* @param vulnerability the vulnerability
* @param nextLine the line to parse
*/
private void setVulnerabilityName(String parentName, Dependency dependency, Vulnerability vulnerability, String nextLine) {
final String advisory = nextLine.substring((ADVISORY.length()));
if (null != vulnerability) {
@@ -311,10 +360,17 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
}
/**
* Adds a reference to the vulnerability.
*
* @param parentName the parent name
* @param vulnerability the vulnerability
* @param nextLine the line to parse
*/
private void addReferenceToVulnerability(String parentName, Vulnerability vulnerability, String nextLine) {
final String url = nextLine.substring(("URL: ").length());
if (null != vulnerability) {
Reference ref = new Reference();
final Reference ref = new Reference();
ref.setName(vulnerability.getName());
ref.setSource("bundle-audit");
ref.setUrl(url);
@@ -323,6 +379,13 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
}
/**
* Adds the criticality to the vulnerability
*
* @param parentName the parent name
* @param vulnerability the vulnerability
* @param nextLine the line to parse
*/
private void addCriticalityToVulnerability(String parentName, Vulnerability vulnerability, String nextLine) {
if (null != vulnerability) {
final String criticality = nextLine.substring(CRITICALITY.length()).trim();
@@ -347,7 +410,17 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
}
private Vulnerability createVulnerability(String parentName, Dependency dependency, Vulnerability vulnerability, String gem, String nextLine) {
/**
* Creates a vulnerability.
*
* @param parentName the parent name
* @param dependency the dependency
* @param gem the gem name
* @param nextLine the line to parse
* @return the vulnerability
*/
private Vulnerability createVulnerability(String parentName, Dependency dependency, String gem, String nextLine) {
Vulnerability vulnerability = null;
if (null != dependency) {
final String version = nextLine.substring(VERSION.length());
dependency.getVersionEvidence().addEvidence(
@@ -370,6 +443,17 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
return vulnerability;
}
/**
* Creates the dependency based off of the gem.
*
* @param engine the engine used for scanning
* @param parentName the gem parent
* @param fileName the file name
* @param filePath the file path
* @param gem the gem name
* @return the dependency to add
* @throws IOException thrown if a temporary gem file could not be written
*/
private Dependency createDependencyForGem(Engine engine, String parentName, String fileName, String filePath, String gem) throws IOException {
final File gemFile = new File(Settings.getTempDirectory(), gem + "_Gemfile.lock");
gemFile.createNewFile();

View File

@@ -25,35 +25,43 @@ import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Dependency;
/**
* This analyzer accepts the fully resolved .gemspec created by the Ruby bundler (http://bundler.io)
* for better evidence results. It also tries to resolve the dependency packagePath
* to where the gem is actually installed. Then during {@link AnalysisPhase.PRE_FINDING_ANALYSIS}
* {@link DependencyBundlingAnalyzer} will merge two .gemspec dependencies together if
* <code>Dependency.getPackagePath()</code> are the same.
*
* Ruby bundler creates new .gemspec files under a folder called "specifications" at deploy time,
* in addition to the original .gemspec files from source. The bundler generated
* .gemspec files always contain fully resolved attributes thus provide more accurate
* evidences, whereas the original .gemspec from source often contain variables for attributes
* that can't be used for evidences.
*
* Note this analyzer share the same {@link Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED} as
* {@link RubyGemspecAnalyzer}, so it will enabled/disabled with {@link RubyGemspecAnalyzer}.
* This analyzer accepts the fully resolved .gemspec created by the Ruby bundler
* (http://bundler.io) for better evidence results. It also tries to resolve the
* dependency packagePath to where the gem is actually installed. Then during {@link org.owasp.dependencycheck.analyzer.AnalysisPhase#PRE_FINDING_ANALYSIS}
* {@link DependencyBundlingAnalyzer} will merge two .gemspec dependencies
* together if <code>Dependency.getPackagePath()</code> are the same.
*
* Ruby bundler creates new .gemspec files under a folder called
* "specifications" at deploy time, in addition to the original .gemspec files
* from source. The bundler generated .gemspec files always contain fully
* resolved attributes thus provide more accurate evidences, whereas the
* original .gemspec from source often contain variables for attributes that
* can't be used for evidences.
*
* Note this analyzer share the same
* {@link org.owasp.dependencycheck.utils.Settings.KEYS#ANALYZER_RUBY_GEMSPEC_ENABLED} as
* {@link RubyGemspecAnalyzer}, so it will enabled/disabled with
* {@link RubyGemspecAnalyzer}.
*
* @author Bianca Jiang (biancajiang@gmail.com)
*/
@Experimental
public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer {
/**
* The name of the analyzer.
*/
private static final String ANALYZER_NAME = "Ruby Bundler Analyzer";
//Folder name that contains .gemspec files created by "bundle install"
private static final String SPECIFICATIONS = "specifications";
//Folder name that contains the gems by "bundle install"
private static final String GEMS = "gems";
/**
* Folder name that contains .gemspec files created by "bundle install"
*/
private static final String SPECIFICATIONS = "specifications";
/**
* Folder name that contains the gems by "bundle install"
*/
private static final String GEMS = "gems";
/**
* Returns the name of the analyzer.
@@ -66,61 +74,66 @@ public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer {
}
/**
* Only accept *.gemspec files generated by "bundle install --deployment" under "specifications" folder.
* Only accept *.gemspec files generated by "bundle install --deployment"
* under "specifications" folder.
*
* @param pathname the path name to test
* @return true if the analyzer can process the given file; otherwise false
*/
@Override
@Override
public boolean accept(File pathname) {
boolean accepted = super.accept(pathname);
if(accepted == true) {
File parentDir = pathname.getParentFile();
accepted = parentDir != null && parentDir.getName().equals(SPECIFICATIONS);
if (accepted) {
final File parentDir = pathname.getParentFile();
accepted = parentDir != null && parentDir.getName().equals(SPECIFICATIONS);
}
return accepted;
}
@Override
@Override
protected void analyzeFileType(Dependency dependency, Engine engine)
throws AnalysisException {
super.analyzeFileType(dependency, engine);
//find the corresponding gem folder for this .gemspec stub by "bundle install --deployment"
File gemspecFile = dependency.getActualFile();
String gemFileName = gemspecFile.getName();
final File gemspecFile = dependency.getActualFile();
final String gemFileName = gemspecFile.getName();
final String gemName = gemFileName.substring(0, gemFileName.lastIndexOf(".gemspec"));
File specificationsDir = gemspecFile.getParentFile();
if(specificationsDir != null && specificationsDir.getName().equals(SPECIFICATIONS) && specificationsDir.exists()) {
File parentDir = specificationsDir.getParentFile();
if(parentDir != null && parentDir.exists()) {
File gemsDir = new File(parentDir, GEMS);
if(gemsDir != null && gemsDir.exists()) {
File[] matchingFiles = gemsDir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.equals(gemName);
}
});
if(matchingFiles.length > 0) {
String gemPath = matchingFiles[0].getAbsolutePath();
if(dependency.getActualFilePath().equals(dependency.getFilePath())) {
if(gemPath != null)
dependency.setPackagePath(gemPath);
} else {
//.gemspec's actualFilePath and filePath are different when it's from a compressed file
//in which case actualFilePath is the temp directory used by decompression.
//packagePath should use the filePath of the identified gem file in "gems" folder
File gemspecStub = new File(dependency.getFilePath());
File specDir = gemspecStub.getParentFile();
if(specDir != null && specDir.getName().equals(SPECIFICATIONS)) {
File gemsDir2 = new File(specDir.getParentFile(), GEMS);
File packageDir = new File(gemsDir2, gemName);
dependency.setPackagePath(packageDir.getAbsolutePath());
}
}
}
}
}
}
}
final File specificationsDir = gemspecFile.getParentFile();
if (specificationsDir != null && specificationsDir.getName().equals(SPECIFICATIONS) && specificationsDir.exists()) {
final File parentDir = specificationsDir.getParentFile();
if (parentDir != null && parentDir.exists()) {
final File gemsDir = new File(parentDir, GEMS);
if (gemsDir.exists()) {
final File[] matchingFiles = gemsDir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.equals(gemName);
}
});
if (matchingFiles != null && matchingFiles.length > 0) {
final String gemPath = matchingFiles[0].getAbsolutePath();
if (dependency.getActualFilePath().equals(dependency.getFilePath())) {
if (gemPath != null) {
dependency.setPackagePath(gemPath);
}
} else {
//.gemspec's actualFilePath and filePath are different when it's from a compressed file
//in which case actualFilePath is the temp directory used by decompression.
//packagePath should use the filePath of the identified gem file in "gems" folder
final File gemspecStub = new File(dependency.getFilePath());
final File specDir = gemspecStub.getParentFile();
if (specDir != null && specDir.getName().equals(SPECIFICATIONS)) {
final File gemsDir2 = new File(specDir.getParentFile(), GEMS);
final File packageDir = new File(gemsDir2, gemName);
dependency.setPackagePath(packageDir.getAbsolutePath());
}
}
}
}
}
}
}
}

View File

@@ -34,15 +34,23 @@ import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.EvidenceCollection;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Used to analyze Ruby Gem specifications and collect information that can be used to determine the associated CPE. Regular
* expressions are used to parse the well-defined Ruby syntax that forms the specification.
* Used to analyze Ruby Gem specifications and collect information that can be
* used to determine the associated CPE. Regular expressions are used to parse
* the well-defined Ruby syntax that forms the specification.
*
* @author Dale Visser
*/
@Experimental
public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(RubyGemspecAnalyzer.class);
/**
* The name of the analyzer.
*/
@@ -53,13 +61,22 @@ public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer {
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
/**
* The gemspec file extension.
*/
private static final String GEMSPEC = "gemspec";
private static final FileFilter FILTER
= FileFilterBuilder.newInstance().addExtensions(GEMSPEC).build();
//TODO: support Rakefile
//= FileFilterBuilder.newInstance().addExtensions(GEMSPEC).addFilenames("Rakefile").build();
/**
* The file filter containing the list of file extensions that can be
* analyzed.
*/
private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(GEMSPEC).build();
//TODO: support Rakefile
//= FileFilterBuilder.newInstance().addExtensions(GEMSPEC).addFilenames("Rakefile").build();
/**
* The name of the version file.
*/
private static final String VERSION_FILE_NAME = "VERSION";
/**
@@ -96,7 +113,8 @@ public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/
@@ -108,8 +126,7 @@ public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The capture group #1 is the block variable.
*/
private static final Pattern GEMSPEC_BLOCK_INIT
= Pattern.compile("Gem::Specification\\.new\\s+?do\\s+?\\|(.+?)\\|");
private static final Pattern GEMSPEC_BLOCK_INIT = Pattern.compile("Gem::Specification\\.new\\s+?do\\s+?\\|(.+?)\\|");
@Override
protected void analyzeFileType(Dependency dependency, Engine engine)
@@ -125,7 +142,7 @@ public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer {
if (matcher.find()) {
contents = contents.substring(matcher.end());
final String blockVariable = matcher.group(1);
final EvidenceCollection vendor = dependency.getVendorEvidence();
final EvidenceCollection product = dependency.getProductEvidence();
final String name = addStringEvidence(product, contents, blockVariable, "name", "name", Confidence.HIGHEST);
@@ -138,71 +155,90 @@ public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer {
addStringEvidence(vendor, contents, blockVariable, "email", "emails?", Confidence.MEDIUM);
addStringEvidence(vendor, contents, blockVariable, "homepage", "homepage", Confidence.HIGHEST);
addStringEvidence(vendor, contents, blockVariable, "license", "licen[cs]es?", Confidence.HIGHEST);
String value = addStringEvidence(dependency.getVersionEvidence(), contents, blockVariable, "version", "version", Confidence.HIGHEST);
if(value.length() < 1)
addEvidenceFromVersionFile(dependency.getActualFile(), dependency.getVersionEvidence());
final String value = addStringEvidence(dependency.getVersionEvidence(), contents,
blockVariable, "version", "version", Confidence.HIGHEST);
if (value.length() < 1) {
addEvidenceFromVersionFile(dependency.getActualFile(), dependency.getVersionEvidence());
}
}
setPackagePath(dependency);
}
/**
* Adds the specified evidence to the given evidence collection.
*
* @param evidences the collection to add the evidence to
* @param contents the evidence contents
* @param blockVariable the variable
* @param field the field
* @param fieldPattern the field pattern
* @param confidence the confidence of the evidence
* @return the evidence string value added
*/
private String addStringEvidence(EvidenceCollection evidences, String contents,
String blockVariable, String field, String fieldPattern, Confidence confidence) {
String value = "";
//capture array value between [ ]
final Matcher arrayMatcher = Pattern.compile(
//capture array value between [ ]
final Matcher arrayMatcher = Pattern.compile(
String.format("\\s*?%s\\.%s\\s*?=\\s*?\\[(.*?)\\]", blockVariable, fieldPattern), Pattern.CASE_INSENSITIVE).matcher(contents);
if(arrayMatcher.find()) {
String arrayValue = arrayMatcher.group(1);
value = arrayValue.replaceAll("['\"]", "").trim(); //strip quotes
}
//capture single value between quotes
else {
final Matcher matcher = Pattern.compile(
String.format("\\s*?%s\\.%s\\s*?=\\s*?(['\"])(.*?)\\1", blockVariable, fieldPattern), Pattern.CASE_INSENSITIVE).matcher(contents);
if (matcher.find()) {
value = matcher.group(2);
}
}
if(value.length() > 0)
evidences.addEvidence(GEMSPEC, field, value, confidence);
if (arrayMatcher.find()) {
final String arrayValue = arrayMatcher.group(1);
value = arrayValue.replaceAll("['\"]", "").trim(); //strip quotes
} else { //capture single value between quotes
final Matcher matcher = Pattern.compile(
String.format("\\s*?%s\\.%s\\s*?=\\s*?(['\"])(.*?)\\1", blockVariable, fieldPattern), Pattern.CASE_INSENSITIVE).matcher(contents);
if (matcher.find()) {
value = matcher.group(2);
}
}
if (value.length() > 0) {
evidences.addEvidence(GEMSPEC, field, value, confidence);
}
return value;
}
private String addEvidenceFromVersionFile(File dependencyFile, EvidenceCollection versionEvidences) {
String value = null;
File parentDir = dependencyFile.getParentFile();
if(parentDir != null) {
File[] matchingFiles = parentDir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.contains(VERSION_FILE_NAME);
}
});
for(int i = 0; i < matchingFiles.length; i++) {
try {
List<String> lines = FileUtils.readLines(matchingFiles[i]);
if(lines.size() == 1) { //TODO other checking?
value = lines.get(0).trim();
versionEvidences.addEvidence(GEMSPEC, "version", value, Confidence.HIGH);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
return value;
/**
* Adds evidence from the version file.
*
* @param dependencyFile the dependency being analyzed
* @param versionEvidences the version evidence
*/
private void addEvidenceFromVersionFile(File dependencyFile, EvidenceCollection versionEvidences) {
final File parentDir = dependencyFile.getParentFile();
if (parentDir != null) {
final File[] matchingFiles = parentDir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.contains(VERSION_FILE_NAME);
}
});
for (File f : matchingFiles) {
try {
final List<String> lines = FileUtils.readLines(f, Charset.defaultCharset());
if (lines.size() == 1) { //TODO other checking?
final String value = lines.get(0).trim();
versionEvidences.addEvidence(GEMSPEC, "version", value, Confidence.HIGH);
}
} catch (IOException e) {
LOGGER.debug("Error reading gemspec", e);
}
}
}
}
/**
* Sets the package path on the dependency.
*
* @param dep the dependency to alter
*/
private void setPackagePath(Dependency dep) {
File file = new File(dep.getFilePath());
String parent = file.getParent();
if(parent != null)
dep.setPackagePath(parent);
final File file = new File(dep.getFilePath());
final String parent = file.getParent();
if (parent != null) {
dep.setPackagePath(parent);
}
}
}

View File

@@ -69,10 +69,19 @@ public class CveDB {
private ResourceBundle statementBundle = null;
/**
* Creates a new CveDB object and opens the database connection. Note, the connection must be closed by the caller by calling
* the close method.
*
* @throws DatabaseException thrown if there is an exception opening the database.
* Creates a new CveDB object and opens the database
* connection. Note, the connection must be closed by the caller by calling
* the close method. ======= Does the underlying connection support batch
* operations?
*/
private boolean batchSupported;
/**
* Creates a new CveDB object and opens the database connection. Note, the
* connection must be closed by the caller by calling the close method.
*
* @throws DatabaseException thrown if there is an exception opening the
* database.
*/
public CveDB() throws DatabaseException {
super();
@@ -80,6 +89,7 @@ public class CveDB {
open();
try {
final String databaseProductName = conn.getMetaData().getDatabaseProductName();
batchSupported = conn.getMetaData().supportsBatchUpdates();
LOGGER.debug("Database dialect: {}", databaseProductName);
final Locale dbDialect = new Locale(databaseProductName);
statementBundle = ResourceBundle.getBundle("data/dbStatements", dbDialect);
@@ -103,9 +113,11 @@ public class CveDB {
}
/**
* Opens the database connection. If the database does not exist, it will create a new one.
* Opens the database connection. If the database does not exist, it will
* create a new one.
*
* @throws DatabaseException thrown if there is an error opening the database connection
* @throws DatabaseException thrown if there is an error opening the
* database connection
*/
public final void open() throws DatabaseException {
if (!isOpen()) {
@@ -114,7 +126,8 @@ public class CveDB {
}
/**
* Closes the DB4O database. Close should be called on this object when it is done being used.
* Closes the DB4O database. Close should be called on this object when it
* is done being used.
*/
public void close() {
if (conn != null) {
@@ -165,7 +178,8 @@ public class CveDB {
super.finalize();
}
/**
* Database properties object containing the 'properties' from the database table.
* Database properties object containing the 'properties' from the database
* table.
*/
private DatabaseProperties databaseProperties;
@@ -179,11 +193,13 @@ public class CveDB {
}
/**
* Searches the CPE entries in the database and retrieves all entries for a given vendor and product combination. The returned
* list will include all versions of the product that are registered in the NVD CVE data.
* Searches the CPE entries in the database and retrieves all entries for a
* given vendor and product combination. The returned list will include all
* versions of the product that are registered in the NVD CVE data.
*
* @param vendor the identified vendor name of the dependency being analyzed
* @param product the identified name of the product of the dependency being analyzed
* @param product the identified name of the product of the dependency being
* analyzed
* @return a set of vulnerable software
*/
public Set<VulnerableSoftware> getCPEs(String vendor, String product) {
@@ -215,7 +231,8 @@ public class CveDB {
* Returns the entire list of vendor/product combinations.
*
* @return the entire list of vendor/product combinations
* @throws DatabaseException thrown when there is an error retrieving the data from the DB
* @throws DatabaseException thrown when there is an error retrieving the
* data from the DB
*/
public Set<Pair<String, String>> getVendorProductList() throws DatabaseException {
final Set<Pair<String, String>> data = new HashSet<Pair<String, String>>();
@@ -380,6 +397,7 @@ public class CveDB {
ResultSet rsR = null;
ResultSet rsS = null;
Vulnerability vuln = null;
try {
psV = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY"));
psV.setString(1, cve);
@@ -438,7 +456,8 @@ public class CveDB {
}
/**
* Updates the vulnerability within the database. If the vulnerability does not exist it will be added.
* Updates the vulnerability within the database. If the vulnerability does
* not exist it will be added.
*
* @param vuln the vulnerability to add to the database
* @throws DatabaseException is thrown if the database
@@ -484,6 +503,7 @@ public class CveDB {
}
DBUtils.closeResultSet(rs);
rs = null;
if (vulnerabilityId != 0) {
if (vuln.getDescription().contains("** REJECT **")) {
deleteVulnerability.setInt(1, vulnerabilityId);
@@ -525,13 +545,24 @@ public class CveDB {
rs = null;
}
}
insertReference.setInt(1, vulnerabilityId);
for (Reference r : vuln.getReferences()) {
insertReference.setInt(1, vulnerabilityId);
insertReference.setString(2, r.getName());
insertReference.setString(3, r.getUrl());
insertReference.setString(4, r.getSource());
insertReference.execute();
if (batchSupported) {
insertReference.addBatch();
} else {
insertReference.execute();
}
}
if (batchSupported) {
insertReference.executeBatch();
}
for (VulnerableSoftware s : vuln.getVulnerableSoftware()) {
int cpeProductId = 0;
selectCpeId.setString(1, s.getName());
@@ -560,17 +591,33 @@ public class CveDB {
insertSoftware.setInt(1, vulnerabilityId);
insertSoftware.setInt(2, cpeProductId);
if (s.getPreviousVersion() == null) {
insertSoftware.setNull(3, java.sql.Types.VARCHAR);
} else {
insertSoftware.setString(3, s.getPreviousVersion());
}
insertSoftware.execute();
if (batchSupported) {
insertSoftware.addBatch();
} else {
try {
insertSoftware.execute();
} catch (SQLException ex) {
if (ex.getMessage().contains("Duplicate entry")) {
final String msg = String.format("Duplicate software key identified in '%s:%s'", vuln.getName(), s.getName());
LOGGER.debug(msg, ex);
} else {
throw ex;
}
}
}
}
if (batchSupported) {
insertSoftware.executeBatch();
}
} catch (SQLException ex) {
final String msg = String.format("Error updating '%s'", vuln.getName());
LOGGER.debug("", ex);
LOGGER.debug(msg, ex);
throw new DatabaseException(msg, ex);
} finally {
DBUtils.closeStatement(selectVulnerabilityId);
@@ -623,8 +670,9 @@ public class CveDB {
}
/**
* It is possible that orphaned rows may be generated during database updates. This should be called after all updates have
* been completed to ensure orphan entries are removed.
* It is possible that orphaned rows may be generated during database
* updates. This should be called after all updates have been completed to
* ensure orphan entries are removed.
*/
public void cleanupDatabase() {
PreparedStatement ps = null;
@@ -642,13 +690,17 @@ public class CveDB {
}
/**
* Determines if the given identifiedVersion is affected by the given cpeId and previous version flag. A non-null, non-empty
* string passed to the previous version argument indicates that all previous versions are affected.
* Determines if the given identifiedVersion is affected by the given cpeId
* and previous version flag. A non-null, non-empty string passed to the
* previous version argument indicates that all previous versions are
* affected.
*
* @param vendor the vendor of the dependency being analyzed
* @param product the product name of the dependency being analyzed
* @param vulnerableSoftware a map of the vulnerable software with a boolean indicating if all previous versions are affected
* @param identifiedVersion the identified version of the dependency being analyzed
* @param vulnerableSoftware a map of the vulnerable software with a boolean
* indicating if all previous versions are affected
* @param identifiedVersion the identified version of the dependency being
* analyzed
* @return true if the identified version is affected, otherwise false
*/
Entry<String, Boolean> getMatchingSoftware(Map<String, Boolean> vulnerableSoftware, String vendor, String product,
@@ -715,7 +767,8 @@ public class CveDB {
}
/**
* Parses the version (including revision) from a CPE identifier. If no version is identified then a '-' is returned.
* Parses the version (including revision) from a CPE identifier. If no
* version is identified then a '-' is returned.
*
* @param cpeStr a cpe identifier
* @return a dependency version
@@ -732,7 +785,8 @@ public class CveDB {
}
/**
* Takes a CPE and parses out the version number. If no version is identified then a '-' is returned.
* Takes a CPE and parses out the version number. If no version is
* identified then a '-' is returned.
*
* @param cpe a cpe object
* @return a dependency version
@@ -771,7 +825,8 @@ public class CveDB {
}
/**
* This method is only referenced in unused code and will likely break on MySQL if ever used due to the MERGE statement.
* This method is only referenced in unused code and will likely break on
* MySQL if ever used due to the MERGE statement.
*
* Merges CPE entries into the database.
*

View File

@@ -60,9 +60,11 @@ public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource {
/**
* <p>
* Downloads the latest NVD CVE XML file from the web and imports it into the current CVE Database.</p>
* Downloads the latest NVD CVE XML file from the web and imports it into
* the current CVE Database.</p>
*
* @throws UpdateException is thrown if there is an error updating the database
* @throws UpdateException is thrown if there is an error updating the
* database
*/
@Override
public void update() throws UpdateException {
@@ -76,6 +78,7 @@ public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource {
}
if (autoUpdate && checkUpdate()) {
final UpdateableNvdCve updateable = getUpdatesNeeded();
getProperties().save(DatabaseProperties.LAST_CHECKED, Long.toString(System.currentTimeMillis()));
if (updateable.isUpdateNeeded()) {
performUpdate(updateable);
}
@@ -98,12 +101,15 @@ 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.
* 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.
* @throws UpdateException thrown when there is an issue checking for updates.
* @throws UpdateException thrown when there is an issue checking for
* updates.
*/
private boolean checkUpdate() throws UpdateException {
boolean proceed = true;
@@ -115,9 +121,7 @@ public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource {
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 {
if (!proceed) {
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);
@@ -147,11 +151,13 @@ public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource {
}
/**
* Downloads the latest NVD CVE XML file from the web and imports it into the current CVE Database.
* Downloads the latest NVD CVE XML file from the web and imports it into
* the current CVE Database.
*
* @param updateable a collection of NVD CVE data file references that need to be downloaded and processed to update the
* @param updateable a collection of NVD CVE data file references that need
* to be downloaded and processed to update the database
* @throws UpdateException is thrown if there is an error updating the
* database
* @throws UpdateException is thrown if there is an error updating the database
*/
public void performUpdate(UpdateableNvdCve updateable) throws UpdateException {
int maxUpdates = 0;
@@ -245,13 +251,18 @@ public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource {
}
/**
* Determines if the index needs to be updated. This is done by fetching the NVD CVE meta data and checking the last update
* date. If the data needs to be refreshed this method will return the NvdCveUrl for the files that need to be updated.
* Determines if the index needs to be updated. This is done by fetching the
* NVD CVE meta data and checking the last update date. If the data needs to
* be refreshed this method will return the NvdCveUrl for the files that
* need to be updated.
*
* @return the collection of files that need to be updated
* @throws MalformedURLException is thrown if the URL for the NVD CVE Meta data is incorrect
* @throws DownloadFailedException is thrown if there is an error. downloading the NVD CVE download data file
* @throws UpdateException Is thrown if there is an issue with the last updated properties file
* @throws MalformedURLException is thrown if the URL for the NVD CVE Meta
* data is incorrect
* @throws DownloadFailedException is thrown if there is an error.
* downloading the NVD CVE download data file
* @throws UpdateException Is thrown if there is an issue with the last
* updated properties file
*/
protected final UpdateableNvdCve getUpdatesNeeded() throws MalformedURLException, DownloadFailedException, UpdateException {
UpdateableNvdCve updates = null;
@@ -315,9 +326,12 @@ public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource {
* Retrieves the timestamps from the NVD CVE meta data file.
*
* @return the timestamp from the currently published nvdcve downloads page
* @throws MalformedURLException thrown if the URL for the NVD CCE Meta data is incorrect.
* @throws DownloadFailedException thrown if there is an error downloading the nvd cve meta data file
* @throws InvalidDataException thrown if there is an exception parsing the timestamps
* @throws MalformedURLException thrown if the URL for the NVD CCE Meta data
* is incorrect.
* @throws DownloadFailedException thrown if there is an error downloading
* the nvd cve meta data file
* @throws InvalidDataException thrown if there is an exception parsing the
* timestamps
* @throws InvalidSettingException thrown if the settings are invalid
*/
private UpdateableNvdCve retrieveCurrentTimestampsFromWeb()
@@ -339,5 +353,4 @@ public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource {
}
return updates;
}
}

View File

@@ -261,6 +261,7 @@ public class DownloadTask implements Callable<Future<ProcessTask>> {
try {
is.close();
} catch (IOException ex) {
LOGGER.debug("Error closing stream", ex);
}
}
}

View File

@@ -254,17 +254,16 @@ public class NvdCve20Handler extends DefaultHandler {
* @throws IOException thrown if there is an IOException with the CPE Index
*/
private void saveEntry(Vulnerability vuln) throws DatabaseException, CorruptIndexException, IOException {
if (cveDB == null) {
return;
}
final String cveName = vuln.getName();
if (prevVersionVulnMap.containsKey(cveName)) {
if (prevVersionVulnMap != null && prevVersionVulnMap.containsKey(cveName)) {
final List<VulnerableSoftware> vulnSoftware = prevVersionVulnMap.get(cveName);
for (VulnerableSoftware vs : vulnSoftware) {
vuln.updateVulnerableSoftware(vs);
}
}
cveDB.updateVulnerability(vuln);
if (cveDB != null) {
cveDB.updateVulnerability(vuln);
}
}
// <editor-fold defaultstate="collapsed" desc="The Element Class that maintains state information about the current node">

View File

@@ -36,9 +36,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A program dependency. This object is one of the core components within DependencyCheck. It is used to collect information about
* the dependency in the form of evidence. The Evidence is then used to determine if there are any known, published,
* vulnerabilities associated with the program dependency.
* A program dependency. This object is one of the core components within
* DependencyCheck. It is used to collect information about the dependency in
* the form of evidence. The Evidence is then used to determine if there are any
* known, published, vulnerabilities associated with the program dependency.
*
* @author Jeremy Long
*/
@@ -72,17 +73,31 @@ public class Dependency implements Serializable, Comparable<Dependency> {
* The file name of the dependency.
*/
private String fileName;
/**
* The package path.
*/
private String packagePath;
/**
* Returns the package path.
*
* @return the package path
*/
public String getPackagePath() {
return packagePath;
}
return packagePath;
}
public void setPackagePath(String packagePath) {
this.packagePath = packagePath;
}
/**
* Sets the package path.
*
* @param packagePath the package path
*/
public void setPackagePath(String packagePath) {
this.packagePath = packagePath;
}
/**
/**
* The md5 hash of the dependency.
*/
private String md5sum;
@@ -144,10 +159,12 @@ public class Dependency implements Serializable, Comparable<Dependency> {
}
/**
* Returns the file name of the dependency with the backslash escaped for use in JavaScript. This is a complete hack as I
* could not get the replace to work in the template itself.
* Returns the file name of the dependency with the backslash escaped for
* use in JavaScript. This is a complete hack as I could not get the replace
* to work in the template itself.
*
* @return the file name of the dependency with the backslash escaped for use in JavaScript
* @return the file name of the dependency with the backslash escaped for
* use in JavaScript
*/
public String getFileNameForJavaScript() {
return this.fileName.replace("\\", "\\\\");
@@ -199,9 +216,9 @@ public class Dependency implements Serializable, Comparable<Dependency> {
* @param filePath the file path of the dependency
*/
public void setFilePath(String filePath) {
if(this.packagePath == null || this.packagePath.equals(this.filePath))
this.packagePath = filePath;
if (this.packagePath == null || this.packagePath.equals(this.filePath)) {
this.packagePath = filePath;
}
this.filePath = filePath;
}
@@ -220,7 +237,8 @@ public class Dependency implements Serializable, Comparable<Dependency> {
}
/**
* Returns the file name to display in reports; if no display file name has been set it will default to the actual file name.
* Returns the file name to display in reports; if no display file name has
* been set it will default to the actual file name.
*
* @return the file name to display
*/
@@ -235,8 +253,9 @@ public class Dependency implements Serializable, Comparable<Dependency> {
* <p>
* Gets the file path of the dependency.</p>
* <p>
* <b>NOTE:</b> This may not be the actual path of the file on disk. The actual path of the file on disk can be obtained via
* the getActualFilePath().</p>
* <b>NOTE:</b> This may not be the actual path of the file on disk. The
* actual path of the file on disk can be obtained via the
* getActualFilePath().</p>
*
* @return the file path of the dependency
*/
@@ -299,7 +318,8 @@ public class Dependency implements Serializable, Comparable<Dependency> {
}
/**
* Adds an entry to the list of detected Identifiers for the dependency file.
* Adds an entry to the list of detected Identifiers for the dependency
* file.
*
* @param type the type of identifier (such as CPE)
* @param value the value of the identifier
@@ -311,7 +331,8 @@ public class Dependency implements Serializable, Comparable<Dependency> {
}
/**
* Adds an entry to the list of detected Identifiers for the dependency file.
* Adds an entry to the list of detected Identifiers for the dependency
* file.
*
* @param type the type of identifier (such as CPE)
* @param value the value of the identifier
@@ -362,7 +383,8 @@ public class Dependency implements Serializable, Comparable<Dependency> {
}
/**
* Adds an entry to the list of detected Identifiers for the dependency file.
* Adds an entry to the list of detected Identifiers for the dependency
* file.
*
* @param identifier the identifier to add
*/
@@ -594,8 +616,9 @@ public class Dependency implements Serializable, Comparable<Dependency> {
private Set<Dependency> relatedDependencies = new TreeSet<Dependency>();
/**
* Get the value of {@link #relatedDependencies}. This field is used to collect other dependencies which really represent the
* same dependency, and may be presented as one item in reports.
* Get the value of {@link #relatedDependencies}. This field is used to
* collect other dependencies which really represent the same dependency,
* and may be presented as one item in reports.
*
* @return the value of relatedDependencies
*/
@@ -654,9 +677,11 @@ public class Dependency implements Serializable, Comparable<Dependency> {
}
/**
* Adds a related dependency. The internal collection is normally a {@link java.util.TreeSet}, which relies on
* {@link #compareTo(Dependency)}. A consequence of this is that if you attempt to add a dependency with the same file path
* (modulo character case) as one that is already in the collection, it won't get added.
* Adds a related dependency. The internal collection is normally a
* {@link java.util.TreeSet}, which relies on
* {@link #compareTo(Dependency)}. A consequence of this is that if you
* attempt to add a dependency with the same file path (modulo character
* case) as one that is already in the collection, it won't get added.
*
* @param dependency a reference to the related dependency
*/
@@ -706,7 +731,8 @@ public class Dependency implements Serializable, Comparable<Dependency> {
}
/**
* Implementation of the Comparable&lt;Dependency&gt; interface. The comparison is solely based on the file path.
* Implementation of the Comparable&lt;Dependency&gt; interface. The
* comparison is solely based on the file path.
*
* @param o a dependency to compare
* @return an integer representing the natural ordering
@@ -776,12 +802,14 @@ public class Dependency implements Serializable, Comparable<Dependency> {
}
/**
* Standard toString() implementation showing the filename, actualFilePath, and filePath.
* Standard toString() implementation showing the filename, actualFilePath,
* and filePath.
*
* @return the string representation of the file
*/
@Override
public String toString() {
return "Dependency{ fileName='" + fileName + "', actualFilePath='" + actualFilePath + "', filePath='" + filePath + "', packagePath='" + packagePath + "'}";
return "Dependency{ fileName='" + fileName + "', actualFilePath='" + actualFilePath
+ "', filePath='" + filePath + "', packagePath='" + packagePath + "'}";
}
}

View File

@@ -20,7 +20,8 @@ package org.owasp.dependencycheck.dependency;
import java.io.Serializable;
/**
* An external reference for a vulnerability. This contains a name, URL, and a source.
* An external reference for a vulnerability. This contains a name, URL, and a
* source.
*
* @author Jeremy Long
*/
@@ -97,6 +98,11 @@ public class Reference implements Serializable, Comparable<Reference> {
this.source = source;
}
@Override
public String toString() {
return "Reference: { name='" + this.name + "', url='" + this.url + "', source='" + this.source + "' }";
}
@Override
public boolean equals(Object obj) {
if (obj == null) {

View File

@@ -21,6 +21,7 @@ import java.io.Serializable;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Iterator;
/**
* Contains the information about a vulnerability.
@@ -33,6 +34,7 @@ public class Vulnerability implements Serializable, Comparable<Vulnerability> {
* The serial version uid.
*/
private static final long serialVersionUID = 307319490326651052L;
/**
* The name of the vulnerability.
*/
@@ -383,6 +385,24 @@ public class Vulnerability implements Serializable, Comparable<Vulnerability> {
return hash;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Vulnerability ");
sb.append(this.name);
sb.append("\nReferences:\n");
for (Iterator i = this.references.iterator(); i.hasNext();) {
sb.append("=> ");
sb.append(i.next());
sb.append("\n");
}
sb.append("\nSoftware:\n");
for (Iterator i = this.vulnerableSoftware.iterator(); i.hasNext();) {
sb.append("=> ");
sb.append(i.next());
sb.append("\n");
}
return sb.toString();
}
/**
* Compares two vulnerabilities.
*

View File

@@ -138,7 +138,7 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
return false;
}
final VulnerableSoftware other = (VulnerableSoftware) obj;
if ((this.getName() == null) ? (other.getName() != null) : !this.getName().equals(other.getName())) {
if ((this.name == null) ? (other.getName() != null) : !this.name.equals(other.getName())) {
return false;
}
return true;
@@ -152,7 +152,7 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
@Override
public int hashCode() {
int hash = 7;
hash = 83 * hash + (this.getName() != null ? this.getName().hashCode() : 0);
hash = 83 * hash + (this.name != null ? this.name.hashCode() : 0);
return hash;
}
@@ -163,7 +163,7 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
*/
@Override
public String toString() {
return "VulnerableSoftware{ name=" + name + ", previousVersion=" + previousVersion + '}';
return "VulnerableSoftware{" + name + "[" + previousVersion + "]}";
}
/**
@@ -175,28 +175,19 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
@Override
public int compareTo(VulnerableSoftware vs) {
int result = 0;
final String[] left = this.getName().split(":");
final String[] left = this.name.split(":");
final String[] right = vs.getName().split(":");
final int max = (left.length <= right.length) ? left.length : right.length;
if (max > 0) {
for (int i = 0; result == 0 && i < max; i++) {
final String[] subLeft = left[i].split("\\.");
final String[] subRight = right[i].split("\\.");
final String[] subLeft = left[i].split("(\\.|-)");
final String[] subRight = right[i].split("(\\.|-)");
final int subMax = (subLeft.length <= subRight.length) ? subLeft.length : subRight.length;
if (subMax > 0) {
for (int x = 0; result == 0 && x < subMax; x++) {
if (isPositiveInteger(subLeft[x]) && isPositiveInteger(subRight[x])) {
try {
result = Long.valueOf(subLeft[x]).compareTo(Long.valueOf(subRight[x]));
// final long iLeft = Long.parseLong(subLeft[x]);
// final long iRight = Long.parseLong(subRight[x]);
// if (iLeft != iRight) {
// if (iLeft > iRight) {
// result = 2;
// } else {
// result = -2;
// }
// }
} catch (NumberFormatException ex) {
//ignore the exception - they obviously aren't numbers
if (!subLeft[x].equalsIgnoreCase(subRight[x])) {

View File

@@ -25,7 +25,6 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.List;
import java.util.logging.Level;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
@@ -110,7 +109,8 @@ public class SuppressionParser {
*
* @param inputStream an InputStream containing suppression rues
* @return a list of suppression rules
* @throws SuppressionParseException if the xml cannot be parsed
* @throws SuppressionParseException thrown if the xml cannot be parsed
* @throws SAXException thrown if the xml cannot be parsed
*/
public List<SuppressionRule> parseSuppressionRules(InputStream inputStream) throws SuppressionParseException, SAXException {
try {

View File

@@ -260,7 +260,7 @@ public class Model {
public void addLicense(License license) {
licenses.add(license);
}
/**
* The project URL.
*/
@@ -272,17 +272,17 @@ public class Model {
* @return the value of projectURL
*/
public String getProjectURL() {
return projectURL;
}
return projectURL;
}
/**
* Set the value of projectURL.
*
* @param parentVersion new value of projectURL
* @param projectURL new value of projectURL
*/
public void setProjectURL(String projectURL) {
this.projectURL = projectURL;
}
public void setProjectURL(String projectURL) {
this.projectURL = projectURL;
}
/**
* Process the Maven properties file and interpolate all properties.
@@ -308,11 +308,14 @@ public class Model {
/**
* <p>
* A utility function that will interpolate strings based on values given in the properties file. It will also interpolate the
* strings contained within the properties file so that properties can reference other properties.</p>
* A utility function that will interpolate strings based on values given in
* the properties file. It will also interpolate the strings contained
* within the properties file so that properties can reference other
* properties.</p>
* <p>
* <b>Note:</b> if there is no property found the reference will be removed. In other words, if the interpolated string will
* be replaced with an empty string.
* <b>Note:</b> if there is no property found the reference will be removed.
* In other words, if the interpolated string will be replaced with an empty
* string.
* </p>
* <p>
* Example:</p>
@@ -329,7 +332,8 @@ public class Model {
* </code>
*
* @param text the string that contains references to properties.
* @param properties a collection of properties that may be referenced within the text.
* @param properties a collection of properties that may be referenced
* within the text.
* @return the interpolated text.
*/
public static String interpolateString(String text, Properties properties) {
@@ -340,8 +344,9 @@ public class Model {
return substitutor.replace(text);
}
/**
* Utility class that can provide values from a Properties object to a StrSubstitutor.
/**
* Utility class that can provide values from a Properties object to a
* StrSubstitutor.
*/
private static class PropertyLookup extends StrLookup {

View File

@@ -13,3 +13,4 @@
# limitations under the License.
MERGE_PROPERTY=MERGE INTO properties (id, value) KEY(id) VALUES(?, ?)
CLEANUP_ORPHANS=DELETE FROM cpeEntry WHERE id IN (SELECT id FROM cpeEntry LEFT JOIN software ON cpeEntry.id = software.CPEEntryId WHERE software.CPEEntryId IS NULL)

View File

@@ -54,4 +54,4 @@ DELIMITER ;
GRANT EXECUTE ON PROCEDURE dependencycheck.save_property TO 'dcuser';
UPDATE Properties SET value='3.0' WHERE ID='version';
UPDATE properties SET value='3.0' WHERE ID='version';

View File

@@ -319,4 +319,98 @@
<filePath regex="true">.*\.(jar|exe|dll|ear|war|pom)</filePath>
<cpe>cpe:/a:class:class</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
Linux ssh False Positives
]]></notes>
<filePath regex="true">.*\.(jar|ear|war|pom)</filePath>
<cpe>cpe:/a:pam:pam</cpe>
<cpe>cpe:/a:pam_ssh:pam_ssh</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
elastic search false postivies
]]></notes>
<gav regex="true">org\.elasticsearch:securesm:.*</gav>
<cpe>cpe:/a:elasticsearch:elasticsearch</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
Glassfish false positives.
]]></notes>
<gav regex="true">org\.glassfish:javax.el:.*</gav>
<cpe>cpe:/a:oracle:glassfish</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
Struts false positives.
]]></notes>
<gav regex="true">sslext:sslext:.*</gav>
<cpe>cpe:/a:apache:struts</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
ACtiveMQ false positives.
]]></notes>
<gav regex="true">org\.apache\.activemq:activemq-pool.*</gav>
<cpe>cpe:/a:apache:activemq</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
ACtiveMQ false positives.
]]></notes>
<gav regex="true">org\.apache\.activemq:artemis.*</gav>
<cpe>cpe:/a:apache:activemq</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
Spring data mongodb false positives.
]]></notes>
<gav regex="true">org\.springframework\.data:spring-data-mongodb.*</gav>
<cpe>cpe:/a:mongodb:mongodb</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
Spring data neo4j false positives.
]]></notes>
<gav regex="true">org\.springframework\.data:spring-data-neo4j:.*</gav>
<cpe>cpe:/a:vmware:springsource_spring_framework</cpe>
<cpe>cpe:/a:pivotal:spring_framework</cpe>
<cpe>cpe:/a:neo4j:neo4j</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
Spring data solr false positives.
]]></notes>
<gav regex="true">org\.springframework\.data:spring-data-solr:.*</gav>
<cpe>cpe:/a:apache:solr</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
Spring social facebook false positive.
]]></notes>
<gav regex="true">org\.springframework\.social:spring-social-facebook:.*</gav>
<cpe>cpe:/a:facebook:facebook</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
Spring Security JWT false positive.
]]></notes>
<gav regex="true">org\.springframework\.security:spring-security-jwt.*</gav>
<cpe>cpe:/a:vmware:springsource_spring_security</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
Aether false positive.
]]></notes>
<gav regex="true">org.eclipse.aether:aether.*</gav>
<cpe>cpe:/a:eclipse:eclipse_ide</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
Drupal services false positive.
]]></notes>
<filePath regex="true">.*\.(jar|ear|war|pom)</filePath>
<cpe>cpe:/a:services_project:services</cpe>
</suppress>
</suppressions>

View File

@@ -63,13 +63,6 @@ cve.url-2.0.base=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz
cpe.validfordays=30
cpe.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.3.xml.gz
# file type analyzer settings:
analyzer.archive.enabled=true
analyzer.jar.enabled=true
analyzer.nuspec.enabled=true
analyzer.assembly.enabled=true
analyzer.composer.lock.enabled=true
# the URL for searching Nexus for SHA-1 hashes and whether it's enabled
analyzer.nexus.enabled=true
analyzer.nexus.url=https://repository.sonatype.org/service/local/
@@ -87,7 +80,7 @@ archive.scan.depth=3
# use HEAD (default) or GET as HTTP request method for query timestamp
downloader.quick.query.timestamp=true
analyzer.experimental.enabled=false
analyzer.jar.enabled=true
analyzer.archive.enabled=true
analyzer.node.package.enabled=true

View File

@@ -18,9 +18,12 @@
package org.owasp.dependencycheck.analyzer;
import java.util.Iterator;
import java.util.List;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.owasp.dependencycheck.BaseDBTestCase;
import org.owasp.dependencycheck.utils.Settings;
/**
*
@@ -34,15 +37,42 @@ public class AnalyzerServiceTest extends BaseDBTestCase {
@Test
public void testGetAnalyzers() {
AnalyzerService instance = new AnalyzerService(Thread.currentThread().getContextClassLoader());
Iterator<Analyzer> result = instance.getAnalyzers();
List<Analyzer> result = instance.getAnalyzers();
boolean found = false;
while (result.hasNext()) {
Analyzer a = result.next();
for (Analyzer a : result) {
if ("Jar Analyzer".equals(a.getName())) {
found = true;
}
}
assertTrue("JarAnalyzer loaded", found);
}
/**
* Test of getAnalyzers method, of class AnalyzerService.
*/
@Test
public void testGetExperimentalAnalyzers() {
Settings.setBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, false);
AnalyzerService instance = new AnalyzerService(Thread.currentThread().getContextClassLoader());
List<Analyzer> result = instance.getAnalyzers();
String experimental = "CMake Analyzer";
boolean found = false;
for (Analyzer a : result) {
if (experimental.equals(a.getName())) {
found = true;
}
}
assertFalse("Experimental analyzer loaded when set to false", found);
Settings.setBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, true);
result = instance.getAnalyzers();
found = false;
for (Analyzer a : result) {
if (experimental.equals(a.getName())) {
found = true;
}
}
assertTrue("Experimental analyzer not loaded when set to true", found);
}
}

View File

@@ -240,7 +240,7 @@ public class CPEAnalyzerIntegrationTest extends BaseDBTestCase {
Set<String> vendorWeightings = Collections.singleton("apache");
List<IndexEntry> result = instance.searchCPE(vendor, product, productWeightings, vendorWeightings);
List<IndexEntry> result = instance.searchCPE(vendor, product, vendorWeightings, productWeightings);
instance.close();
boolean found = false;

View File

@@ -31,6 +31,7 @@ import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.owasp.dependencycheck.BaseDBTestCase;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
@@ -48,7 +49,7 @@ import org.slf4j.LoggerFactory;
*
* @author Dale Visser
*/
public class RubyBundleAuditAnalyzerTest extends BaseTest {
public class RubyBundleAuditAnalyzerTest extends BaseDBTestCase {
private static final Logger LOGGER = LoggerFactory.getLogger(RubyBundleAuditAnalyzerTest.class);
@@ -64,7 +65,10 @@ public class RubyBundleAuditAnalyzerTest extends BaseTest {
*/
@Before
public void setUp() throws Exception {
Settings.initialize();
super.setUp();
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false);
Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, false);
analyzer = new RubyBundleAuditAnalyzer();
analyzer.setFilesMatched(true);
}
@@ -76,7 +80,6 @@ public class RubyBundleAuditAnalyzerTest extends BaseTest {
*/
@After
public void tearDown() throws Exception {
Settings.cleanup();
analyzer.close();
analyzer = null;
}
@@ -104,7 +107,7 @@ public class RubyBundleAuditAnalyzerTest extends BaseTest {
*/
@Test
public void testAnalysis() throws AnalysisException, DatabaseException {
try {
try {
analyzer.initialize();
final String resource = "ruby/vulnerable/gems/rails-4.1.15/Gemfile.lock";
final Dependency result = new Dependency(BaseTest.getResourceAsFile(this, resource));
@@ -112,14 +115,14 @@ public class RubyBundleAuditAnalyzerTest extends BaseTest {
analyzer.analyze(result, engine);
int size = engine.getDependencies().size();
assertTrue(size >= 1);
Dependency dependency = engine.getDependencies().get(0);
assertTrue(dependency.getProductEvidence().toString().toLowerCase().contains("redcarpet"));
assertTrue(dependency.getVersionEvidence().toString().toLowerCase().contains("2.2.2"));
assertTrue(dependency.getFilePath().endsWith(resource));
assertTrue(dependency.getFileName().equals("Gemfile.lock"));
} catch (Exception e) {
LOGGER.warn("Exception setting up RubyBundleAuditAnalyzer. Make sure Ruby gem bundle-audit is installed. You may also need to set property \"analyzer.bundle.audit.path\".", e);
LOGGER.warn("Exception setting up RubyBundleAuditAnalyzer. Make sure Ruby gem bundle-audit is installed. You may also need to set property \"analyzer.bundle.audit.path\".");
Assume.assumeNoException("Exception setting up RubyBundleAuditAnalyzer; bundle audit may not be installed, or property \"analyzer.bundle.audit.path\" may not be set.", e);
}
}
@@ -137,7 +140,6 @@ public class RubyBundleAuditAnalyzerTest extends BaseTest {
final Engine engine = new Engine();
analyzer.analyze(result, engine);
Dependency dependency = engine.getDependencies().get(0);
Vulnerability vulnerability = dependency.getVulnerabilities().first();
assertEquals(vulnerability.getCvssScore(), 5.0f, 0.0);
@@ -148,7 +150,6 @@ public class RubyBundleAuditAnalyzerTest extends BaseTest {
}
}
/**
* Test when Ruby bundle-audit is not available on the system.
*
@@ -156,17 +157,16 @@ public class RubyBundleAuditAnalyzerTest extends BaseTest {
*/
@Test
public void testMissingBundleAudit() throws AnalysisException, DatabaseException {
//set a non-exist bundle-audit
//set a non-exist bundle-audit
Settings.setString(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, "phantom-bundle-audit");
try {
//initialize should fail.
analyzer.initialize();
} catch (Exception e) {
//expected, so ignore.
}
finally {
assertThat(analyzer.isEnabled(), is(false));
LOGGER.info("phantom-bundle-audit is not available. Ruby Bundle Audit Analyzer is disabled as expected.");
analyzer.initialize();
} catch (Exception e) {
//expected, so ignore.
} finally {
assertThat(analyzer.isEnabled(), is(false));
LOGGER.info("phantom-bundle-audit is not available. Ruby Bundle Audit Analyzer is disabled as expected.");
}
}
@@ -177,45 +177,48 @@ public class RubyBundleAuditAnalyzerTest extends BaseTest {
*/
@Test
public void testDependenciesPath() throws AnalysisException, DatabaseException {
final Engine engine = new Engine();
engine.scan(BaseTest.getResourceAsFile(this,
"ruby/vulnerable/gems/rails-4.1.15/"));
engine.analyzeDependencies();
try {
engine.analyzeDependencies();
} catch (NullPointerException ex) {
LOGGER.error("NPE", ex);
throw ex;
}
List<Dependency> dependencies = engine.getDependencies();
LOGGER.info(dependencies.size() + " dependencies found.");
Iterator<Dependency> dIterator = dependencies.iterator();
while(dIterator.hasNext()) {
Dependency dept = dIterator.next();
LOGGER.info("dept path: " + dept.getActualFilePath());
while (dIterator.hasNext()) {
Dependency dept = dIterator.next();
LOGGER.info("dept path: " + dept.getActualFilePath());
Set<Identifier> identifiers = dept.getIdentifiers();
Iterator<Identifier> idIterator = identifiers.iterator();
while(idIterator.hasNext()) {
Identifier id = idIterator.next();
LOGGER.info(" Identifier: " + id.getValue() + ", type=" + id.getType() + ", url=" + id.getUrl() + ", conf="+ id.getConfidence());
}
Set<Evidence> prodEv = dept.getProductEvidence().getEvidence();
Iterator<Evidence> it = prodEv.iterator();
while(it.hasNext()) {
Evidence e = it.next();
LOGGER.info(" prod: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence());
}
Set<Evidence> versionEv = dept.getVersionEvidence().getEvidence();
Iterator<Evidence> vIt = versionEv.iterator();
while(vIt.hasNext()) {
Evidence e = vIt.next();
LOGGER.info(" version: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence());
}
Set<Identifier> identifiers = dept.getIdentifiers();
Iterator<Identifier> idIterator = identifiers.iterator();
while (idIterator.hasNext()) {
Identifier id = idIterator.next();
LOGGER.info(" Identifier: " + id.getValue() + ", type=" + id.getType() + ", url=" + id.getUrl() + ", conf=" + id.getConfidence());
}
Set<Evidence> vendorEv = dept.getVendorEvidence().getEvidence();
Iterator<Evidence> vendorIt = vendorEv.iterator();
while(vendorIt.hasNext()) {
Evidence e = vendorIt.next();
LOGGER.info(" vendor: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence());
}
Set<Evidence> prodEv = dept.getProductEvidence().getEvidence();
Iterator<Evidence> it = prodEv.iterator();
while (it.hasNext()) {
Evidence e = it.next();
LOGGER.info(" prod: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence());
}
Set<Evidence> versionEv = dept.getVersionEvidence().getEvidence();
Iterator<Evidence> vIt = versionEv.iterator();
while (vIt.hasNext()) {
Evidence e = vIt.next();
LOGGER.info(" version: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence());
}
Set<Evidence> vendorEv = dept.getVendorEvidence().getEvidence();
Iterator<Evidence> vendorIt = vendorEv.iterator();
while (vendorIt.hasNext()) {
Evidence e = vendorIt.next();
LOGGER.info(" vendor: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence());
}
}
}
}

View File

@@ -19,6 +19,8 @@ package org.owasp.dependencycheck.data.update.nvd;
import org.owasp.dependencycheck.data.update.nvd.NvdCve20Handler;
import java.io.File;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.junit.After;
@@ -28,6 +30,7 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
/**
*
@@ -49,12 +52,42 @@ public class NvdCve_2_0_HandlerTest extends BaseTest {
saxParser.parse(file, instance);
} catch (Throwable ex) {
ex.printStackTrace();
results = ex;
}
assertTrue("Exception thrown during parse of 2012 CVE version 2.0?", results == null);
if (results != null) {
System.err.println(results);
}
}
@Test
public void testParserWithPreviousVersion() {
Throwable results = null;
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
File file12 = BaseTest.getResourceAsFile(this, "cve-1.2-2008_4411.xml");
final NvdCve12Handler cve12Handler = new NvdCve12Handler();
saxParser.parse(file12, cve12Handler);
final Map<String, List<VulnerableSoftware>> prevVersionVulnMap = cve12Handler.getVulnerabilities();
//File file = new File(this.getClass().getClassLoader().getResource("nvdcve-2.0-2012.xml").getPath());
File file20 = BaseTest.getResourceAsFile(this, "cve-2.0-2008_4411.xml");
NvdCve20Handler instance = new NvdCve20Handler();
instance.setPrevVersionVulnMap(prevVersionVulnMap);
saxParser.parse(file20, instance);
assertTrue(instance.getTotalNumberOfEntries()==1);
} catch (Throwable ex) {
results = ex;
}
assertTrue("Exception thrown during parse of 2012 CVE version 2.0?", results == null);
if (results != null) {
System.err.println(results);
}
}
}

View File

@@ -0,0 +1,161 @@
/*
* 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) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.dependency;
import java.util.Set;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
/**
*
* @author Jens Hausherr
*/
public class VulnerabilityTest extends BaseTest {
/**
* Test of equals method, of class VulnerableSoftware.
*/
@Test
public void testDuplicateVersions() {
Vulnerability obj = new Vulnerability();
obj.addVulnerableSoftware("cpe:/a:mortbay:jetty:6.1.0");
obj.addVulnerableSoftware("cpe:/a:mortbay:jetty:6.1.1");
obj.addVulnerableSoftware("cpe:/a:mortbay:jetty:6.1.0");
assertEquals(2, obj.getVulnerableSoftware().size());
}
@Test
public void testDpulicateVersionsWithPreviousVersion() {
Vulnerability obj = new Vulnerability();
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.0-103%28a%29", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.0-118", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.3.132", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.12-200", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.2-127", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.9", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.10", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.11", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.12-118", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.4-143", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.0-109", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.6-156", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.4", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.3", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.10-186", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.6", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.5", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.5-146", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.8", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.7", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.2", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.0.2", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.1", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.8-177", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.0.1", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.0.0", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.7-168", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.0-103", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.11-197", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.9-178", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.12-200", "1");
assertEquals(31, obj.getVulnerableSoftware().size());
}
@Test
public void testSoftwareSorting() {
Vulnerability obj = new Vulnerability();
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.0-103%28a%29", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.0-118", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.3.132", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.12-200", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.2-127", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.9", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.10", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.11", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.12-118", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.4-143", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.0-109", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.6-156", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.4", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.3", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.10-186", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.6", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.5", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.5-146", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.8", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.7", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.2", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.0.2", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.1", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.8-177", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.0.1", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.0.0", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.7-168", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.0-103", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.11-197", null);
obj.addVulnerableSoftware("cpe:/a:hp:system_management_homepage:2.1.9-178", null);
Set<VulnerableSoftware> software = obj.getVulnerableSoftware();
VulnerableSoftware vs[] = software.toArray(new VulnerableSoftware[software.size()]);
assertTrue("cpe:/a:hp:system_management_homepage:2.0.0".equals(vs[0].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.0.1".equals(vs[1].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.0.2".equals(vs[2].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1".equals(vs[3].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.0-103".equals(vs[4].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.0-103%28a%29".equals(vs[5].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.0-109".equals(vs[6].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.0-118".equals(vs[7].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.1".equals(vs[8].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.2".equals(vs[9].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.2-127".equals(vs[10].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.3".equals(vs[11].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.3.132".equals(vs[12].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.4".equals(vs[13].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.4-143".equals(vs[14].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.5".equals(vs[15].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.5-146".equals(vs[16].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.6".equals(vs[17].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.6-156".equals(vs[18].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.7".equals(vs[19].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.7-168".equals(vs[20].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.8".equals(vs[21].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.8-177".equals(vs[22].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.9".equals(vs[23].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.9-178".equals(vs[24].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.10".equals(vs[25].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.10-186".equals(vs[26].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.11".equals(vs[27].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.11-197".equals(vs[28].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.12-118".equals(vs[29].getName()));
assertTrue("cpe:/a:hp:system_management_homepage:2.1.12-200".equals(vs[30].getName()));
}
}

View File

@@ -20,6 +20,8 @@ package org.owasp.dependencycheck.dependency;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -29,7 +31,7 @@ import org.owasp.dependencycheck.BaseTest;
*
* @author Jeremy Long
*/
public class VulnerableSoftwareTest extends BaseTest {
public class VulnerableSoftwareTest extends BaseTest {
/**
* Test of equals method, of class VulnerableSoftware.
@@ -40,9 +42,20 @@ public class VulnerableSoftwareTest extends BaseTest {
obj.setCpe("cpe:/a:mortbay:jetty:6.1.0");
VulnerableSoftware instance = new VulnerableSoftware();
instance.setCpe("cpe:/a:mortbay:jetty:6.1");
boolean expResult = false;
boolean result = instance.equals(obj);
assertEquals(expResult, result);
assertFalse(instance.equals(obj));
}
/**
* Test of equals method, of class VulnerableSoftware.
*/
@Test
public void testEquals2() {
VulnerableSoftware obj = new VulnerableSoftware();
obj.setCpe("cpe:/a:mortbay:jetty:6.1.0");
VulnerableSoftware instance = new VulnerableSoftware();
instance.setCpe("cpe:/a:mortbay:jetty:6.1.0");
obj.setPreviousVersion("1");
assertTrue(instance.equals(obj));
}
/**
@@ -78,4 +91,64 @@ public class VulnerableSoftwareTest extends BaseTest {
result = instance.compareTo(vs);
assertEquals(expResult, result);
}
@Test
public void testCompareToNonNumerical() {
VulnerableSoftware vs = new VulnerableSoftware();
vs.setCpe("cpe:/a:mysql:mysql:5.1.23a");
VulnerableSoftware vs1 = new VulnerableSoftware();
vs1.setCpe("cpe:/a:mysql:mysql:5.1.23a");
vs1.setPreviousVersion("1");
assertEquals(0, vs.compareTo(vs1));
assertEquals(0, vs1.compareTo(vs));
}
@Test
public void testCompareToComplex() {
VulnerableSoftware vs = new VulnerableSoftware();
VulnerableSoftware vs1 = new VulnerableSoftware();
vs.setCpe("2.1");
vs1.setCpe("2.1.10");
assertTrue(vs.compareTo(vs1) < 0);
vs.setCpe("cpe:/a:hp:system_management_homepage:2.1.1");
vs1.setCpe("cpe:/a:hp:system_management_homepage:2.1.10");
assertTrue(vs.compareTo(vs1) < 0);
vs.setCpe("10");
vs1.setCpe("10-186");
assertTrue(vs.compareTo(vs1) < 0);
vs.setCpe("2.1.10");
vs1.setCpe("2.1.10-186");
assertTrue(vs.compareTo(vs1) < 0);
vs.setCpe("cpe:/a:hp:system_management_homepage:2.1.10");
vs1.setCpe("cpe:/a:hp:system_management_homepage:2.1.10-186");
assertTrue(vs.compareTo(vs1) < 0);
//assertTrue(vs1.compareTo(vs)>0);
}
@Test
public void testEqualsPreviousVersion() {
VulnerableSoftware vs = new VulnerableSoftware();
vs.setCpe("cpe:/a:mysql:mysql:5.1.23a");
VulnerableSoftware vs1 = new VulnerableSoftware();
vs1.setCpe("cpe:/a:mysql:mysql:5.1.23a");
vs1.setPreviousVersion("1");
assertEquals(vs, vs1);
assertEquals(vs1, vs);
}
@Test
public void testParseCPE() {
VulnerableSoftware vs = new VulnerableSoftware();
/* Version for test taken from CVE-2008-2079 */
vs.setCpe("cpe:/a:mysql:mysql:5.1.23a");
assertEquals("mysql", vs.getVendor());
assertEquals("mysql", vs.getProduct());
assertEquals("5.1.23a", vs.getVersion());
}
}

View File

@@ -0,0 +1,57 @@
<?xml version='1.0' encoding='UTF-8'?>
<nvd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://nvd.nist.gov/feeds/cve/1.2" nvd_xml_version="1.2" pub_date="2016-05-28" xsi:schemaLocation="http://nvd.nist.gov/feeds/cve/1.2 http://nvd.nist.gov/schema/nvdcve_1.2.1.xsd">
<entry type="CVE" name="CVE-2008-4411" seq="2008-4411" published="2008-10-13" modified="2011-03-07" severity="Medium" CVSS_version="2.0" CVSS_score="4.3" CVSS_base_score="4.3" CVSS_impact_subscore="2.9" CVSS_exploit_subscore="8.6" CVSS_vector="(AV:N/AC:M/Au:N/C:N/I:P/A:N)">
<desc>
<descript source="cve">Cross-site scripting (XSS) vulnerability in HP System Management Homepage (SMH) before 2.1.15.210 on Linux and Windows allows remote attackers to inject arbitrary web script or HTML via unspecified vectors, a different vulnerability than CVE-2008-1663.</descript>
</desc>
<loss_types>
<int/>
</loss_types>
<range>
<network/>
</range>
<refs>
<ref source="BID" url="http://www.securityfocus.com/bid/31663" patch="1">31663</ref>
<ref source="XF" url="http://xforce.iss.net/xforce/xfdb/45754">smh-unspecified-xss(45754)</ref>
<ref source="VUPEN" url="http://www.vupen.com/english/advisories/2008/2778">ADV-2008-2778</ref>
<ref source="SECTRACK" url="http://securitytracker.com/id?1021015">1021015</ref>
<ref source="SREASON" url="http://securityreason.com/securityalert/4398">4398</ref>
</refs>
<vuln_soft>
<prod name="system_management_homepage" vendor="hp">
<vers num="2.0.0"/>
<vers num="2.0.1"/>
<vers num="2.0.2"/>
<vers num="2.1"/>
<vers num="2.1.0-103"/>
<vers num="2.1.0-103(a)"/>
<vers num="2.1.0-109"/>
<vers num="2.1.0-118"/>
<vers num="2.1.1"/>
<vers num="2.1.10"/>
<vers num="2.1.10-186"/>
<vers num="2.1.11"/>
<vers num="2.1.11-197"/>
<vers num="2.1.12-118"/>
<vers num="2.1.12-200" prev="1"/>
<vers num="2.1.2"/>
<vers num="2.1.2-127"/>
<vers num="2.1.3"/>
<vers num="2.1.3.132"/>
<vers num="2.1.4"/>
<vers num="2.1.4-143"/>
<vers num="2.1.5"/>
<vers num="2.1.5-146"/>
<vers num="2.1.6"/>
<vers num="2.1.6-156"/>
<vers num="2.1.7"/>
<vers num="2.1.7-168"/>
<vers num="2.1.8"/>
<vers num="2.1.8-177"/>
<vers num="2.1.9"/>
<vers num="2.1.9-178"/>
</prod>
</vuln_soft>
</entry>
</nvd>

View File

@@ -0,0 +1,115 @@
<?xml version='1.0' encoding='UTF-8'?>
<nvd xmlns:scap-core="http://scap.nist.gov/schema/scap-core/0.1" xmlns:cvss="http://scap.nist.gov/schema/cvss-v2/0.2" xmlns:vuln="http://scap.nist.gov/schema/vulnerability/0.4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:patch="http://scap.nist.gov/schema/patch/0.1" xmlns="http://scap.nist.gov/schema/feed/vulnerability/2.0" xmlns:cpe-lang="http://cpe.mitre.org/language/2.0" pub_date="2016-05-28T04:10:38" nvd_xml_version="2.0" xsi:schemaLocation="http://scap.nist.gov/schema/patch/0.1 http://nvd.nist.gov/schema/patch_0.1.xsd http://scap.nist.gov/schema/feed/vulnerability/2.0 http://nvd.nist.gov/schema/nvd-cve-feed_2.0.xsd http://scap.nist.gov/schema/scap-core/0.1 http://nvd.nist.gov/schema/scap-core_0.1.xsd">
<entry id="CVE-2008-4411">
<vuln:vulnerable-configuration id="http://nvd.nist.gov/">
<cpe-lang:logical-test operator="OR" negate="false">
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.0.1"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.0.2"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.11"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.10"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.0.0"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.3"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.2"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.1"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.3.132"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.8"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.4"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.5"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.6"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.7"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.9"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.12-200"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.11-197"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.10-186"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.9-178"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.8-177"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.7-168"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.6-156"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.5-146"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.4-143"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.2-127"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.12-118"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.0-118"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.0-109"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.0-103%28a%29"/>
<cpe-lang:fact-ref name="cpe:/a:hp:system_management_homepage:2.1.0-103"/>
</cpe-lang:logical-test>
</vuln:vulnerable-configuration>
<vuln:vulnerable-software-list>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.0-103%28a%29</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.0-118</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.3.132</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.12-200</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.2-127</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.9</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.10</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.11</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.12-118</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.4-143</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.0-109</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.6-156</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.4</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.3</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.10-186</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.6</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.5</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.5-146</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.8</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.7</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.2</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.0.2</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.1</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.8-177</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.0.1</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.0.0</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.7-168</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.0-103</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.11-197</vuln:product>
<vuln:product>cpe:/a:hp:system_management_homepage:2.1.9-178</vuln:product>
</vuln:vulnerable-software-list>
<vuln:cve-id>CVE-2008-4411</vuln:cve-id>
<vuln:published-datetime>2008-10-13T16:00:02.277-04:00</vuln:published-datetime>
<vuln:last-modified-datetime>2011-03-07T22:12:25.097-05:00</vuln:last-modified-datetime>
<vuln:cvss>
<cvss:base_metrics>
<cvss:score>4.3</cvss:score>
<cvss:access-vector>NETWORK</cvss:access-vector>
<cvss:access-complexity>MEDIUM</cvss:access-complexity>
<cvss:authentication>NONE</cvss:authentication>
<cvss:confidentiality-impact>NONE</cvss:confidentiality-impact>
<cvss:integrity-impact>PARTIAL</cvss:integrity-impact>
<cvss:availability-impact>NONE</cvss:availability-impact>
<cvss:source>http://nvd.nist.gov</cvss:source>
<cvss:generated-on-datetime>2008-10-14T10:57:00.000-04:00</cvss:generated-on-datetime>
</cvss:base_metrics>
</vuln:cvss>
<vuln:cwe id="CWE-79"/>
<vuln:references xml:lang="en" reference_type="PATCH">
<vuln:source>BID</vuln:source>
<vuln:reference href="http://www.securityfocus.com/bid/31663" xml:lang="en">31663</vuln:reference>
</vuln:references>
<vuln:references xml:lang="en" reference_type="UNKNOWN">
<vuln:source>XF</vuln:source>
<vuln:reference href="http://xforce.iss.net/xforce/xfdb/45754" xml:lang="en">smh-unspecified-xss(45754)</vuln:reference>
</vuln:references>
<vuln:references xml:lang="en" reference_type="UNKNOWN">
<vuln:source>VUPEN</vuln:source>
<vuln:reference href="http://www.vupen.com/english/advisories/2008/2778" xml:lang="en">ADV-2008-2778</vuln:reference>
</vuln:references>
<vuln:references xml:lang="en" reference_type="UNKNOWN">
<vuln:source>SECTRACK</vuln:source>
<vuln:reference href="http://securitytracker.com/id?1021015" xml:lang="en">1021015</vuln:reference>
</vuln:references>
<vuln:references xml:lang="en" reference_type="UNKNOWN">
<vuln:source>SREASON</vuln:source>
<vuln:reference href="http://securityreason.com/securityalert/4398" xml:lang="en">4398</vuln:reference>
</vuln:references>
<vuln:summary>Cross-site scripting (XSS) vulnerability in HP System Management Homepage (SMH) before 2.1.15.210 on Linux and Windows allows remote attackers to inject arbitrary web script or HTML via unspecified vectors, a different vulnerability than CVE-2008-1663.</vuln:summary>
</entry>
</nvd>

View File

@@ -58,12 +58,6 @@ cve.url-2.0.base=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz
cpe.validfordays=30
cpe.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.3.xml.gz
# file type analyzer settings:
analyzer.archive.enabled=true
analyzer.jar.enabled=true
analyzer.nuspec.enabled=true
analyzer.assembly.enabled=true
analyzer.composer.lock.enabled=true
# the URL for searching Nexus for SHA-1 hashes and whether it's enabled
analyzer.nexus.enabled=true
@@ -82,7 +76,7 @@ archive.scan.depth=3
# use HEAD (default) or GET as HTTP request method for query timestamp
downloader.quick.query.timestamp=true
analyzer.experimental.enabled=true
analyzer.jar.enabled=true
analyzer.archive.enabled=true
analyzer.node.package.enabled=true

View File

@@ -20,7 +20,7 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.3.7-SNAPSHOT</version>
<version>1.4.0-SNAPSHOT</version>
</parent>
<artifactId>dependency-check-maven</artifactId>

View File

@@ -94,24 +94,32 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
@Parameter(defaultValue = "${project.build.directory}", required = true)
private File outputDirectory;
/**
* Specifies the destination directory for the generated Dependency-Check report. This generally maps to "target/site".
* Specifies the destination directory for the generated Dependency-Check
* report. This generally maps to "target/site".
*/
@Parameter(property = "project.reporting.outputDirectory", required = true)
private File reportOutputDirectory;
/**
* Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which
* means since the CVSS scores are 0-10, by default the build will never fail.
* Specifies if the build should be failed if a CVSS score above a specified
* level is identified. The default is 11 which means since the CVSS scores
* are 0-10, by default the build will never fail.
*/
@SuppressWarnings("CanBeFinal")
@Parameter(property = "failBuildOnCVSS", defaultValue = "11", required = true)
private float failBuildOnCVSS = 11;
/**
* Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. Default
* is true.
* Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not
* recommended that this be turned to false. Default is true.
*/
@SuppressWarnings("CanBeFinal")
@Parameter(property = "autoUpdate")
private Boolean autoUpdate;
/**
* Sets whether Experimental analyzers are enabled. Default is false.
*/
@SuppressWarnings("CanBeFinal")
@Parameter(property = "enableExperimental")
private Boolean enableExperimental;
/**
* Generate aggregate reports in multi-module projects.
*
@@ -121,8 +129,9 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
@Deprecated
private Boolean aggregate;
/**
* The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the
* Site plug-in unless the externalReport is set to true. Default is HTML.
* The report format to be generated (HTML, XML, VULN, ALL). This
* configuration option has no affect if using this within the Site plug-in
* unless the externalReport is set to true. Default is HTML.
*/
@SuppressWarnings("CanBeFinal")
@Parameter(property = "format", defaultValue = "HTML", required = true)
@@ -234,7 +243,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
private Boolean nexusAnalyzerEnabled;
/**
* The URL of a Nexus server's REST API end point (http://domain/nexus/service/local).
* The URL of a Nexus server's REST API end point
* (http://domain/nexus/service/local).
*/
@Parameter(property = "nexusUrl", required = false)
private String nexusUrl;
@@ -268,7 +278,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
@Parameter(property = "databaseDriverPath", defaultValue = "", required = false)
private String databaseDriverPath;
/**
* The server id in the settings.xml; used to retrieve encrypted passwords from the settings.xml.
* The server id in the settings.xml; used to retrieve encrypted passwords
* from the settings.xml.
*/
@Parameter(property = "serverId", defaultValue = "", required = false)
private String serverId;
@@ -293,7 +304,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
@Parameter(property = "databasePassword", defaultValue = "", required = false)
private String databasePassword;
/**
* A comma-separated list of file extensions to add to analysis next to jar, zip, ....
* A comma-separated list of file extensions to add to analysis next to jar,
* zip, ....
*/
@Parameter(property = "zipExtensions", required = false)
private String zipExtensions;
@@ -347,7 +359,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
@Parameter(property = "cveUrl20Base", defaultValue = "", required = false)
private String cveUrl20Base;
/**
* Optionally skip excessive CVE update checks for a designated duration in hours.
* Optionally skip excessive CVE update checks for a designated duration in
* hours.
*/
@Parameter(property = "cveValidForHours", defaultValue = "", required = false)
private Integer cveValidForHours;
@@ -382,7 +395,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
/**
* Executes dependency-check.
*
* @throws MojoExecutionException thrown if there is an exception executing the mojo
* @throws MojoExecutionException thrown if there is an exception executing
* the mojo
* @throws MojoFailureException thrown if dependency-check failed the build
*/
@Override
@@ -398,8 +412,9 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
}
/**
* Checks if the aggregate configuration parameter has been set to true. If it has a MojoExecutionException is thrown because
* the aggregate configuration parameter is no longer supported.
* Checks if the aggregate configuration parameter has been set to true. If
* it has a MojoExecutionException is thrown because the aggregate
* configuration parameter is no longer supported.
*
* @throws MojoExecutionException thrown if aggregate is set to true
*/
@@ -417,7 +432,9 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
* @param sink the sink to write the report to
* @param locale the locale to use when generating the report
* @throws MavenReportException if a maven report exception occurs
* @deprecated use {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale)} instead.
* @deprecated use
* {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale)}
* instead.
*/
@Override
@Deprecated
@@ -464,17 +481,20 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
}
/**
* Returns the correct output directory depending on if a site is being executed or not.
* Returns the correct output directory depending on if a site is being
* executed or not.
*
* @return the directory to write the report(s)
* @throws MojoExecutionException thrown if there is an error loading the file path
* @throws MojoExecutionException thrown if there is an error loading the
* file path
*/
protected File getCorrectOutputDirectory() throws MojoExecutionException {
return getCorrectOutputDirectory(this.project);
}
/**
* Returns the correct output directory depending on if a site is being executed or not.
* Returns the correct output directory depending on if a site is being
* executed or not.
*
* @param current the Maven project to get the output directory from
* @return the directory to write the report(s)
@@ -492,7 +512,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
}
/**
* Returns the correct output directory depending on if a site is being executed or not.
* Returns the correct output directory depending on if a site is being
* executed or not.
*
* @param current the Maven project to get the output directory from
* @return the directory to write the report(s)
@@ -507,16 +528,15 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
final File f = new File((String) obj);
return f;
}
} else {
if (getLog().isDebugEnabled()) {
getLog().debug("Context value not found");
}
} else if (getLog().isDebugEnabled()) {
getLog().debug("Context value not found");
}
return null;
}
/**
* Scans the project's artifacts and adds them to the engine's dependency list.
* Scans the project's artifacts and adds them to the engine's dependency
* list.
*
* @param project the project to scan the dependencies of
* @param engine the engine to use to scan the dependencies
@@ -539,12 +559,10 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
d.getDisplayFileName()));
}
}
} else {
if (getLog().isDebugEnabled()) {
final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'",
a.getGroupId(), a.getArtifactId(), a.getVersion());
getLog().debug(msg);
}
} else if (getLog().isDebugEnabled()) {
final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'",
a.getGroupId(), a.getArtifactId(), a.getVersion());
getLog().debug(msg);
}
}
}
@@ -553,8 +571,10 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
/**
* Executes the dependency-check scan and generates the necassary report.
*
* @throws MojoExecutionException thrown if there is an exception running the scan
* @throws MojoFailureException thrown if dependency-check is configured to fail the build
* @throws MojoExecutionException thrown if there is an exception running
* the scan
* @throws MojoFailureException thrown if dependency-check is configured to
* fail the build
*/
public abstract void runCheck() throws MojoExecutionException, MojoFailureException;
@@ -588,7 +608,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
}
/**
* Returns whether this is an external report. This method always returns true.
* Returns whether this is an external report. This method always returns
* true.
*
* @return <code>true</code>
*/
@@ -640,8 +661,9 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
}
/**
* Takes the properties supplied and updates the dependency-check settings. Additionally, this sets the system properties
* required to change the proxy url, port, and connection timeout.
* Takes the properties supplied and updates the dependency-check settings.
* Additionally, this sets the system properties required to change the
* proxy url, port, and connection timeout.
*/
protected void populateSettings() {
Settings.initialize();
@@ -667,6 +689,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
}
Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate);
Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental);
if (externalReport != null) {
getLog().warn("The 'externalReport' option was set; this configuration option has been removed. "
+ "Please update the dependency-check-maven plugin's configuration");
@@ -795,10 +819,12 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
}
/**
* Tests is the artifact should be included in the scan (i.e. is the dependency in a scope that is being scanned).
* Tests is the artifact should be included in the scan (i.e. is the
* dependency in a scope that is being scanned).
*
* @param a the Artifact to test
* @return <code>true</code> if the artifact is in an excluded scope; otherwise <code>false</code>
* @return <code>true</code> if the artifact is in an excluded scope;
* otherwise <code>false</code>
*/
protected boolean excludeFromScan(Artifact a) {
if (skipTestScope && Artifact.SCOPE_TEST.equals(a.getScope())) {
@@ -814,10 +840,12 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
}
/**
* Returns a reference to the current project. This method is used instead of auto-binding the project via component
* annotation in concrete implementations of this. If the child has a <code>@Component MavenProject project;</code> defined
* then the abstract class (i.e. this class) will not have access to the current project (just the way Maven works with the
* binding).
* Returns a reference to the current project. This method is used instead
* of auto-binding the project via component annotation in concrete
* implementations of this. If the child has a
* <code>@Component MavenProject project;</code> defined then the abstract
* class (i.e. this class) will not have access to the current project (just
* the way Maven works with the binding).
*
* @return returns a reference to the current project
*/
@@ -886,11 +914,12 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
//<editor-fold defaultstate="collapsed" desc="Methods to fail build or show summary">
/**
* Checks to see if a vulnerability has been identified with a CVSS score that is above the threshold set in the
* configuration.
* Checks to see if a vulnerability has been identified with a CVSS score
* that is above the threshold set in the configuration.
*
* @param dependencies the list of dependency objects
* @throws MojoFailureException thrown if a CVSS score is found that is higher then the threshold set
* @throws MojoFailureException thrown if a CVSS score is found that is
* higher then the threshold set
*/
protected void checkForFailure(List<Dependency> dependencies) throws MojoFailureException {
if (failBuildOnCVSS <= 10) {
@@ -919,7 +948,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
}
/**
* Generates a warning message listing a summary of dependencies and their associated CPE and CVE entries.
* Generates a warning message listing a summary of dependencies and their
* associated CPE and CVE entries.
*
* @param mp the Maven project for which the summary is shown
* @param dependencies a list of dependency objects
@@ -963,8 +993,9 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Methods to read/write the serialized data file">
/**
* Returns the key used to store the path to the data file that is saved by <code>writeDataFile()</code>. This key is used in
* the <code>MavenProject.(set|get)ContextValue</code>.
* Returns the key used to store the path to the data file that is saved by
* <code>writeDataFile()</code>. This key is used in the
* <code>MavenProject.(set|get)ContextValue</code>.
*
* @return the key used to store the path to the data file
*/
@@ -973,8 +1004,9 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
}
/**
* Returns the key used to store the path to the output directory. When generating the report in the
* <code>executeAggregateReport()</code> the output directory should be obtained by using this key.
* Returns the key used to store the path to the output directory. When
* generating the report in the <code>executeAggregateReport()</code> the
* output directory should be obtained by using this key.
*
* @return the key used to store the path to the output directory
*/
@@ -983,7 +1015,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
}
/**
* Writes the scan data to disk. This is used to serialize the scan data between the "check" and "aggregate" phase.
* Writes the scan data to disk. This is used to serialize the scan data
* between the "check" and "aggregate" phase.
*
* @param mp the mMven project for which the data file was created
* @param writeTo the directory to write the data file
@@ -1000,7 +1033,7 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
file = new File(writeTo, dataFileName);
}
final File parent = file.getParentFile();
if (!parent.isDirectory() && parent.mkdirs()) {
if (!parent.isDirectory() && !parent.mkdirs()) {
getLog().error(String.format("Directory '%s' does not exist and cannot be created; unable to write data file.",
parent.getAbsolutePath()));
}
@@ -1037,12 +1070,12 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
}
/**
* Reads the serialized scan data from disk. This is used to serialize the scan data between the "check" and "aggregate"
* phase.
* Reads the serialized scan data from disk. This is used to serialize the
* scan data between the "check" and "aggregate" phase.
*
* @param project the Maven project to read the data file from
* @return a <code>Engine</code> object populated with dependencies if the serialized data file exists; otherwise
* <code>null</code> is returned
* @return a <code>Engine</code> object populated with dependencies if the
* serialized data file exists; otherwise <code>null</code> is returned
*/
protected List<Dependency> readDataFile(MavenProject project) {
final Object oPath = project.getContextValue(this.getDataFileContextKey());

View File

@@ -27,10 +27,6 @@ import org.slf4j.helpers.MessageFormatter;
* @author colezlaw
*/
public class MavenLoggerAdapter extends MarkerIgnoringBase {
/**
* The serial version UID for serialization.
*/
private static final long serialVersionUID = 1L;
/**
* A reference to the Maven log.

View File

@@ -23,8 +23,9 @@ import org.slf4j.ILoggerFactory;
import org.slf4j.spi.LoggerFactoryBinder;
/**
* The binding of org.slf4j.LoggerFactory class with an actual instance of org.slf4j.ILoggerFactory is performed using information
* returned by this class.
* The binding of org.slf4j.LoggerFactory class with an actual instance of
* org.slf4j.ILoggerFactory is performed using information returned by this
* class.
*
* @author colezlaw
*/
@@ -47,7 +48,7 @@ public class StaticLoggerBinder implements LoggerFactoryBinder {
}
/**
* Maven mojos have their own logger, so we'll use one of those
* Maven mojos have their own logger, so we'll use one of those.
*/
private Log log = null;
@@ -62,8 +63,8 @@ public class StaticLoggerBinder implements LoggerFactoryBinder {
}
/**
* Declare the version of the SLF4J API this implementation is compiled against. The value of this filed is usually modified
* with each release.
* Declare the version of the SLF4J API this implementation is compiled
* against. The value of this filed is usually modified with each release.
*/
// to avoid constant folding by the compiler, this field must *not* be final
//CSOFF: StaticVariableName
@@ -78,7 +79,8 @@ public class StaticLoggerBinder implements LoggerFactoryBinder {
private static final String LOGGER_FACTORY_CLASS = MavenLoggerFactory.class.getName();
/**
* The ILoggerFactory instance returned by the {@link #getLoggerFactory} method should always be the same object
* The ILoggerFactory instance returned by the {@link #getLoggerFactory}
* method should always be the same object
*/
private ILoggerFactory loggerFactory;

View File

@@ -21,10 +21,11 @@ format | The report format to be generated (HTML, XML, VULN, ALL).
name | The name of the report in the site | dependency-check or dependency-check:aggregate
outputDirectory | The location to write the report(s). Note, this is not used if generating the report as part of a `mvn site` build | 'target'
skip | Skips the dependency-check analysis | false
skipTestScope | Should be skip analysis for artifacts with Test Scope | true
skipProvidedScope | Should be skip analysis for artifacts with Provided Scope | false
skipRuntimeScope | Should be skip analysis for artifacts with Runtime Scope | false
skipTestScope | Skip analysis for artifacts with Test Scope | true
skipProvidedScope | Skip analysis for artifacts with Provided Scope | false
skipRuntimeScope | Skip analysis for artifacts with Runtime Scope | false
suppressionFile | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html) | &nbsp;
enableExperimental | Enable the [experimental analyzers](../analyzers/index.html). If not enabled the experimental analyzers (see below) will not be loaded or used. | false
Analyzer Configuration
====================
@@ -43,16 +44,16 @@ centralAnalyzerEnabled | Sets whether Central Analyzer will be used. If t
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. | &nbsp;
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
pyDistributionAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Python Distribution Analyzer will be used. | true
pyPackageAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Python Package Analyzer will be used. | true
rubygemsAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Ruby Gemspec Analyzer will be used. | true
opensslAnalyzerEnabled | Sets whether the openssl Analyzer should be used. | true
cmakeAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) CMake Analyzer should be used. | true
autoconfAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) autoconf Analyzer should be used. | true
composerAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) PHP Composer Lock File Analyzer should be used. | true
nodeAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Node.js Analyzer should be used. | true
nuspecAnalyzerEnabled | Sets whether the .NET Nuget Nuspec Analyzer will be used. | true
assemblyAnalyzerEnabled | Sets whether the .NET Assembly Analyzer should be used. | true
pathToMono | The path to Mono for .NET assembly analysis on non-windows systems. | &nbsp;
Advanced Configuration
@@ -78,7 +79,8 @@ metaFileName | Sets the name of the file to use for storing the metadata
Proxy Configuration
====================
Use [Maven's settings](https://maven.apache.org/settings.html#Proxies) to configure a proxy server. If multiple proxies
Use [Maven's settings](https://maven.apache.org/settings.html#Proxies) to configure a proxy server. Please see the
dependency-check [proxy configuration](../data/proxy.html) page for additional problem solving techniques. If multiple proxies
are configured in the Maven settings file you must tell dependency-check which proxy to use with the following property:
Property | Description | Default Value

View File

@@ -20,7 +20,7 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.3.7-SNAPSHOT</version>
<version>1.4.0-SNAPSHOT</version>
</parent>
<artifactId>dependency-check-utils</artifactId>

View File

@@ -189,6 +189,10 @@ public final class Settings {
* The properties key for whether the Jar Analyzer is enabled.
*/
public static final String ANALYZER_JAR_ENABLED = "analyzer.jar.enabled";
/**
* The properties key for whether experimental analyzers are loaded.
*/
public static final String ANALYZER_EXPERIMENTAL_ENABLED = "analyzer.experimental.enabled";
/**
* The properties key for whether the Archive analyzer is enabled.
*/
@@ -317,7 +321,7 @@ public final class Settings {
/**
* Thread local settings.
*/
private static ThreadLocal<Settings> localSettings = new ThreadLocal<Settings>();
private static final ThreadLocal<Settings> LOCAL_SETTINGS = new ThreadLocal<Settings>();
/**
* The properties.
*/
@@ -354,7 +358,7 @@ public final class Settings {
* also call Settings.cleanup() to properly release resources.
*/
public static void initialize() {
localSettings.set(new Settings(PROPERTIES_FILE));
LOCAL_SETTINGS.set(new Settings(PROPERTIES_FILE));
}
/**
@@ -364,7 +368,7 @@ public final class Settings {
* @param propertiesFilePath the path to the base properties file to load
*/
public static void initialize(String propertiesFilePath) {
localSettings.set(new Settings(propertiesFilePath));
LOCAL_SETTINGS.set(new Settings(propertiesFilePath));
}
/**
@@ -393,7 +397,7 @@ public final class Settings {
}
}
try {
localSettings.remove();
LOCAL_SETTINGS.remove();
} catch (Throwable ex) {
LOGGER.debug("Error cleaning up Settings", ex);
}
@@ -405,7 +409,7 @@ public final class Settings {
* @return the Settings object
*/
public static Settings getInstance() {
return localSettings.get();
return LOCAL_SETTINGS.get();
}
/**
@@ -414,7 +418,7 @@ public final class Settings {
* @param instance the instance of the settings object to use in this thread
*/
public static void setInstance(Settings instance) {
localSettings.set(instance);
LOCAL_SETTINGS.set(instance);
}
/**
@@ -460,7 +464,7 @@ public final class Settings {
* @param value the value for the property
*/
public static void setString(String key, String value) {
localSettings.get().props.setProperty(key, value);
LOCAL_SETTINGS.get().props.setProperty(key, value);
LOGGER.debug("Setting: {}='{}'", key, value);
}
@@ -517,7 +521,7 @@ public final class Settings {
* @param value the value for the property
*/
public static void setInt(String key, int value) {
localSettings.get().props.setProperty(key, String.valueOf(value));
LOCAL_SETTINGS.get().props.setProperty(key, String.valueOf(value));
LOGGER.debug("Setting: {}='{}'", key, value);
}
@@ -592,8 +596,8 @@ public final class Settings {
* @throws IOException is thrown when there is an exception loading/merging the properties
*/
public static void mergeProperties(InputStream stream) throws IOException {
localSettings.get().props.load(stream);
logProperties("Properties updated via merge", localSettings.get().props);
LOCAL_SETTINGS.get().props.load(stream);
logProperties("Properties updated via merge", LOCAL_SETTINGS.get().props);
}
/**
@@ -673,7 +677,7 @@ public final class Settings {
* @return the property from the properties file
*/
public static String getString(String key, String defaultValue) {
final String str = System.getProperty(key, localSettings.get().props.getProperty(key, defaultValue));
final String str = System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key, defaultValue));
return str;
}
@@ -707,7 +711,7 @@ public final class Settings {
* @return the property from the properties file
*/
public static String getString(String key) {
return System.getProperty(key, localSettings.get().props.getProperty(key));
return System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key));
}
/**
@@ -716,7 +720,7 @@ public final class Settings {
* @param key the property key to remove
*/
public static void removeProperty(String key) {
localSettings.get().props.remove(key);
LOCAL_SETTINGS.get().props.remove(key);
}
/**

12
pom.xml
View File

@@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.3.7-SNAPSHOT</version>
<version>1.4.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
@@ -100,8 +100,8 @@ Copyright (c) 2012 - Jeremy Long
<url>https://github.com/jeremylong/DependencyCheck/issues</url>
</issueManagement>
<ciManagement>
<system>Cloudbees</system>
<url>https://dependency-check.ci.cloudbees.com/</url>
<system>travis-ci</system>
<url>https://travis-ci.org/jeremylong/DependencyCheck</url>
</ciManagement>
<mailingLists>
<mailingList>
@@ -212,7 +212,7 @@ Copyright (c) 2012 - Jeremy Long
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<version>3.0.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -222,7 +222,7 @@ Copyright (c) 2012 - Jeremy Long
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<version>3.0.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -337,7 +337,7 @@ Copyright (c) 2012 - Jeremy Long
<dependency>
<groupId>org.apache.maven.doxia</groupId>
<artifactId>doxia-module-markdown</artifactId>
<version>1.7.1</version>
<version>1.7</version>
</dependency>
</dependencies>
<configuration>

View File

@@ -13,6 +13,6 @@
^ \* See the License for the specific language governing permissions and\s*$
^ \* limitations under the License\.\s*$
^ \*\s*$
^ \* Copyright \(c\) 201[0-9] (Jeremy Long|Steve Springett|The OWASP Foundation|Institute for Defense Analyses)\. All Rights Reserved\.\s*$
^ \* Copyright \(c\) 201[0-9] (Jeremy Long|Steve Springett|Bianca Jiang|The OWASP Foundation|Institute for Defense Analyses)\. All Rights Reserved\.\s*$
^ \*/\s*$
^package

View File

@@ -1,6 +1,10 @@
Autoconf Analyzer
=================
*Experimental*: This analyzer is considered experimental. While this analyzer may
be useful and provide valid results more testing must be completed to ensure that
the false negative/false positive rates are acceptable.
OWASP dependency-check includes an analyzer that will scan Autoconf project
configuration files. The analyzer will collect as much information it can
about the project. The information collected is internally referred to as

View File

@@ -1,6 +1,10 @@
CMake Analyzer
==============
*Experimental*: This analyzer is considered experimental. While this analyzer may
be useful and provide valid results more testing must be completed to ensure that
the false negative/false positive rates are acceptable.
OWASP dependency-check includes an analyzer that will scan CMake project
configuration files. The analyzer will collect as much information it can
about the project. The information collected is internally referred to as

View File

@@ -1,6 +1,10 @@
Composer Lock Analyzer
==============
*Experimental*: This analyzer is considered experimental. While this analyzer may
be useful and provide valid results more testing must be completed to ensure that
the false negative/false positive rates are acceptable.
OWASP dependency-check includes an analyzer that scans composer.lock files to get exact dependency
version information from PHP projects which are managed with [Composer](http://getcomposer.org/).
If you're using Composer to manage your project, this will only analyze the `composer.lock` file

View File

@@ -7,14 +7,24 @@ to extract identification information from the files analyzed.
| -------- | ------------------ | --------------- |
| [Archive](./archive-analyzer.html) | Zip archive format (\*.zip, \*.ear, \*.war, \*.jar, \*.sar, \*.apk, \*.nupkg); Tape Archive Format (\*.tar); Gzip format (\*.gz, \*.tgz); Bzip2 format (\*.bz2, \*.tbz2) | Extracts archive contents, then scans contents with all available analyzers. |
| [Assembly](./assembly-analyzer.html) | .NET Assemblies (\*.exe, \*.dll) | Uses [GrokAssembly.exe](https://github.com/colezlaw/GrokAssembly), which requires .NET Framework or Mono runtime to be installed. |
| [Autoconf](./autoconf.html) | Autoconf project configuration files (configure, configure.in, configure.ac) | [Regex](https://en.wikipedia.org/wiki/Regular_expression) scan for AC_INIT metadata, including in generated configuration script. |
| [Central](./central-analyzer.html) | Java archive files (\*.jar) | Searches Maven Central or a configured Nexus repository for the file's SHA1 hash. |
| [CMake](./cmake.html) | CMake project files (CMakeLists.txt) and scripts (\*.cmake) | Regex scan for project initialization and version setting commands. |
| [Composer Lock](./composer-lock.html) | PHP [Composer](http://getcomposer.org) Lock files (composer.lock) | Parses PHP [Composer](http://getcomposer.org) lock files for exact versions of dependencies. |
| [Jar](./jar-analyzer.html) | Java archive files (\*.jar); Web application archive (\*.war) | Examines archive manifest metadata, and Maven Project Object Model files (pom.xml). |
| [Nexus](./nexus-analyzer.html) | Java archive files (\*.jar) | Searches Sonatype or a configured Nexus repository for the file's SHA1 hash. In most cases, superceded by Central . |
| [Node.js](./nodejs.html) | NPM package specification files (package.json) | Parse JSON format for metadata. |
| [Nuspec](./nuspec-analyzer.html) | Nuget package specification file (\*.nuspec) | Uses XPath to parse specification XML. |
| [OpenSSL](./openssl.html) | OpenSSL Version Source Header File (opensslv.h) | Regex parse of the OPENSSL_VERSION_NUMBER macro definition. |
Experimental Analyzers
----------------------
The following analyzers can be enabled by enabling the _experimental_ configuration
option; see the documentation for the CLI, Ant, Maven, etc. for more information.
These analyzers are considered experimental due to the higher false positive and
false negative rates. Even though these are marked as experimental
several teams have found them useful in their current state.
| Analyzer | File Types Scanned | Analysis Method |
| -------- | ------------------ | --------------- |
| [Autoconf](./autoconf.html) | Autoconf project configuration files (configure, configure.in, configure.ac) | [Regex](https://en.wikipedia.org/wiki/Regular_expression) scan for AC_INIT metadata, including in generated configuration script. |
| [CMake](./cmake.html) | CMake project files (CMakeLists.txt) and scripts (\*.cmake) | Regex scan for project initialization and version setting commands. |
| [Composer Lock](./composer-lock.html) | PHP [Composer](http://getcomposer.org) Lock files (composer.lock) | Parses PHP [Composer](http://getcomposer.org) lock files for exact versions of dependencies. |
| [Node.js](./nodejs.html) | NPM package specification files (package.json) | Parse JSON format for metadata. |
| [Python](./python.html) | Python source files (\*.py); Package metadata files (PKG-INFO, METADATA); Package Distribution Files (\*.whl, \*.egg, \*.zip) | Regex scan of Python source files for setuptools metadata; Parse RFC822 header format for metadata in all other artifacts. |
| [Ruby Gemspec](./ruby-gemspec.html) | Ruby makefiles (Rakefile); Ruby Gemspec files (\*.gemspec) | Regex scan Gemspec initialization blocks for metadata. |
| [Ruby Gemspec](./ruby-gemspec.html) | Ruby makefiles (Rakefile); Ruby Gemspec files (\*.gemspec) | Regex scan Gemspec initialization blocks for metadata. |

View File

@@ -1,6 +1,10 @@
Node.js Analyzer
================
*Experimental*: This analyzer is considered experimental. While this analyzer may
be useful and provide valid results more testing must be completed to ensure that
the false negative/false positive rates are acceptable.
OWASP dependency-check includes an analyzer that will scan [Node Package Manager](https://www.npmjs.com/)
package specification files. The analyzer will collect as much information as
it can about the package. The information collected is internally referred to
@@ -8,7 +12,7 @@ as evidence and is grouped into vendor, product, and version buckets. Other
analyzers later use this evidence to identify any Common Platform Enumeration
(CPE) identifiers that apply.
Note:_Consider using [Retire.js](http://retirejs.github.io/retire.js/) or the
*Note*: Consider using [Retire.js](http://retirejs.github.io/retire.js/) or the
Node Security Project auditing tool, [nsp](https://nodesecurity.io/tools) instead
of, or in addition to OWASP dependency-check to analyze Node.js packages.

View File

@@ -1,6 +1,10 @@
Python Analyzer
==============
*Experimental*: This analyzer is considered experimental. While this analyzer may
be useful and provide valid results more testing must be completed to ensure that
the false negative/false positive rates are acceptable.
OWASP dependency-check includes an analyzer that will scan Python artifacts.
The analyzer(s) will collect as much information it can about the Python
artifacts. The information collected is internally referred to as evidence and

View File

@@ -1,6 +1,10 @@
Ruby Gemspec Analyzer
=====================
*Experimental*: This analyzer is considered experimental. While this analyzer may
be useful and provide valid results more testing must be completed to ensure that
the false negative/false positive rates are acceptable.
OWASP dependency-check includes an analyzer that will scan [Ruby Gem](https://rubygems.org/)
[specifications](http://guides.rubygems.org/specification-reference/). The
analyzer will collect as much information as it can about the Gem. The
@@ -9,7 +13,7 @@ into vendor, product, and version buckets. Other analyzers later use this
evidence to identify any Common Platform Enumeration (CPE) identifiers that
apply.
Note: It is highly recommended that Ruby projects use
*Note*: It is highly recommended that Ruby projects use
[bundler-audit](https://github.com/rubysec/bundler-audit#readme).
Files Types Scanned: Rakefile, \*.gemspec

View File

@@ -29,4 +29,7 @@ contained within the JAR file itself, contain evidence that is used to accuratel
a library. If Central cannot be reached, it is highly recommended to setup a
Nexus server within your organization and to configure dependency-check to use the local
Nexus server. **Note**, even with a Nexus server setup I have seen dependency-check be
re-directed to other repositories on the Internet to download the actual POM file.
re-directed to other repositories on the Internet to download the actual POM file; this
happened due to a rare circumstance where the Nexus instance used by dependency-check
was not the instance of Nexus used to build the application (i.e. the dependencies
were not actually present in the Nexus used by dependency-check).

View File

@@ -9,3 +9,25 @@ to use a proxy to connect to the Internet. See the configuration settings for ea
Note, it may also be possible to use the core [Java proxy](https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html)
system properties instead of the configuration above.
Certificate Errors
------------------
In some cases if you setup a proxy the connection may still fail due to certificate
errors (see the log file from dependency-check). If you know which cert it's failing
on (either your proxy or NVD/CVE) you can either add the certificate itself or the
signing chain to your trust store. If you don't have access to modify the system
trust store (in $JAVA_HOME/lib/security/cacerts) you can copy it elsewhere and
import it using keytool, then specify that trust store on the command line
(`mvn -Djavax.net.ssl.trustStore=/path/to/cacerts`) or if you need to always
have that set, you can set the environment variable `JAVA_TOOL_OPTIONS` to have
`-Djavax.net.ssl.trustStore=/path/to/cacerts`.
Still failing?
--------------
In some cases the proxy is configured to block `HEAD` requests. While an attempt
is made by dependency-check to identify this situation it does not appear to be
100% successful. As such, the last thing to try is to add the property
`mvn -Ddownloader.quick.query.timestamp=false`.
If trying the above and it still fails please open a ticket in the
[github repo](https://github.com/jeremylong/DependencyCheck/issues).

View File

@@ -34,7 +34,7 @@ dependencyCheck {
Property | Description | Default Value
------------------|------------------------------------|------------------
server | The proxy server. | &nbsp;
server | The proxy server; see the [proxy configuration](../data/proxy.html) page for more information. | &nbsp;
port | The proxy port. | &nbsp;
username | Defines the proxy user name. | &nbsp;
password | Defines the proxy password. | &nbsp;
@@ -87,6 +87,7 @@ analyzers is likely not needed.
Property | Description | Default Value
----------------------|---------------------------------------------------------------------------|------------------
experimentalEnabled | Sets whether the [experimental analyzers](../analyzers/index.html) will be used. If not set to true the analyzers marked as experimental (see below) will not be used | false
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. | &nbsp;
jarEnabled | Sets whether Jar Analyzer will be used. | true
@@ -94,14 +95,14 @@ centralEnabled | Sets whether Central Analyzer will be used. If this anal
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. | &nbsp;
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
pyDistributionEnabled | Sets whether the [experimental](../analyzers/index.html) Python Distribution Analyzer will be used. | true
pyPackageEnabled | Sets whether the [experimental](../analyzers/index.html) Python Package Analyzer will be used. | true
rubygemsEnabled | Sets whether the [experimental](../analyzers/index.html) 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
cmakeEnabled | Sets whether or not the [experimental](../analyzers/index.html) CMake Analyzer should be used. | true
autoconfEnabled | Sets whether or not the [experimental](../analyzers/index.html) autoconf Analyzer should be used. | true
composerEnabled | Sets whether or not the [experimental](../analyzers/index.html) PHP Composer Lock File Analyzer should be used. | true
nodeEnabled | Sets whether or not the [experimental](../analyzers/index.html) 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. | &nbsp;

View File

@@ -2,11 +2,14 @@ About
====================
OWASP dependency-check is an open source solution the OWASP Top 10 2013 entry:
[A9 - Using Components with Known Vulnerabilities](https://www.owasp.org/index.php/Top_10_2013-A9-Using_Components_with_Known_Vulnerabilities).
Dependency-check can currently be used to scan Java, .NET, Python, Ruby (gemspec), PHP (composer), and
Node.js applications (and their dependent libraries) to identify known
vulnerable components. In addition, Dependency-check can be used to scan some
source code, including OpenSSL source code and projects that use
[Autoconf](https://www.gnu.org/software/autoconf/) or
Dependency-check can currently be used to scan Java and .NET applications to
identify the use of known vulnerable components. Experimental analyzers for
Python, Ruby, PHP (composer), and Node.js applications; these are experimental
due to the possible false positive and false negative rates. To use the experimental
analyzers they must be specifically enabled via the appropriate _experimental_
configuration. In addition, dependency-check has experimental analyzers that can
be used to scan some C/C++ source code, including OpenSSL source code and projects
that use [Autoconf](https://www.gnu.org/software/autoconf/) or
[CMake](http://www.cmake.org/overview/).
The problem with using known vulnerable components was covered in a paper by
@@ -30,3 +33,10 @@ OWASP dependency-check's core analysis engine can be used as:
- [Ant Task](dependency-check-ant/index.html)
- [Gradle Plugin](dependency-check-gradle/index.html)
- [Jenkins Plugin](dependency-check-jenkins/index.html)
For help with dependency-check the following resource can be used:
- Post to the [google group](https://groups.google.com/forum/#!forum/dependency-check):
[subscribe](mailto://dependency-check+subscribe@googlegroups.com),
[post](mailto://dependency-check@googlegroups.com),
- Open a [github issue](https://github.com/jeremylong/DependencyCheck/issues)

View File

@@ -57,10 +57,6 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
title="developed using" width="170px"
alt="developed using"
img="http://jeremylong.github.io/DependencyCheck/images/logos/logo_intellij_idea.png"/>
<logo name="Cloudbees" href="http://www.cloudbees.com/"
title="built on cloudbees"
alt="built on cloudbees"
img="http://jeremylong.github.io/DependencyCheck/images/logos/Button-Built-on-CB-1.png"/>
</poweredBy>
<body>