Compare commits

..

75 Commits

Author SHA1 Message Date
Jeremy Long
848be0db6c version 1.2.2
Former-commit-id: 8da06e1a2f4b41bccc22105d7bc758442bb14e57
2014-06-22 21:31:58 -04:00
Jeremy Long
0f9da0731e updated text
Former-commit-id: 7749b9ec6b0ce9502e1c7129bdec902ce5b43595
2014-06-22 21:22:32 -04:00
Jeremy Long
8bc2364cce added site information to the dependency-check utils
Former-commit-id: 7d8c4c3c2b98e0d492f4447e5f1dc1f071a2241a
2014-06-22 19:56:14 -04:00
Jeremy Long
b64916ce3f added file analyzer documentation
Former-commit-id: c0c29021cd1197f26942ff36c8b63220d1267c21
2014-06-22 19:55:21 -04:00
Jeremy Long
452955667c checkstyle correction
Former-commit-id: e5a891ea5b438e64e8a3aa5e697cb859d1a1f09a
2014-06-22 19:54:25 -04:00
Jeremy Long
f38bbf4cc7 minor javadoc correction
Former-commit-id: 45e621682304820fe17c17e92bd0aa5ac5dfd023
2014-06-22 19:53:59 -04:00
Jeremy Long
25eaa11a52 updated description
Former-commit-id: c8cb8b041ce351c2d33a3621f772e75d02950193
2014-06-22 19:53:38 -04:00
Jeremy Long
4b4da8d467 checkstyle/pmd/etc. corrections
Former-commit-id: 59883bd0b03c8690ce9a20120eafefe7c61384cd
2014-06-22 19:03:33 -04:00
Jeremy Long
13116c5381 added support for suppression by GAV (issue #124), created base suppression.xml (issue #123), and fixed false positives related to spring security (issue #130)
Former-commit-id: 330134211d022fec336dc1ca39205a94a088ee84
2014-06-22 16:34:39 -04:00
Jeremy Long
d2cd406a62 added additional test resources
Former-commit-id: b788c7420b82d8a108cd2335c536be667c2ab293
2014-06-22 16:32:48 -04:00
Jeremy Long
acbce05fbf updated to support suppression by maven coordinates (GAV) per issue #124
Former-commit-id: 3cff74ded9b0c352fb1d45e784d89c3c20f55467
2014-06-20 06:47:46 -04:00
Jeremy Long
bee4d3a338 fixed bug that left false positive, previously fixed, due to the file name modifications that the archive analyzer makes - regex needed updating to not just look for the start of the filename
Former-commit-id: 922a9edaf9123524585b97e6cb9f8efd4a389031
2014-06-14 07:04:02 -04:00
Jeremy Long
bce226002b added data.zip back after cleaning up history
Former-commit-id: 6d227bf38e8023eeb134c965f48fbf859aeb9600
2014-06-01 11:31:09 -04:00
Jeremy Long
a417db7c7a updated documentation to replace deprecated proxyUrl with proxyServer
Former-commit-id: 165e14fcb6b57d8a522875eaa65f5ee766c9b1af
2014-05-31 06:43:07 -04:00
Jeremy Long
0ffef12a8b deprecated the proxyUrl field replacing it with proxyServer; getter and setter for proxyUrl now just wrap proxyServer
Former-commit-id: 5f1fbdf2eda6f05252f81dd8bf7acd44c01b7b6f
2014-05-31 06:42:27 -04:00
Jeremy Long
4539b040e0 deprecated proxyUrl and replaced it with proxyServer
Former-commit-id: 3330de9b2c36742a0b93d478b7dadaccea00cd4a
2014-05-31 06:39:36 -04:00
Jeremy Long
f85014a86d deprecated proxyUrl and replaced it with proxyServer - using the deprecated configuration will still work but will generate a warning
Former-commit-id: d9ff32d6b6e2f4d088f95d52ee33f1d0df3457fd
2014-05-31 06:38:50 -04:00
Jeremy Long
d90d07c68b added code to disable the analyzer if initialization fails
Former-commit-id: 202baa329f07fb24921ce83660d596d46b71b663
2014-05-30 05:26:03 -04:00
Jeremy Long
ce292b84fa fixed spelling error in property name
Former-commit-id: 106e8e9128bc371ff78f3a73c3f0da6012761cba
2014-05-30 05:25:20 -04:00
Jeremy Long
01690860db renamed PROXY_URL to PROXY_SERVER to avoid confusion
Former-commit-id: 1fbc025fba68aff644a8b8582657e5ef30024a24
2014-05-24 07:06:59 -04:00
Jeremy Long
89fb2d4915 fixed error messages and added status code checks
Former-commit-id: d21ff11466908f07ca02a50269f08d76f16a243e
2014-05-24 07:06:46 -04:00
Jeremy Long
5cc3a42832 renamed PROXY_URL to PROXY_SERVER to avoid confusion
Former-commit-id: 730eebed21baddfbd90c42a95769f8781de95b56
2014-05-24 07:05:05 -04:00
Jeremy Long
60b0145e04 added a new initialize method that accepts a properties file path to load to make the class more versatile
Former-commit-id: 00ec19b51a20c4ce3329a7c3c075a1f3ba16859e
2014-05-21 06:42:43 -04:00
Jeremy Long
ce48823d38 Moved some of the utility classes from core to a new utils module
Former-commit-id: 2e6ff9631ff4c843f10db1e022e41e728394e420
2014-05-21 06:29:46 -04:00
Jeremy Long
d43fee5585 renamed CallableDownloadTask to DownloadTask
Former-commit-id: 4ed8987945722d99e0f23b2f379321a652f76348
2014-05-20 21:08:15 -04:00
Jeremy Long
5dc9e51dd4 fixed test cases
Former-commit-id: 081ea17023cef3313ce59dbf8ce7f2a8cff706eb
2014-05-17 08:04:20 -04:00
Jeremy Long
235fcccbd7 if maven identifier already exists we now update it with a hyperlink instead of adding a new one - the Jar analyzer may add a maven identifier based on the pom.xml
Former-commit-id: db0ae1145d000089fb10e0357566f03632a559b9
2014-05-17 08:04:03 -04:00
Jeremy Long
91c971b8fd cleaned up pom evidence collection and added a maven identifier if the GAV is available from the pom.xml
Former-commit-id: 0400863fea2cfe86a5601b3ae134e7e98a4b29c7
2014-05-17 08:03:04 -04:00
Jeremy Long
e43003cadc fixed false positives related to Apache POI and MS Office CPE/CVE per issue #126
Former-commit-id: cfde8d86cb339a9f2cf0b8c1f72f5ca198efab8a
2014-05-14 19:17:47 -04:00
Jeremy Long
9a96165655 Update JarAnalyze to resolve issue #127
Updated JarAnalyzer to resolve issue #127 - duplicate package and package name evidence in the report.

Former-commit-id: 067643f7e99a7a4f36438b18c07e92a5e8544089
2014-05-14 18:01:12 -04:00
Jeremy Long
994aef411c updated version to 1.2.2-SNAPSHOT
Former-commit-id: e1b07457515dcab0f00c6a0b36fadb58ecc3deeb
2014-05-10 08:41:37 -04:00
Jeremy Long
094a180935 updated to release version 1.2.1
Former-commit-id: d908eed4538f0928c8b108348d9d46ce6d2f57e0
2014-05-10 08:32:34 -04:00
Jeremy Long
74e9de6370 updated sample report
Former-commit-id: c55ddb623e21f046c90493b0724f7eb34225ea29
2014-05-10 07:25:42 -04:00
Jeremy Long
c7f31b3d79 fixed typo in log statement
Former-commit-id: 08192210f3c5bb322160fba678a56acb36af3198
2014-05-10 07:23:18 -04:00
Jeremy Long
98d0239d03 pmd correction to logger
Former-commit-id: 3c3b26ec8fbf4d2602c681ff02f460fe7e712914
2014-05-10 07:16:50 -04:00
Jeremy Long
ffeab147ce checkstyle corrections
Former-commit-id: f9ae61d41ba01b6931892a339a9b701ae3c91ce2
2014-05-10 07:13:07 -04:00
Jeremy Long
90bdbd6b84 updated version of presentation
Former-commit-id: ec47594f35f5cca92888e6c8578b0d123d31b898
2014-05-10 07:12:56 -04:00
Jeremy Long
e29dd3cd33 added additional test file
Former-commit-id: 8487a2f4ba7287f54f0b5f69bc39e63bee455172
2014-05-10 07:01:24 -04:00
Jeremy Long
23b95178ff updated to remove archive files from the list of dependencies - additionally, if a zip file appears to be a jar it will now make a copy of the zip and scan it as a jar
Former-commit-id: d927daea530abad2d578dbe0ff38b97d044b4775
2014-05-10 07:00:43 -04:00
Jeremy Long
9bde80357f patch to remove additional false positives due to SCM entries in the pom
Former-commit-id: 6101fae1b5957254ddbece5afc2db8edeb7bf9b8
2014-05-10 06:59:34 -04:00
Jeremy Long
1485733715 updated to use displayFileName field instead of FileName when writing information about dependencies
Former-commit-id: bd3383ac4831bc44db6b63083e47802cce04b520
2014-05-10 06:58:51 -04:00
Jeremy Long
d125a7f09d added displayFileName field to the dependency class
Former-commit-id: 248f5397d37ea6e2f333dc0fe357188865bdb446
2014-05-10 06:57:44 -04:00
Jeremy Long
77486dffd4 removed additional false positives as part of patch for issue #93 and #119
Former-commit-id: 86f48b30150f2ba4db99dfc2eb15a0ac50a6e383
2014-05-10 06:56:53 -04:00
Jeremy Long
c84bcb433f fixed spelling error
Former-commit-id: d3aed24d6691b58ef132e00f9827e27fceb9fc73
2014-05-07 19:33:59 -04:00
Jeremy Long
f1e5221257 Merge pull request #122 from colezlaw/master
Fixed logging order of GrokAssembly for bad assemblies. Using resources ...

Former-commit-id: 65a41d23df6ccfa8c4f05235da3d7c613e4290a0
2014-05-07 19:31:59 -04:00
Jeremy Long
b8bf01acc3 added checks before warning that a file could not be deleted
Former-commit-id: 098ea1889b49ade0c73385919906398c86627ab2
2014-05-07 19:31:21 -04:00
Jeremy Long
65aa7bd1de fixed display bug when only one CPE exists for a given CVE
Former-commit-id: 18535dc408a51e516626ec4c43a3e72b01fd28f0
2014-05-07 19:30:45 -04:00
Jeremy Long
6f511444a7 fixed display bug when only one CPE exists for a given CVE
Former-commit-id: 3b791d0a0fbe2587390e048cffc4453567ddf74a
2014-05-07 19:29:52 -04:00
Jeremy Long
ef5174d89f fixed bug causing vulnerabilities to be missed
Former-commit-id: 5c6421ea8475db16f7184340fa5b8b2033d53b29
2014-05-07 07:05:37 -04:00
Jeremy Long
e2a97e75d8 moved duplicated code to a method
Former-commit-id: f6cb80dc56ef86294f2490729bb84658d98e6c9a
2014-05-07 07:03:38 -04:00
Jeremy Long
9fc6e265eb fixed off by one string truncation issue
Former-commit-id: f25894627402e9e2d310b25163dae7d7db1457d9
2014-05-07 07:03:02 -04:00
Will Stranathan
f81c42b1fd Fixed logging order of GrokAssembly for bad assemblies. Using resources for logging
Former-commit-id: 611d665c7f5312462c19c8dcf8e87dc672184f67
2014-05-03 19:12:39 -04:00
Jeremy Long
8594e146eb updates to help resolve issue 119
Former-commit-id: c8778008b91b7999cb8d88382efe8a83ebe87102
2014-05-03 14:46:48 -04:00
Jeremy Long
cda0dfdafe updated test case and related data
Former-commit-id: 513602f48b6d599b43848f0a88537190084e9cbf
2014-05-03 12:30:29 -04:00
Jeremy Long
363568b02c updated to begin fixes for issue #90 and #119
Former-commit-id: 1ceae6236ecd83e15f91ddab549027082e269e0b
2014-05-03 12:30:07 -04:00
Jeremy Long
443ab02788 added local copies of the NVD CVE data to speed up some of the test cases
Former-commit-id: 54a264872bf151034706f6ed52de3a99ed961b04
2014-05-03 11:02:23 -04:00
Jeremy Long
65784d6dc4 updated to use local copy of data files to speedup the test case
Former-commit-id: 5bb1d67156500ba74124ced18bcae599e4c5dc7a
2014-05-03 11:01:31 -04:00
Jeremy Long
da805d037f removed duplicative test
Former-commit-id: e403e85cef541416ccb3cf13704d019f4c2b5f92
2014-05-03 11:00:48 -04:00
Jeremy Long
d383776245 added additional informational log statements
Former-commit-id: 9dfe02f737cffc05838dcffeec1cfca77c3100e1
2014-05-03 11:00:21 -04:00
Jeremy Long
51eba8da73 updated settings cleanup to prevent issue with the update process
Former-commit-id: e883b7d37c583b581b41da368dbe9b8d1bafae89
2014-05-03 10:59:47 -04:00
Jeremy Long
14b4d64244 updated the URL for the NVD CVE external link
Former-commit-id: 18cd71abd7a1f0d94dde8dba2a3076b28405ab00
2014-05-03 10:58:41 -04:00
Jeremy Long
7cb7f68cda updated the URL for the NVD CVE external link
Former-commit-id: 83ad77fb9fe6029fdb95ba7ffc96663d88234631
2014-05-03 10:58:16 -04:00
Jeremy Long
83300d028b updated the URL for the NVD CVE external link
Former-commit-id: 7527c31dab810145d8aebc1225ba302aca9fc80e
2014-05-03 10:57:44 -04:00
Jeremy Long
e891ce39c0 updated settings cleanup to prevent issue with the update process
Former-commit-id: 3452aec55b778224e10879175e1aba8060da4e42
2014-05-03 10:55:56 -04:00
Jeremy Long
e58b7782ac updated settings cleanup to prevent issue with the update process
Former-commit-id: 07122c535d47f3f414659013555fa826ce0e9b9c
2014-05-03 10:55:15 -04:00
Jeremy Long
1ddb468a08 applied part of PR for issue #121 - classpath issue with some invocations of the ant client
Former-commit-id: 129a5fd9cd55c8a0abf393d0ae8405ddec412d51
2014-05-03 09:54:11 -04:00
Jeremy Long
95e3f0e0d9 added additional dependencies for testing
Former-commit-id: 99be1ef0f35f040ca13b204e2a1689cbaa3cf41a
2014-05-03 09:52:57 -04:00
Jeremy Long
0edf017ddc patched for issue #120 - duplicate evidence listed in reports
Former-commit-id: 3cdc1854af586029911b70fb4b8ff54669bac022
2014-05-03 08:52:45 -04:00
Jeremy Long
ad601fd1ee Merge branch 'bkimminich-master'
Former-commit-id: d4f3bd1ebe5237060251b1f81111b26b5f653f65
2014-04-30 19:23:23 -04:00
Jeremy Long
e7eaccb5e0 Merge branch 'master' of github.com:bkimminich/DependencyCheck into bkimminich-master
Former-commit-id: 7fe67ea5fa1b94824d2f2c8df5bd099d89dbaf85
2014-04-30 19:23:13 -04:00
Jeremy Long
6b201da3ff version 1.2.1-SNAPSHOT
Former-commit-id: 62ed08de9077505ef8e5350b0470eb5c61089dc3
2014-04-30 18:30:46 -04:00
Jeremy Long
a85a47bc20 fixed issue #118
Former-commit-id: dceb807f182be921c2d85338c1d8192361dc2c1f
2014-04-30 18:13:04 -04:00
Björn Kimminich
0d943ba805 Update AbstractSuppressionAnalyzerTest.java
Former-commit-id: 640d50086e6b5cd9302ca4a24ffed881c614fd54
2014-04-29 14:37:52 +02:00
Björn Kimminich
56fe3b5892 simplified exception testing
Former-commit-id: f43f211c4cc3133e5dfc466a4badfb3606a3be0c
2014-04-29 14:29:46 +02:00
Björn Kimminich
c177f12e1d added test case for classpath suppression file and missing file
Former-commit-id: 975cbe1f480ad52b0e527148c4fd30b76d5baa0e
2014-04-29 11:48:07 +02:00
82 changed files with 27021 additions and 5516 deletions

View File

@@ -21,12 +21,10 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.0</version>
<version>1.2.2</version>
</parent>
<artifactId>dependency-check-ant</artifactId>
<version>1.2.0.1</version>
<packaging>jar</packaging>
<name>Dependency-Check Ant Task</name>
@@ -441,6 +439,11 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
<artifactId>dependency-check-core</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-utils</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-core</artifactId>

View File

@@ -285,26 +285,50 @@ public class DependencyCheckTask extends Task {
this.reportFormat = reportFormat.getValue();
}
/**
* The Proxy URL.
* The Proxy Server.
*/
private String proxyUrl;
private String proxyServer;
/**
* Get the value of proxyUrl.
* Get the value of proxyServer.
*
* @return the value of proxyUrl
* @return the value of proxyServer
*/
public String getProxyUrl() {
return proxyUrl;
public String getProxyServer() {
return proxyServer;
}
/**
* Set the value of proxyUrl.
* Set the value of proxyServer.
*
* @param proxyUrl new value of proxyUrl
* @param server new value of proxyServer
*/
public void setProxyServer(String server) {
this.proxyServer = server;
}
/**
* Get the value of proxyServer.
*
* @return the value of proxyServer
* @deprecated use {@link org.owasp.dependencycheck.taskdefs.DependencyCheckTask#getProxyServer()} instead
*/
@Deprecated
public String getProxyUrl() {
return proxyServer;
}
/**
* Set the value of proxyServer.
*
* @param proxyUrl new value of proxyServer
* @deprecated use {@link org.owasp.dependencycheck.taskdefs.DependencyCheckTask#setProxyServer(java.lang.String)}
* instead
*/
@Deprecated
public void setProxyUrl(String proxyUrl) {
this.proxyUrl = proxyUrl;
LOGGER.warning("A deprecated configuration option 'proxyUrl' was detected; use 'proxyServer' instead.");
this.proxyServer = proxyUrl;
}
/**
* The Proxy Port.
@@ -866,7 +890,7 @@ public class DependencyCheckTask extends Task {
Engine engine = null;
try {
engine = new Engine();
engine = new Engine(DependencyCheckTask.class.getClassLoader());
for (Resource resource : path) {
final FileProvider provider = resource.as(FileProvider.class);
@@ -912,7 +936,7 @@ public class DependencyCheckTask extends Task {
LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
LOGGER.log(Level.FINE, "", ex);
} finally {
Settings.cleanup();
Settings.cleanup(true);
if (engine != null) {
engine.cleanup();
}
@@ -935,7 +959,7 @@ public class DependencyCheckTask extends Task {
/**
* 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.
* properties required to change the proxy server, port, and connection timeout.
*/
private void populateSettings() {
Settings.initialize();
@@ -967,8 +991,8 @@ public class DependencyCheckTask extends Task {
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
if (proxyUrl != null && !proxyUrl.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_URL, proxyUrl);
if (proxyServer != null && !proxyServer.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_SERVER, proxyServer);
}
if (proxyPort != null && !proxyPort.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort);

View File

@@ -32,7 +32,7 @@ failBuildOnCVSS | Specifies if the build should be failed if a CVSS score a
format | The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the Site plugin unless the externalReport is set to true. | HTML
logFile | The file path to write verbose logging information. | &nbsp;
suppressionFile | The file path to the XML suppression file \- used to suppress [false positives](../suppression.html) | &nbsp;
proxyUrl | The Proxy URL. | &nbsp;
proxyServer | The Proxy Server. | &nbsp;
proxyPort | The Proxy Port. | &nbsp;
proxyUsername | Defines the proxy user name. | &nbsp;
proxyPassword | Defines the proxy password. | &nbsp;

View File

@@ -45,7 +45,7 @@ public class DependencyCheckTaskTest extends BuildFileTest {
public void tearDown() {
//no cleanup...
//executeTarget("cleanup");
Settings.cleanup();
Settings.cleanup(true);
}
/**

View File

@@ -21,7 +21,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.0</version>
<version>1.2.2</version>
</parent>
<artifactId>dependency-check-cli</artifactId>
@@ -341,5 +341,10 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
<artifactId>dependency-check-core</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-utils</artifactId>
<version>${project.parent.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -62,7 +62,7 @@ public class App {
final App app = new App();
app.run(args);
} finally {
Settings.cleanup();
Settings.cleanup(true);
}
}
@@ -161,7 +161,7 @@ public class App {
final boolean autoUpdate = cli.isAutoUpdate();
final String connectionTimeout = cli.getConnectionTimeout();
final String proxyUrl = cli.getProxyUrl();
final String proxyServer = cli.getProxyServer();
final String proxyPort = cli.getProxyPort();
final String proxyUser = cli.getProxyUsername();
final String proxyPass = cli.getProxyPassword();
@@ -212,8 +212,8 @@ public class App {
Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
}
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
if (proxyUrl != null && !proxyUrl.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_URL, proxyUrl);
if (proxyServer != null && !proxyServer.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_SERVER, proxyServer);
}
if (proxyPort != null && !proxyPort.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort);

View File

@@ -19,6 +19,7 @@ package org.owasp.dependencycheck.cli;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.logging.Logger;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
@@ -39,6 +40,10 @@ import org.owasp.dependencycheck.utils.Settings;
*/
public final class CliParser {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(CliParser.class.getName());
/**
* The command line.
*/
@@ -85,16 +90,16 @@ public final class CliParser {
*/
private void validateArgs() throws FileNotFoundException, ParseException {
if (isRunScan()) {
validatePathExists(getScanFiles(), ArgumentName.SCAN);
validatePathExists(getReportDirectory(), ArgumentName.OUT);
validatePathExists(getScanFiles(), ARGUMENT.SCAN);
validatePathExists(getReportDirectory(), ARGUMENT.OUT);
if (getPathToMono() != null) {
validatePathExists(getPathToMono(), ArgumentName.PATH_TO_MONO);
validatePathExists(getPathToMono(), ARGUMENT.PATH_TO_MONO);
}
if (!line.hasOption(ArgumentName.APP_NAME)) {
if (!line.hasOption(ARGUMENT.APP_NAME)) {
throw new ParseException("Missing 'app' argument; the scan cannot be run without the an application name.");
}
if (line.hasOption(ArgumentName.OUTPUT_FORMAT)) {
final String format = line.getOptionValue(ArgumentName.OUTPUT_FORMAT);
if (line.hasOption(ARGUMENT.OUTPUT_FORMAT)) {
final String format = line.getOptionValue(ARGUMENT.OUTPUT_FORMAT);
try {
Format.valueOf(format);
} catch (IllegalArgumentException ex) {
@@ -150,7 +155,7 @@ public final class CliParser {
final Options options = new Options();
addStandardOptions(options);
addAdvancedOptions(options);
addDeprecatedOptions(options);
return options;
}
@@ -162,44 +167,44 @@ public final class CliParser {
*/
@SuppressWarnings("static-access")
private void addStandardOptions(final Options options) throws IllegalArgumentException {
final Option help = new Option(ArgumentName.HELP_SHORT, ArgumentName.HELP, false,
final Option help = new Option(ARGUMENT.HELP_SHORT, ARGUMENT.HELP, false,
"Print this message.");
final Option advancedHelp = OptionBuilder.withLongOpt(ArgumentName.ADVANCED_HELP)
final Option advancedHelp = OptionBuilder.withLongOpt(ARGUMENT.ADVANCED_HELP)
.withDescription("Print the advanced help message.").create();
final Option version = new Option(ArgumentName.VERSION_SHORT, ArgumentName.VERSION,
final Option version = new Option(ARGUMENT.VERSION_SHORT, ARGUMENT.VERSION,
false, "Print the version information.");
final Option noUpdate = new Option(ArgumentName.DISABLE_AUTO_UPDATE_SHORT, ArgumentName.DISABLE_AUTO_UPDATE,
final Option noUpdate = new Option(ARGUMENT.DISABLE_AUTO_UPDATE_SHORT, ARGUMENT.DISABLE_AUTO_UPDATE,
false, "Disables the automatic updating of the CPE data.");
final Option appName = OptionBuilder.withArgName("name").hasArg().withLongOpt(ArgumentName.APP_NAME)
final Option appName = OptionBuilder.withArgName("name").hasArg().withLongOpt(ARGUMENT.APP_NAME)
.withDescription("The name of the application being scanned. This is a required argument.")
.create(ArgumentName.APP_NAME_SHORT);
.create(ARGUMENT.APP_NAME_SHORT);
final Option path = OptionBuilder.withArgName("path").hasArg().withLongOpt(ArgumentName.SCAN)
final Option path = OptionBuilder.withArgName("path").hasArg().withLongOpt(ARGUMENT.SCAN)
.withDescription("The path to scan - this option can be specified multiple times. To limit the scan"
+ " to specific file types *.[ext] can be added to the end of the path.")
.create(ArgumentName.SCAN_SHORT);
.create(ARGUMENT.SCAN_SHORT);
final Option props = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.PROP)
final Option props = OptionBuilder.withArgName("file").hasArg().withLongOpt(ARGUMENT.PROP)
.withDescription("A property file to load.")
.create(ArgumentName.PROP_SHORT);
.create(ARGUMENT.PROP_SHORT);
final Option out = OptionBuilder.withArgName("folder").hasArg().withLongOpt(ArgumentName.OUT)
final Option out = OptionBuilder.withArgName("folder").hasArg().withLongOpt(ARGUMENT.OUT)
.withDescription("The folder to write reports to. This defaults to the current directory.")
.create(ArgumentName.OUT_SHORT);
.create(ARGUMENT.OUT_SHORT);
final Option outputFormat = OptionBuilder.withArgName("format").hasArg().withLongOpt(ArgumentName.OUTPUT_FORMAT)
final Option outputFormat = OptionBuilder.withArgName("format").hasArg().withLongOpt(ARGUMENT.OUTPUT_FORMAT)
.withDescription("The output format to write to (XML, HTML, VULN, ALL). The default is HTML.")
.create(ArgumentName.OUTPUT_FORMAT_SHORT);
.create(ARGUMENT.OUTPUT_FORMAT_SHORT);
final Option verboseLog = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.VERBOSE_LOG)
final Option verboseLog = OptionBuilder.withArgName("file").hasArg().withLongOpt(ARGUMENT.VERBOSE_LOG)
.withDescription("The file path to write verbose logging information.")
.create(ArgumentName.VERBOSE_LOG_SHORT);
.create(ARGUMENT.VERBOSE_LOG_SHORT);
final Option suppressionFile = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.SUPPRESSION_FILE)
final Option suppressionFile = OptionBuilder.withArgName("file").hasArg().withLongOpt(ARGUMENT.SUPPRESSION_FILE)
.withDescription("The file path to the suppression XML file.")
.create();
@@ -230,87 +235,87 @@ public final class CliParser {
@SuppressWarnings("static-access")
private void addAdvancedOptions(final Options options) throws IllegalArgumentException {
final Option data = OptionBuilder.withArgName("path").hasArg().withLongOpt(ArgumentName.DATA_DIRECTORY)
final Option data = OptionBuilder.withArgName("path").hasArg().withLongOpt(ARGUMENT.DATA_DIRECTORY)
.withDescription("The location of the H2 Database file. This option should generally not be set.")
.create(ArgumentName.DATA_DIRECTORY_SHORT);
.create(ARGUMENT.DATA_DIRECTORY_SHORT);
final Option connectionTimeout = OptionBuilder.withArgName("timeout").hasArg().withLongOpt(ArgumentName.CONNECTION_TIMEOUT)
final Option connectionTimeout = OptionBuilder.withArgName("timeout").hasArg().withLongOpt(ARGUMENT.CONNECTION_TIMEOUT)
.withDescription("The connection timeout (in milliseconds) to use when downloading resources.")
.create(ArgumentName.CONNECTION_TIMEOUT_SHORT);
.create(ARGUMENT.CONNECTION_TIMEOUT_SHORT);
final Option proxyUrl = OptionBuilder.withArgName("url").hasArg().withLongOpt(ArgumentName.PROXY_URL)
.withDescription("The proxy url to use when downloading resources.")
.create(ArgumentName.PROXY_URL_SHORT);
final Option proxyServer = OptionBuilder.withArgName("server").hasArg().withLongOpt(ARGUMENT.PROXY_SERVER)
.withDescription("The proxy server to use when downloading resources.")
.create();
final Option proxyPort = OptionBuilder.withArgName("port").hasArg().withLongOpt(ArgumentName.PROXY_PORT)
final Option proxyPort = OptionBuilder.withArgName("port").hasArg().withLongOpt(ARGUMENT.PROXY_PORT)
.withDescription("The proxy port to use when downloading resources.")
.create(ArgumentName.PROXY_PORT_SHORT);
.create();
final Option proxyUsername = OptionBuilder.withArgName("user").hasArg().withLongOpt(ArgumentName.PROXY_USERNAME)
final Option proxyUsername = OptionBuilder.withArgName("user").hasArg().withLongOpt(ARGUMENT.PROXY_USERNAME)
.withDescription("The proxy username to use when downloading resources.")
.create();
final Option proxyPassword = OptionBuilder.withArgName("pass").hasArg().withLongOpt(ArgumentName.PROXY_PASSWORD)
final Option proxyPassword = OptionBuilder.withArgName("pass").hasArg().withLongOpt(ARGUMENT.PROXY_PASSWORD)
.withDescription("The proxy password to use when downloading resources.")
.create();
final Option connectionString = OptionBuilder.withArgName("connStr").hasArg().withLongOpt(ArgumentName.CONNECTION_STRING)
final Option connectionString = OptionBuilder.withArgName("connStr").hasArg().withLongOpt(ARGUMENT.CONNECTION_STRING)
.withDescription("The connection string to the database.")
.create();
final Option dbUser = OptionBuilder.withArgName("user").hasArg().withLongOpt(ArgumentName.DB_NAME)
final Option dbUser = OptionBuilder.withArgName("user").hasArg().withLongOpt(ARGUMENT.DB_NAME)
.withDescription("The username used to connect to the database.")
.create();
final Option dbPassword = OptionBuilder.withArgName("password").hasArg().withLongOpt(ArgumentName.DB_PASSWORD)
final Option dbPassword = OptionBuilder.withArgName("password").hasArg().withLongOpt(ARGUMENT.DB_PASSWORD)
.withDescription("The password for connecting to the database.")
.create();
final Option dbDriver = OptionBuilder.withArgName("driver").hasArg().withLongOpt(ArgumentName.DB_DRIVER)
final Option dbDriver = OptionBuilder.withArgName("driver").hasArg().withLongOpt(ARGUMENT.DB_DRIVER)
.withDescription("The database driver name.")
.create();
final Option dbDriverPath = OptionBuilder.withArgName("path").hasArg().withLongOpt(ArgumentName.DB_DRIVER_PATH)
final Option dbDriverPath = OptionBuilder.withArgName("path").hasArg().withLongOpt(ARGUMENT.DB_DRIVER_PATH)
.withDescription("The path to the database driver; note, this does not need to be set unless the JAR is outside of the classpath.")
.create();
final Option disableJarAnalyzer = OptionBuilder.withLongOpt(ArgumentName.DISABLE_JAR)
final Option disableJarAnalyzer = OptionBuilder.withLongOpt(ARGUMENT.DISABLE_JAR)
.withDescription("Disable the Jar Analyzer.")
.create();
final Option disableArchiveAnalyzer = OptionBuilder.withLongOpt(ArgumentName.DISABLE_ARCHIVE)
final Option disableArchiveAnalyzer = OptionBuilder.withLongOpt(ARGUMENT.DISABLE_ARCHIVE)
.withDescription("Disable the Archive Analyzer.")
.create();
final Option disableNuspecAnalyzer = OptionBuilder.withLongOpt(ArgumentName.DISABLE_NUSPEC)
final Option disableNuspecAnalyzer = OptionBuilder.withLongOpt(ARGUMENT.DISABLE_NUSPEC)
.withDescription("Disable the Nuspec Analyzer.")
.create();
final Option disableAssemblyAnalyzer = OptionBuilder.withLongOpt(ArgumentName.DISABLE_ASSEMBLY)
final Option disableAssemblyAnalyzer = OptionBuilder.withLongOpt(ARGUMENT.DISABLE_ASSEMBLY)
.withDescription("Disable the .NET Assembly Analyzer.")
.create();
final Option disableNexusAnalyzer = OptionBuilder.withLongOpt(ArgumentName.DISABLE_NEXUS)
final Option disableNexusAnalyzer = OptionBuilder.withLongOpt(ARGUMENT.DISABLE_NEXUS)
.withDescription("Disable the Nexus Analyzer.")
.create();
final Option nexusUrl = OptionBuilder.withArgName("url").hasArg().withLongOpt(ArgumentName.NEXUS_URL)
final Option nexusUrl = OptionBuilder.withArgName("url").hasArg().withLongOpt(ARGUMENT.NEXUS_URL)
.withDescription("The url to the Nexus Server.")
.create();
final Option nexusUsesProxy = OptionBuilder.withArgName("true/false").hasArg().withLongOpt(ArgumentName.NEXUS_USES_PROXY)
final Option nexusUsesProxy = OptionBuilder.withArgName("true/false").hasArg().withLongOpt(ARGUMENT.NEXUS_USES_PROXY)
.withDescription("Whether or not the configured proxy should be used when connecting to Nexus.")
.create();
final Option additionalZipExtensions = OptionBuilder.withArgName("extensions").hasArg()
.withLongOpt(ArgumentName.ADDITIONAL_ZIP_EXTENSIONS)
.withLongOpt(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS)
.withDescription("A comma separated list of additional extensions to be scanned as ZIP files "
+ "(ZIP, EAR, WAR are already treated as zip files)")
.create();
final Option pathToMono = OptionBuilder.withArgName("path").hasArg().withLongOpt(ArgumentName.PATH_TO_MONO)
final Option pathToMono = OptionBuilder.withArgName("path").hasArg().withLongOpt(ARGUMENT.PATH_TO_MONO)
.withDescription("The path to Mono for .NET Assembly analysis on non-windows systems.")
.create();
options.addOption(proxyPort)
.addOption(proxyUrl)
.addOption(proxyServer)
.addOption(proxyUsername)
.addOption(proxyPassword)
.addOption(connectionTimeout)
@@ -331,13 +336,30 @@ public final class CliParser {
.addOption(pathToMono);
}
/**
* 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
*/
@SuppressWarnings("static-access")
private void addDeprecatedOptions(final Options options) throws IllegalArgumentException {
final Option proxyServer = OptionBuilder.withArgName("url").hasArg().withLongOpt(ARGUMENT.PROXY_URL)
.withDescription("The proxy url argument is deprecated, use proxyserver instead.")
.create();
options.addOption(proxyServer);
}
/**
* Determines if the 'version' command line argument was passed in.
*
* @return whether or not the 'version' command line argument was passed in
*/
public boolean isGetVersion() {
return (line != null) && line.hasOption(ArgumentName.VERSION);
return (line != null) && line.hasOption(ARGUMENT.VERSION);
}
/**
@@ -346,7 +368,7 @@ public final class CliParser {
* @return whether or not the 'help' command line argument was passed in
*/
public boolean isGetHelp() {
return (line != null) && line.hasOption(ArgumentName.HELP);
return (line != null) && line.hasOption(ARGUMENT.HELP);
}
/**
@@ -355,7 +377,7 @@ public final class CliParser {
* @return whether or not the 'scan' command line argument was passed in
*/
public boolean isRunScan() {
return (line != null) && isValid && line.hasOption(ArgumentName.SCAN);
return (line != null) && isValid && line.hasOption(ARGUMENT.SCAN);
}
/**
@@ -364,7 +386,7 @@ public final class CliParser {
* @return true if the disableJar command line argument was specified; otherwise false
*/
public boolean isJarDisabled() {
return (line != null) && line.hasOption(ArgumentName.DISABLE_JAR);
return (line != null) && line.hasOption(ARGUMENT.DISABLE_JAR);
}
/**
@@ -373,7 +395,7 @@ public final class CliParser {
* @return true if the disableArchive command line argument was specified; otherwise false
*/
public boolean isArchiveDisabled() {
return (line != null) && line.hasOption(ArgumentName.DISABLE_ARCHIVE);
return (line != null) && line.hasOption(ARGUMENT.DISABLE_ARCHIVE);
}
/**
@@ -382,7 +404,7 @@ public final class CliParser {
* @return true if the disableNuspec command line argument was specified; otherwise false
*/
public boolean isNuspecDisabled() {
return (line != null) && line.hasOption(ArgumentName.DISABLE_NUSPEC);
return (line != null) && line.hasOption(ARGUMENT.DISABLE_NUSPEC);
}
/**
@@ -391,7 +413,7 @@ public final class CliParser {
* @return true if the disableAssembly command line argument was specified; otherwise false
*/
public boolean isAssemblyDisabled() {
return (line != null) && line.hasOption(ArgumentName.DISABLE_ASSEMBLY);
return (line != null) && line.hasOption(ARGUMENT.DISABLE_ASSEMBLY);
}
/**
@@ -400,7 +422,7 @@ public final class CliParser {
* @return true if the disableNexus command line argument was specified; otherwise false
*/
public boolean isNexusDisabled() {
return (line != null) && line.hasOption(ArgumentName.DISABLE_NEXUS);
return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS);
}
/**
@@ -409,10 +431,10 @@ public final class CliParser {
* @return the url to the nexus server; if none was specified this will return null;
*/
public String getNexusUrl() {
if (line == null || !line.hasOption(ArgumentName.NEXUS_URL)) {
if (line == null || !line.hasOption(ARGUMENT.NEXUS_URL)) {
return null;
} else {
return line.getOptionValue(ArgumentName.NEXUS_URL);
return line.getOptionValue(ARGUMENT.NEXUS_URL);
}
}
@@ -425,14 +447,14 @@ public final class CliParser {
public boolean isNexusUsesProxy() {
// If they didn't specify whether Nexus needs to use the proxy, we should
// still honor the property if it's set.
if (line == null || !line.hasOption(ArgumentName.NEXUS_USES_PROXY)) {
if (line == null || !line.hasOption(ARGUMENT.NEXUS_USES_PROXY)) {
try {
return Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY);
} catch (InvalidSettingException ise) {
return true;
}
} else {
return Boolean.parseBoolean(line.getOptionValue(ArgumentName.NEXUS_USES_PROXY));
return Boolean.parseBoolean(line.getOptionValue(ARGUMENT.NEXUS_USES_PROXY));
}
}
@@ -443,7 +465,7 @@ public final class CliParser {
final HelpFormatter formatter = new HelpFormatter();
final Options options = new Options();
addStandardOptions(options);
if (line != null && line.hasOption(ArgumentName.ADVANCED_HELP)) {
if (line != null && line.hasOption(ARGUMENT.ADVANCED_HELP)) {
addAdvancedOptions(options);
}
final String helpMsg = String.format("%n%s"
@@ -466,7 +488,7 @@ public final class CliParser {
* @return the file paths specified on the command line for scan
*/
public String[] getScanFiles() {
return line.getOptionValues(ArgumentName.SCAN);
return line.getOptionValues(ARGUMENT.SCAN);
}
/**
@@ -475,7 +497,7 @@ public final class CliParser {
* @return the path to the reports directory.
*/
public String getReportDirectory() {
return line.getOptionValue(ArgumentName.OUT, ".");
return line.getOptionValue(ARGUMENT.OUT, ".");
}
/**
@@ -484,7 +506,7 @@ public final class CliParser {
* @return the path to Mono
*/
public String getPathToMono() {
return line.getOptionValue(ArgumentName.PATH_TO_MONO);
return line.getOptionValue(ARGUMENT.PATH_TO_MONO);
}
/**
@@ -493,7 +515,7 @@ public final class CliParser {
* @return the output format name.
*/
public String getReportFormat() {
return line.getOptionValue(ArgumentName.OUTPUT_FORMAT, "HTML");
return line.getOptionValue(ARGUMENT.OUTPUT_FORMAT, "HTML");
}
/**
@@ -502,7 +524,7 @@ public final class CliParser {
* @return the application name.
*/
public String getApplicationName() {
return line.getOptionValue(ArgumentName.APP_NAME);
return line.getOptionValue(ARGUMENT.APP_NAME);
}
/**
@@ -511,16 +533,24 @@ public final class CliParser {
* @return the connection timeout
*/
public String getConnectionTimeout() {
return line.getOptionValue(ArgumentName.CONNECTION_TIMEOUT);
return line.getOptionValue(ARGUMENT.CONNECTION_TIMEOUT);
}
/**
* Returns the proxy url.
* Returns the proxy server.
*
* @return the proxy url
* @return the proxy server
*/
public String getProxyUrl() {
return line.getOptionValue(ArgumentName.PROXY_URL);
public String getProxyServer() {
String server = line.getOptionValue(ARGUMENT.PROXY_SERVER);
if (server == null) {
server = line.getOptionValue(ARGUMENT.PROXY_URL);
if (server != null) {
LOGGER.warning("An old command line argument 'proxyurl' was detected; use proxyserver instead");
}
}
return server;
}
/**
@@ -529,7 +559,7 @@ public final class CliParser {
* @return the proxy port
*/
public String getProxyPort() {
return line.getOptionValue(ArgumentName.PROXY_PORT);
return line.getOptionValue(ARGUMENT.PROXY_PORT);
}
/**
@@ -538,7 +568,7 @@ public final class CliParser {
* @return the proxy username
*/
public String getProxyUsername() {
return line.getOptionValue(ArgumentName.PROXY_USERNAME);
return line.getOptionValue(ARGUMENT.PROXY_USERNAME);
}
/**
@@ -547,7 +577,7 @@ public final class CliParser {
* @return the proxy password
*/
public String getProxyPassword() {
return line.getOptionValue(ArgumentName.PROXY_PASSWORD);
return line.getOptionValue(ARGUMENT.PROXY_PASSWORD);
}
/**
@@ -556,7 +586,7 @@ public final class CliParser {
* @return the value of dataDirectory
*/
public String getDataDirectory() {
return line.getOptionValue(ArgumentName.DATA_DIRECTORY);
return line.getOptionValue(ARGUMENT.DATA_DIRECTORY);
}
/**
@@ -565,7 +595,7 @@ public final class CliParser {
* @return the properties file specified on the command line
*/
public File getPropertiesFile() {
final String path = line.getOptionValue(ArgumentName.PROP);
final String path = line.getOptionValue(ARGUMENT.PROP);
if (path != null) {
return new File(path);
}
@@ -578,7 +608,7 @@ public final class CliParser {
* @return the path to the verbose log file
*/
public String getVerboseLog() {
return line.getOptionValue(ArgumentName.VERBOSE_LOG);
return line.getOptionValue(ARGUMENT.VERBOSE_LOG);
}
/**
@@ -587,7 +617,7 @@ public final class CliParser {
* @return the path to the suppression file
*/
public String getSuppressionFile() {
return line.getOptionValue(ArgumentName.SUPPRESSION_FILE);
return line.getOptionValue(ARGUMENT.SUPPRESSION_FILE);
}
/**
@@ -610,7 +640,7 @@ public final class CliParser {
* @return if auto-update is allowed.
*/
public boolean isAutoUpdate() {
return (line == null) || !line.hasOption(ArgumentName.DISABLE_AUTO_UPDATE);
return (line == null) || !line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE);
}
/**
@@ -619,7 +649,7 @@ public final class CliParser {
* @return the database driver name if specified; otherwise null is returned
*/
public String getDatabaseDriverName() {
return line.getOptionValue(ArgumentName.DB_DRIVER);
return line.getOptionValue(ARGUMENT.DB_DRIVER);
}
/**
@@ -628,7 +658,7 @@ public final class CliParser {
* @return the database driver name if specified; otherwise null is returned
*/
public String getDatabaseDriverPath() {
return line.getOptionValue(ArgumentName.DB_DRIVER_PATH);
return line.getOptionValue(ARGUMENT.DB_DRIVER_PATH);
}
/**
@@ -637,7 +667,7 @@ public final class CliParser {
* @return the database connection string if specified; otherwise null is returned
*/
public String getConnectionString() {
return line.getOptionValue(ArgumentName.CONNECTION_STRING);
return line.getOptionValue(ARGUMENT.CONNECTION_STRING);
}
/**
@@ -646,7 +676,7 @@ public final class CliParser {
* @return the database database user name if specified; otherwise null is returned
*/
public String getDatabaseUser() {
return line.getOptionValue(ArgumentName.DB_NAME);
return line.getOptionValue(ARGUMENT.DB_NAME);
}
/**
@@ -655,7 +685,7 @@ public final class CliParser {
* @return the database database password if specified; otherwise null is returned
*/
public String getDatabasePassword() {
return line.getOptionValue(ArgumentName.DB_PASSWORD);
return line.getOptionValue(ARGUMENT.DB_PASSWORD);
}
/**
@@ -664,13 +694,13 @@ public final class CliParser {
* @return the additional Extensions; otherwise null is returned
*/
public String getAdditionalZipExtensions() {
return line.getOptionValue(ArgumentName.ADDITIONAL_ZIP_EXTENSIONS);
return line.getOptionValue(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS);
}
/**
* A collection of static final strings that represent the possible command line arguments.
*/
public static class ArgumentName {
public static class ARGUMENT {
/**
* The long CLI argument name specifying the directory/file to scan.
@@ -732,21 +762,20 @@ public final class CliParser {
* The short CLI argument name asking for the version.
*/
public static final String VERSION = "version";
/**
* The short CLI argument name indicating the proxy port.
*/
public static final String PROXY_PORT_SHORT = "p";
/**
* The CLI argument name indicating the proxy port.
*/
public static final String PROXY_PORT = "proxyport";
/**
* The short CLI argument name indicating the proxy url.
* The CLI argument name indicating the proxy server.
*/
public static final String PROXY_URL_SHORT = "u";
public static final String PROXY_SERVER = "proxyserver";
/**
* The CLI argument name indicating the proxy url.
*
* @deprecated use {@link org.owasp.dependencycheck.cli.CliParser.ArgumentName#PROXY_SERVER} instead
*/
@Deprecated
public static final String PROXY_URL = "proxyurl";
/**
* The CLI argument name indicating the proxy username.

View File

@@ -3,7 +3,7 @@ Command Line Arguments
The following table lists the command line arguments:
Short | Argument Name | Parameter | Description | Requirement
Short | Argument&nbsp;Name&nbsp;&nbsp; | Parameter | Description | Requirement
-------|-----------------------|-----------------|-------------|------------
\-a | \-\-app | \<name\> | The name of the application being scanned. This is a required argument. | Required
\-s | \-\-scan | \<path\> | The path to scan \- this option can be specified multiple times. It is also possible to specify specific file types that should be scanned by supplying a scan path of '[path]/[to]/[scan]/*.zip'. The wild card can only be used to denote any file-name with a specific extension. | Required
@@ -18,7 +18,7 @@ Short | Argument Name | Parameter | Description | Requirement
Advanced Options
================
Short | Argument Name | Parameter | Description | Default Value
Short | Argument&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Parameter | Description | Default&nbsp;Value
-------|-----------------------|-----------------|-------------|---------------
| \-\-disableArchive | | Sets whether the Archive Analyzer will be used. | 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;
@@ -30,7 +30,7 @@ Short | Argument Name | Parameter | Description | Default Value
| \-\-disableNuspec | | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | false
| \-\-disableAssembly | | Sets whether or not the .NET Assembly Analyzer should be used. | false
| \-\-pathToMono | \<path\> | The path to Mono for .NET Assembly analysis on non-windows systems. | &nbsp;
| \-\-proxyurl | \<url\> | The proxy url to use when downloading resources. | &nbsp;
| \-\-proxyserver | \<server\> | The proxy server to use when downloading resources. | &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

@@ -44,7 +44,7 @@ public class CliParserTest {
@AfterClass
public static void tearDownClass() throws Exception {
Settings.cleanup();
Settings.cleanup(true);
}
@Before

View File

@@ -15,13 +15,12 @@ limitations under the License.
Copyright (c) 2012 Jeremy Long. All Rights Reserved.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.0</version>
<version>1.2.2</version>
</parent>
<artifactId>dependency-check-core</artifactId>
@@ -220,6 +219,11 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<name>data.directory</name>
<value>${project.build.directory}/data</value>
</property>
<property>
<name>temp.directory</name>
<value>${project.build.directory}/temp</value>
</property>
</systemProperties>
<includes>
<include>**/*IntegrationTest.java</include>
@@ -399,6 +403,11 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-utils</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-test-framework</artifactId>
@@ -521,6 +530,13 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.0.0.RELEASE</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast</artifactId>
@@ -662,11 +678,11 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
Additionally, these are only added when using "allTests" to
make the build slightly faster in most cases. -->
<id>False Positive Tests</id>
<!--activation>
<activation>
<property>
<name>allTests</name>
</property>
</activation-->
</activation>
<dependencies>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
@@ -689,6 +705,34 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.ganyo</groupId>
<artifactId>gcm-server</artifactId>
<version>1.0.2</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.7-b1</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-complete</artifactId>
<version>1.7.4</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby</artifactId>
<version>1.6.3</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
</dependencies>
</profile>
</profiles>

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
* Copyright (c) 2014 Steve Springett. All Rights Reserved.
*/
package org.owasp.dependencycheck.agent;
@@ -234,26 +234,49 @@ public class DependencyCheckScanAgent {
}
/**
* The Proxy URL.
* The Proxy Server.
*/
private String proxyUrl;
private String proxyServer;
/**
* Get the value of proxyUrl.
* Get the value of proxyServer.
*
* @return the value of proxyUrl
* @return the value of proxyServer
*/
public String getProxyUrl() {
return proxyUrl;
public String getProxyServer() {
return proxyServer;
}
/**
* Set the value of proxyUrl.
* Set the value of proxyServer.
*
* @param proxyUrl new value of proxyUrl
* @param proxyServer new value of proxyServer
*/
public void setProxyServer(String proxyServer) {
this.proxyServer = proxyServer;
}
/**
* Get the value of proxyServer.
*
* @return the value of proxyServer
* @deprecated use {@link org.owasp.dependencycheck.agent.DependencyCheckScanAgent#getProxyServer()} instead
*/
@Deprecated
public String getProxyUrl() {
return proxyServer;
}
/**
* Set the value of proxyServer.
*
* @param proxyUrl new value of proxyServer
* @deprecated use {@link org.owasp.dependencycheck.agent.DependencyCheckScanAgent#setProxyServer(java.lang.String)
* } instead
*/
@Deprecated
public void setProxyUrl(String proxyUrl) {
this.proxyUrl = proxyUrl;
this.proxyServer = proxyUrl;
}
/**
@@ -792,7 +815,7 @@ public class DependencyCheckScanAgent {
/**
* 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.
* properties required to change the proxy server, port, and connection timeout.
*/
private void populateSettings() {
Settings.initialize();
@@ -808,8 +831,8 @@ public class DependencyCheckScanAgent {
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
if (proxyUrl != null && !proxyUrl.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_URL, proxyUrl);
if (proxyServer != null && !proxyServer.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_SERVER, proxyServer);
}
if (proxyPort != null && !proxyPort.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort);
@@ -888,7 +911,7 @@ public class DependencyCheckScanAgent {
"Unable to connect to the dependency-check database; analysis has stopped");
LOGGER.log(Level.FINE, "", ex);
} finally {
Settings.cleanup();
Settings.cleanup(true);
if (engine != null) {
engine.cleanup();
}

View File

@@ -98,11 +98,18 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
* @throws SuppressionParseException thrown if the XML cannot be parsed.
*/
private void loadSuppressionData() throws SuppressionParseException {
final SuppressionParser parser = new SuppressionParser();
File file = null;
file = new File(this.getClass().getClassLoader().getResource("dependencycheck-base-suppression.xml").getPath());
try {
rules = parser.parseSuppressionRules(file);
} catch (SuppressionParseException ex) {
LOGGER.log(Level.FINE, "Unable to parse the base suppression data file", ex);
}
final String suppressionFilePath = Settings.getString(Settings.KEYS.SUPPRESSION_FILE);
if (suppressionFilePath == null) {
return;
}
File file = null;
boolean deleteTempFile = false;
try {
final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE);
@@ -132,9 +139,9 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
}
if (file != null) {
final SuppressionParser parser = new SuppressionParser();
try {
rules = parser.parseSuppressionRules(file);
//rules = parser.parseSuppressionRules(file);
rules.addAll(parser.parseSuppressionRules(file));
LOGGER.log(Level.FINE, rules.size() + " suppression rules were loaded.");
} catch (SuppressionParseException ex) {
final String msg = String.format("Unable to parse suppression xml file '%s'", file.getPath());

View File

@@ -27,6 +27,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -35,7 +36,9 @@ import java.util.logging.Logger;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.compress.compressors.CompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipUtils;
@@ -99,6 +102,11 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
*/
private static final Set<String> EXTENSIONS = newHashSet("tar", "gz", "tgz");
/**
* The set of file extensions to remove from the engine's collection of dependencies.
*/
private static final Set<String> REMOVE_FROM_ANALYSIS = newHashSet("zip", "tar", "gz", "tgz"); //TODO add nupkg, apk, sar?
static {
final String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS);
if (additionalZipExt != null) {
@@ -178,7 +186,7 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
if (tempFileLocation != null && tempFileLocation.exists()) {
LOGGER.log(Level.FINE, "Attempting to delete temporary files");
final boolean success = FileUtils.delete(tempFileLocation);
if (!success) {
if (!success && tempFileLocation != null & tempFileLocation.exists()) {
LOGGER.log(Level.WARNING, "Failed to delete some temporary files, see the log for more details");
}
}
@@ -199,9 +207,9 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
extractFiles(f, tmpDir, engine);
//make a copy
final List<Dependency> dependencies = new ArrayList<Dependency>(engine.getDependencies());
List<Dependency> dependencies = new ArrayList<Dependency>(engine.getDependencies());
engine.scan(tmpDir);
final List<Dependency> newDependencies = engine.getDependencies();
List<Dependency> newDependencies = engine.getDependencies();
if (dependencies.size() != newDependencies.size()) {
//get the new dependencies
final Set<Dependency> dependencySet = new HashSet<Dependency>();
@@ -229,6 +237,40 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
}
}
}
if (this.REMOVE_FROM_ANALYSIS.contains(dependency.getFileExtension())) {
if ("zip".equals(dependency.getFileExtension()) && isZipFileActuallyJarFile(dependency)) {
final File tdir = getNextTempDirectory();
final String fileName = dependency.getFileName();
LOGGER.info(String.format("The zip file '%s' appears to be a JAR file, making a deep copy and analyzing it as a JAR.", fileName));
final File tmpLoc = new File(tdir, fileName.substring(0, fileName.length() - 3) + "jar");
try {
org.apache.commons.io.FileUtils.copyFile(tdir, tmpLoc);
dependencies = new ArrayList<Dependency>(engine.getDependencies());
engine.scan(tmpLoc);
newDependencies = engine.getDependencies();
if (dependencies.size() != newDependencies.size()) {
//get the new dependencies
final Set<Dependency> dependencySet = new HashSet<Dependency>();
dependencySet.addAll(newDependencies);
dependencySet.removeAll(dependencies);
if (dependencySet.size() != 1) {
LOGGER.info("Deep copy of ZIP to JAR file resulted in more then one dependency?");
}
for (Dependency d : dependencySet) {
//fix the dependency's display name and path
d.setFilePath(dependency.getFilePath());
d.setDisplayFileName(dependency.getFileName());
}
}
} catch (IOException ex) {
final String msg = String.format("Unable to perform deep copy on '%s'", dependency.getActualFile().getPath());
LOGGER.log(Level.FINE, msg, ex);
}
}
engine.getDependencies().remove(dependency);
}
Collections.sort(engine.getDependencies());
}
@@ -411,4 +453,38 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
}
}
}
/**
* Attempts to determine if a zip file is actually a JAR file.
*
* @param dependency the dependency to check
* @return true if the dependency appears to be a JAR file; otherwise false
*/
private boolean isZipFileActuallyJarFile(Dependency dependency) {
boolean isJar = false;
ZipFile zip = null;
try {
zip = new ZipFile(dependency.getActualFilePath());
if (zip.getEntry("META-INF/MANIFEST.MF") != null
|| zip.getEntry("META-INF/maven") != null) {
final Enumeration<ZipArchiveEntry> entries = zip.getEntries();
while (entries.hasMoreElements()) {
final ZipArchiveEntry entry = entries.nextElement();
if (!entry.isDirectory()) {
final String name = entry.getName().toLowerCase();
if (name.endsWith(".class")) {
isJar = true;
break;
}
}
}
}
} catch (IOException ex) {
LOGGER.log(Level.FINE, String.format("Unable to unzip zip file '%s'", dependency.getFilePath()), ex);
} finally {
ZipFile.closeQuietly(zip);
}
return isJar;
}
}

View File

@@ -73,7 +73,7 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Logger
*/
private static final Logger LOGGER = Logger.getLogger(AssemblyAnalyzer.class.getName());
private static final Logger LOGGER = Logger.getLogger(AssemblyAnalyzer.class.getName(), "dependencycheck-resources");
/**
* Builds the beginnings of a List for ProcessBuilder
@@ -106,7 +106,7 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
public void analyzeFileType(Dependency dependency, Engine engine)
throws AnalysisException {
if (grokAssemblyExe == null) {
LOGGER.warning("GrokAssembly didn't get deployed");
LOGGER.warning("analyzer.AssemblyAnalyzer.notdeployed");
return;
}
@@ -114,16 +114,30 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
args.add(dependency.getActualFilePath());
final ProcessBuilder pb = new ProcessBuilder(args);
BufferedReader rdr = null;
Document doc = null;
try {
final Process proc = pb.start();
// Try evacuating the error stream
rdr = new BufferedReader(new InputStreamReader(proc.getErrorStream(), "UTF-8"));
String line = null;
while (rdr.ready() && (line = rdr.readLine()) != null) {
LOGGER.log(Level.WARNING, "Error from GrokAssembly: {0}", line);
LOGGER.log(Level.WARNING, "analyzer.AssemblyAnalyzer.grokassembly.stderr", line);
}
int rc = 0;
final Document doc = builder.parse(proc.getInputStream());
doc = builder.parse(proc.getInputStream());
try {
rc = proc.waitFor();
} catch (InterruptedException ie) {
return;
}
if (rc == 3) {
LOGGER.log(Level.FINE, "analyzer.AssemblyAnalyzer.notassembly", dependency.getActualFilePath());
return;
} else if (rc != 0) {
LOGGER.log(Level.WARNING, "analyzer.AssemblyAnalyzer.grokassembly.rc", rc);
}
final XPath xpath = XPathFactory.newInstance().newXPath();
// First, see if there was an error
@@ -150,18 +164,6 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
product, Confidence.HIGH));
}
try {
rc = proc.waitFor();
} catch (InterruptedException ie) {
return;
}
if (rc == 3) {
LOGGER.log(Level.INFO, "{0} is not a valid assembly", dependency.getActualFilePath());
return;
} else if (rc != 0) {
LOGGER.log(Level.WARNING, "Return code {0} from GrokAssembly", rc);
}
} catch (IOException ioe) {
throw new AnalysisException(ioe);
} catch (SAXException saxe) {
@@ -201,9 +203,10 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
grokAssemblyExe = tempFile;
// Set the temp file to get deleted when we're done
grokAssemblyExe.deleteOnExit();
LOGGER.log(Level.FINE, "Extracted GrokAssembly.exe to {0}", grokAssemblyExe.getPath());
LOGGER.log(Level.FINE, "analyzer.AssemblyAnalyzer.grokassembly.deployed", grokAssemblyExe.getPath());
} catch (IOException ioe) {
LOGGER.log(Level.WARNING, "Could not extract GrokAssembly.exe: {0}", ioe.getMessage());
this.setEnabled(false);
LOGGER.log(Level.WARNING, "analyzer.AssemblyAnalyzer.grokassembly.notdeployed", ioe.getMessage());
throw new AnalysisException("Could not extract GrokAssembly.exe", ioe);
} finally {
if (fos != null) {
@@ -240,15 +243,16 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
LOGGER.warning("An error occurred with the .NET AssemblyAnalyzer, please see the log for more details.");
LOGGER.fine("GrokAssembly.exe is not working properly");
grokAssemblyExe = null;
this.setEnabled(false);
throw new AnalysisException("Could not execute .NET AssemblyAnalyzer");
}
} catch (Throwable e) {
if (e instanceof AnalysisException) {
throw (AnalysisException) e;
} else {
LOGGER.warning("An error occured with the .NET AssemblyAnalyzer; "
+ "this can be ignored unless you are scanning .NET DLLs. Please see the log for more details.");
LOGGER.log(Level.FINE, "Could not execute GrokAssembly {0}", e.getMessage());
LOGGER.warning("analyzer.AssemblyAnalyzer.grokassembly.initialization.failed");
LOGGER.log(Level.FINE, "analyzer.AssemblyAnalyzer.grokassembly.initialization.message", e.getMessage());
this.setEnabled(false);
throw new AnalysisException("An error occured with the .NET AssemblyAnalyzer", e);
}
} finally {
@@ -260,7 +264,6 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
}
}
}
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
}
@@ -272,7 +275,7 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
grokAssemblyExe.deleteOnExit();
}
} catch (SecurityException se) {
LOGGER.fine("Can't delete temporary GrokAssembly.exe");
LOGGER.fine("analyzer.AssemblyAnalyzer.grokassembly.notdeleted");
}
}

View File

@@ -57,6 +57,7 @@ import org.owasp.dependencycheck.utils.DependencyVersionUtil;
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class CPEAnalyzer implements Analyzer {
/**
* The Logger.
*/
@@ -90,6 +91,11 @@ public class CPEAnalyzer implements Analyzer {
*/
private CveDB cve;
/**
* The URL to perform a search of the NVD CVE data at NIST.
*/
public static final String NVD_SEARCH_URL = "https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=%s";
/**
* Returns the name of this analyzer.
*
@@ -524,7 +530,8 @@ public class CPEAnalyzer implements Analyzer {
}
if (dbVer == null //special case, no version specified - everything is vulnerable
|| evVer.equals(dbVer)) { //yeah! exact match
final String url = String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(vs.getName(), "UTF-8"));
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 {
@@ -549,7 +556,7 @@ public class CPEAnalyzer implements Analyzer {
}
}
final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString());
final String url = null; //String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(cpeName, "UTF-8"));
final String url = null;
if (bestGuessConf == null) {
bestGuessConf = Confidence.LOW;
}

View File

@@ -88,6 +88,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
removeBadMatches(dependency);
removeWrongVersionMatches(dependency);
removeSpuriousCPE(dependency);
removeDuplicativeEntriesFromJar(dependency, engine);
addFalseNegativeCPEs(dependency);
}
@@ -160,11 +161,20 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
*/
public static final Pattern CORE_JAVA = Pattern.compile("^cpe:/a:(sun|oracle|ibm):(j2[ems]e|"
+ "java(_platform_micro_edition|_runtime_environment|_se|virtual_machine|se_development_kit|fx)?|"
+ "jdk|jre|jsf|jsse)($|:.*)");
+ "jdk|jre|jsse)($|:.*)");
/**
* Regex to identify core jsf libraries.
*/
public static final Pattern CORE_JAVA_JSF = Pattern.compile("^cpe:/a:(sun|oracle|ibm):jsf($|:.*)");
/**
* Regex to identify core java library files. This is currently incomplete.
*/
public static final Pattern CORE_FILES = Pattern.compile("^((alt[-])?rt|jsf[-].*|jsse|jfxrt|jfr|jce|javaws|deploy|charsets)\\.jar$");
public static final Pattern CORE_FILES = Pattern.compile("(^|/)((alt[-])?rt|jsse|jfxrt|jfr|jce|javaws|deploy|charsets)\\.jar$");
/**
* Regex to identify core jsf java library files. This is currently incomplete.
*/
public static final Pattern CORE_JSF_FILES = Pattern.compile("(^|/)jsf[-][^/]*\\.jar$");
/**
* Removes any CPE entries for the JDK/JRE unless the filename ends with rt.jar
@@ -181,27 +191,11 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
if (coreCPE.matches() && !coreFiles.matches()) {
itr.remove();
}
//replaced with the regex above.
// if (("cpe:/a:sun:java".equals(i.getValue())
// || "cpe:/a:oracle:java".equals(i.getValue())
// || "cpe:/a:ibm:java".equals(i.getValue())
// || "cpe:/a:sun:j2se".equals(i.getValue())
// || "cpe:/a:oracle:j2se".equals(i.getValue())
// || i.getValue().startsWith("cpe:/a:sun:java:")
// || i.getValue().startsWith("cpe:/a:sun:j2se:")
// || i.getValue().startsWith("cpe:/a:sun:java:jre")
// || i.getValue().startsWith("cpe:/a:sun:java:jdk")
// || i.getValue().startsWith("cpe:/a:sun:java_se")
// || i.getValue().startsWith("cpe:/a:oracle:java_se")
// || i.getValue().startsWith("cpe:/a:oracle:java:")
// || i.getValue().startsWith("cpe:/a:oracle:j2se:")
// || i.getValue().startsWith("cpe:/a:oracle:jre")
// || i.getValue().startsWith("cpe:/a:oracle:jdk")
// || i.getValue().startsWith("cpe:/a:ibm:java:"))
// && !dependency.getFileName().toLowerCase().endsWith("rt.jar")) {
// itr.remove();
// }
final Matcher coreJsfCPE = CORE_JAVA_JSF.matcher(i.getValue());
final Matcher coreJsfFiles = CORE_JSF_FILES.matcher(dependency.getFileName());
if (coreJsfCPE.matches() && !coreJsfFiles.matches()) {
itr.remove();
}
}
}
@@ -248,14 +242,33 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
//TODO move this startsWith expression to a configuration file?
if ("cpe".equals(i.getType())) {
if ((i.getValue().matches(".*c\\+\\+.*")
|| i.getValue().startsWith("cpe:/a:jquery:jquery")
|| i.getValue().startsWith("cpe:/a:prototypejs:prototype")
|| i.getValue().startsWith("cpe:/a:yahoo:yui")
|| i.getValue().startsWith("cpe:/a:file:file")
|| i.getValue().startsWith("cpe:/a:mozilla:mozilla")
|| i.getValue().startsWith("cpe:/a:cvs:cvs")
|| i.getValue().startsWith("cpe:/a:ftp:ftp")
|| i.getValue().startsWith("cpe:/a:ssh:ssh"))
|| i.getValue().startsWith("cpe:/a:tcp:tcp")
|| i.getValue().startsWith("cpe:/a:ssh:ssh")
|| i.getValue().startsWith("cpe:/a:lookup:lookup"))
&& (dependency.getFileName().toLowerCase().endsWith(".jar")
|| dependency.getFileName().toLowerCase().endsWith("pom.xml")
|| dependency.getFileName().toLowerCase().endsWith(".dll")
|| dependency.getFileName().toLowerCase().endsWith(".exe")
|| dependency.getFileName().toLowerCase().endsWith(".nuspec")
|| dependency.getFileName().toLowerCase().endsWith(".nupkg"))) {
itr.remove();
} else if ((i.getValue().startsWith("cpe:/a:jquery:jquery")
|| i.getValue().startsWith("cpe:/a:prototypejs:prototype")
|| i.getValue().startsWith("cpe:/a:yahoo:yui"))
&& (dependency.getFileName().toLowerCase().endsWith(".jar")
|| dependency.getFileName().toLowerCase().endsWith("pom.xml")
|| dependency.getFileName().toLowerCase().endsWith(".dll")
|| dependency.getFileName().toLowerCase().endsWith(".exe"))) {
itr.remove();
} else if ((i.getValue().startsWith("cpe:/a:microsoft:excel")
|| i.getValue().startsWith("cpe:/a:microsoft:word")
|| i.getValue().startsWith("cpe:/a:microsoft:visio")
|| i.getValue().startsWith("cpe:/a:microsoft:powerpoint")
|| i.getValue().startsWith("cpe:/a:microsoft:office"))
&& (dependency.getFileName().toLowerCase().endsWith(".jar")
|| dependency.getFileName().toLowerCase().endsWith("pom.xml"))) {
itr.remove();
@@ -266,7 +279,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
&& !dependency.getEvidenceUsed().containsUsedString("m-core")) {
itr.remove();
} else if (i.getValue().startsWith("cpe:/a:jboss:jboss")
&& !dependency.getFileName().toLowerCase().matches("jboss-[\\d\\.]+(GA)?\\.jar")) {
&& !dependency.getFileName().toLowerCase().matches("jboss-?[\\d\\.-]+(GA)?\\.jar")) {
itr.remove();
}
}
@@ -314,6 +327,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
* @param dependency the dependency being analyzed
*/
private void addFalseNegativeCPEs(Dependency dependency) {
//TODO move this to the hint analyzer
final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
while (itr.hasNext()) {
final Identifier i = itr.next();
@@ -329,20 +343,92 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
try {
dependency.addIdentifier("cpe",
newCpe,
String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(newCpe, "UTF-8")));
String.format(CPEAnalyzer.NVD_SEARCH_URL, URLEncoder.encode(newCpe, "UTF-8")));
dependency.addIdentifier("cpe",
newCpe2,
String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(newCpe2, "UTF-8")));
String.format(CPEAnalyzer.NVD_SEARCH_URL, URLEncoder.encode(newCpe2, "UTF-8")));
dependency.addIdentifier("cpe",
newCpe3,
String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(newCpe3, "UTF-8")));
String.format(CPEAnalyzer.NVD_SEARCH_URL, URLEncoder.encode(newCpe3, "UTF-8")));
dependency.addIdentifier("cpe",
newCpe4,
String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(newCpe4, "UTF-8")));
String.format(CPEAnalyzer.NVD_SEARCH_URL, URLEncoder.encode(newCpe4, "UTF-8")));
} catch (UnsupportedEncodingException ex) {
LOGGER.log(Level.FINE, null, ex);
}
}
}
}
/**
* Removes duplicate entries identified that are contained within JAR files. These occasionally crop up due to POM
* entries or other types of files (such as DLLs and EXEs) being contained within the JAR.
*
* @param dependency the dependency that might be a duplicate
* @param engine the engine used to scan all dependencies
*/
private void removeDuplicativeEntriesFromJar(Dependency dependency, Engine engine) {
if (dependency.getFileName().toLowerCase().endsWith("pom.xml")
|| "dll".equals(dependency.getFileExtension())
|| "exe".equals(dependency.getFileExtension())) {
String parentPath = dependency.getFilePath().toLowerCase();
if (parentPath.contains(".jar")) {
parentPath = parentPath.substring(0, parentPath.indexOf(".jar") + 4);
final Dependency parent = findDependency(parentPath, engine.getDependencies());
if (parent != null) {
boolean remove = false;
for (Identifier i : dependency.getIdentifiers()) {
if ("cpe".equals(i.getType())) {
final String trimmedCPE = trimCpeToVendor(i.getValue());
for (Identifier parentId : parent.getIdentifiers()) {
if ("cpe".equals(parentId.getType()) && parentId.getValue().startsWith(trimmedCPE)) {
remove |= true;
}
}
}
if (!remove) { //we can escape early
return;
}
}
if (remove) {
engine.getDependencies().remove(dependency);
}
}
}
}
}
/**
* Retrieves a given dependency, based on a given path, from a list of dependencies.
*
* @param dependencyPath the path of the dependency to return
* @param dependencies the collection of dependencies to search
* @return the dependency object for the given path, otherwise null
*/
private Dependency findDependency(String dependencyPath, List<Dependency> dependencies) {
for (Dependency d : dependencies) {
if (d.getFilePath().equalsIgnoreCase(dependencyPath)) {
return d;
}
}
return null;
}
/**
* Takes a full CPE and returns the CPE trimmed to include only vendor and product.
*
* @param value the CPE value to trim
* @return a CPE value that only includes the vendor and product
*/
private String trimCpeToVendor(String value) {
//cpe:/a:jruby:jruby:1.0.8
final int pos1 = value.indexOf(":", 7); //right of vendor
final int pos2 = value.indexOf(":", pos1 + 1); //right of product
if (pos2 < 0) {
return value;
} else {
return value.substring(0, pos2);
}
}
}

View File

@@ -64,7 +64,6 @@ import org.owasp.dependencycheck.jaxb.pom.MavenNamespaceFilter;
import org.owasp.dependencycheck.jaxb.pom.generated.License;
import org.owasp.dependencycheck.jaxb.pom.generated.Model;
import org.owasp.dependencycheck.jaxb.pom.generated.Organization;
import org.owasp.dependencycheck.jaxb.pom.generated.Parent;
import org.owasp.dependencycheck.utils.FileUtils;
import org.owasp.dependencycheck.utils.NonClosingStream;
import org.owasp.dependencycheck.utils.Settings;
@@ -74,7 +73,6 @@ import org.xml.sax.XMLFilter;
import org.xml.sax.XMLReader;
/**
*
* Used to load a JAR file and collect information that can be used to determine the associated CPE.
*
* @author Jeremy Long <jeremy.long@owasp.org>
@@ -138,7 +136,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
"include-resource",
"embed-dependency",
"ipojo-components",
"ipojo-extension");
"ipojo-extension",
"eclipse-sourcereferences");
/**
* item in some manifest, should be considered medium confidence.
*/
@@ -321,7 +320,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
newDependency.setFileName(displayName);
newDependency.setFilePath(displayPath);
addPomEvidence(newDependency, pom, pomProperties);
setPomEvidence(newDependency, pom, pomProperties, null);
engine.getDependencies().add(newDependency);
Collections.sort(engine.getDependencies());
} else {
@@ -558,10 +557,21 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
*/
private boolean setPomEvidence(Dependency dependency, Model pom, Properties pomProperties, ArrayList<ClassNameInformation> classes) {
boolean foundSomething = false;
boolean addAsIdentifier = true;
if (pom == null) {
return foundSomething;
}
String groupid = interpolateString(pom.getGroupId(), pomProperties);
String parentGroupId = null;
if (pom.getParent() != null) {
parentGroupId = interpolateString(pom.getParent().getGroupId(), pomProperties);
if ((groupid == null || groupid.isEmpty()) && parentGroupId != null && !parentGroupId.isEmpty()) {
groupid = parentGroupId;
}
}
final String originalGroupID = groupid;
if (groupid != null && !groupid.isEmpty()) {
if (groupid.startsWith("org.") || groupid.startsWith("com.")) {
groupid = groupid.substring(4);
@@ -571,8 +581,26 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW);
addMatchingValues(classes, groupid, dependency.getVendorEvidence());
addMatchingValues(classes, groupid, dependency.getProductEvidence());
if (parentGroupId != null && !parentGroupId.isEmpty() && !parentGroupId.equals(groupid)) {
dependency.getVendorEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.MEDIUM);
dependency.getProductEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.LOW);
addMatchingValues(classes, parentGroupId, dependency.getVendorEvidence());
addMatchingValues(classes, parentGroupId, dependency.getProductEvidence());
}
} else {
addAsIdentifier = false;
}
String artifactid = interpolateString(pom.getArtifactId(), pomProperties);
String parentArtifactId = null;
if (pom.getParent() != null) {
parentArtifactId = interpolateString(pom.getParent().getArtifactId(), pomProperties);
if ((artifactid == null || artifactid.isEmpty()) && parentArtifactId != null && !parentArtifactId.isEmpty()) {
artifactid = parentArtifactId;
}
}
final String originalArtifactID = artifactid;
if (artifactid != null && !artifactid.isEmpty()) {
if (artifactid.startsWith("org.") || artifactid.startsWith("com.")) {
artifactid = artifactid.substring(4);
@@ -582,13 +610,40 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW);
addMatchingValues(classes, artifactid, dependency.getVendorEvidence());
addMatchingValues(classes, artifactid, dependency.getProductEvidence());
if (parentArtifactId != null && !parentArtifactId.isEmpty() && !parentArtifactId.equals(artifactid)) {
dependency.getProductEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.MEDIUM);
dependency.getVendorEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.LOW);
addMatchingValues(classes, parentArtifactId, dependency.getVendorEvidence());
addMatchingValues(classes, parentArtifactId, dependency.getProductEvidence());
}
} else {
addAsIdentifier = false;
}
//version
final String version = interpolateString(pom.getVersion(), pomProperties);
String version = interpolateString(pom.getVersion(), pomProperties);
String parentVersion = null;
if (pom.getParent() != null) {
parentVersion = interpolateString(pom.getParent().getVersion(), pomProperties);
if ((version == null || version.isEmpty()) && parentVersion != null && !parentVersion.isEmpty()) {
version = parentVersion;
}
}
if (version != null && !version.isEmpty()) {
foundSomething = true;
dependency.getVersionEvidence().addEvidence("pom", "version", version, Confidence.HIGHEST);
if (parentVersion != null && !parentVersion.isEmpty() && !parentVersion.equals(version)) {
dependency.getVersionEvidence().addEvidence("pom", "parent-version", version, Confidence.LOW);
}
} else {
addAsIdentifier = false;
}
if (addAsIdentifier) {
dependency.addIdentifier("maven", String.format("%s:%s:%s", originalGroupID, originalArtifactID, version), null, Confidence.LOW);
}
// org name
final Organization org = pom.getOrganization();
if (org != null && org.getName() != null) {
@@ -647,7 +702,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
//TODO remove weighting
vendor.addWeighting(entry.getKey());
if (addPackagesAsEvidence && entry.getKey().length() > 1) {
vendor.addEvidence("jar", "package", entry.getKey(), Confidence.LOW);
vendor.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW);
}
}
}
@@ -656,7 +711,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
if (ratio > 0.5) {
product.addWeighting(entry.getKey());
if (addPackagesAsEvidence && entry.getKey().length() > 1) {
product.addEvidence("jar", "package", entry.getKey(), Confidence.LOW);
product.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW);
}
}
}
@@ -690,7 +745,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
&& !dependency.getFileName().toLowerCase().endsWith("-javadoc.jar")
&& !dependency.getFileName().toLowerCase().endsWith("-src.jar")
&& !dependency.getFileName().toLowerCase().endsWith("-doc.jar")) {
LOGGER.log(Level.INFO,
LOGGER.log(Level.FINE,
String.format("Jar file '%s' does not contain a manifest.",
dependency.getFileName()));
}
@@ -764,6 +819,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
&& !key.endsWith("class-path")
&& !key.endsWith("-scm") //todo change this to a regex?
&& !key.startsWith("scm-")
&& !value.trim().startsWith("scm:")
&& !isImportPackage(key, value)
&& !isPackage(key, value)) {
@@ -1111,7 +1167,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
* @param evidence the evidence collection to add new entries too
*/
private void addMatchingValues(ArrayList<ClassNameInformation> classes, String value, EvidenceCollection evidence) {
if (value == null || value.isEmpty()) {
if (value == null || value.isEmpty() || classes == null || classes.isEmpty()) {
return;
}
final String text = value.toLowerCase();
@@ -1138,93 +1194,6 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Adds evidence from the POM to the dependency. This includes the GAV and in some situations the parent GAV if
* specified.
*
* @param dependency the dependency being analyzed
* @param pom the POM data
* @param pomProperties the properties file associated with the pom
*/
private void addPomEvidence(Dependency dependency, Model pom, Properties pomProperties) {
if (pom == null) {
return;
}
String groupid = interpolateString(pom.getGroupId(), pomProperties);
if (groupid != null && !groupid.isEmpty()) {
if (groupid.startsWith("org.") || groupid.startsWith("com.")) {
groupid = groupid.substring(4);
}
dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGH);
dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW);
}
String artifactid = interpolateString(pom.getArtifactId(), pomProperties);
if (artifactid != null && !artifactid.isEmpty()) {
if (artifactid.startsWith("org.") || artifactid.startsWith("com.")) {
artifactid = artifactid.substring(4);
}
dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGH);
dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW);
}
final String version = interpolateString(pom.getVersion(), pomProperties);
if (version != null && !version.isEmpty()) {
dependency.getVersionEvidence().addEvidence("pom", "version", version, Confidence.HIGHEST);
}
final Parent parent = pom.getParent(); //grab parent GAV
if (parent != null) {
final String parentGroupId = interpolateString(parent.getGroupId(), pomProperties);
if (parentGroupId != null && !parentGroupId.isEmpty()) {
if (groupid == null || groupid.isEmpty()) {
dependency.getVendorEvidence().addEvidence("pom", "parent.groupid", parentGroupId, Confidence.HIGH);
} else {
dependency.getVendorEvidence().addEvidence("pom", "parent.groupid", parentGroupId, Confidence.MEDIUM);
}
dependency.getProductEvidence().addEvidence("pom", "parent.groupid", parentGroupId, Confidence.LOW);
}
final String parentArtifactId = interpolateString(parent.getArtifactId(), pomProperties);
if (parentArtifactId != null && !parentArtifactId.isEmpty()) {
if (artifactid == null || artifactid.isEmpty()) {
dependency.getProductEvidence().addEvidence("pom", "parent.artifactid", parentArtifactId, Confidence.HIGH);
} else {
dependency.getProductEvidence().addEvidence("pom", "parent.artifactid", parentArtifactId, Confidence.MEDIUM);
}
dependency.getVendorEvidence().addEvidence("pom", "parent.artifactid", parentArtifactId, Confidence.LOW);
}
final String parentVersion = interpolateString(parent.getVersion(), pomProperties);
if (parentVersion != null && !parentVersion.isEmpty()) {
if (version == null || version.isEmpty()) {
dependency.getVersionEvidence().addEvidence("pom", "parent.version", parentVersion, Confidence.HIGH);
} else {
dependency.getVersionEvidence().addEvidence("pom", "parent.version", parentVersion, Confidence.LOW);
}
}
}
// org name
final Organization org = pom.getOrganization();
if (org != null && org.getName() != null) {
final String orgName = interpolateString(org.getName(), pomProperties);
if (orgName != null && !orgName.isEmpty()) {
dependency.getVendorEvidence().addEvidence("pom", "organization name", orgName, Confidence.HIGH);
}
}
//pom name
final String pomName = interpolateString(pom.getName(), pomProperties);
if (pomName != null && !pomName.isEmpty()) {
dependency.getProductEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH);
dependency.getVendorEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH);
}
//Description
if (pom.getDescription() != null) {
final String description = interpolateString(pom.getDescription(), pomProperties);
if (description != null && !description.isEmpty()) {
addDescription(dependency, description, "pom", "description");
}
}
extractLicense(pom, pomProperties, dependency);
}
/**
* Extracts the license information from the pom and adds it to the dependency.
*

View File

@@ -30,6 +30,7 @@ import org.owasp.dependencycheck.data.nexus.MavenArtifact;
import org.owasp.dependencycheck.data.nexus.NexusSearch;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Identifier;
import org.owasp.dependencycheck.utils.Settings;
/**
@@ -161,7 +162,18 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
dependency.getVersionEvidence().addEvidence("nexus", "version", ma.getVersion(), Confidence.HIGH);
}
if (ma.getArtifactUrl() != null && !"".equals(ma.getArtifactUrl())) {
dependency.addIdentifier("maven", ma.toString(), ma.getArtifactUrl(), Confidence.HIGHEST);
boolean found = false;
for (Identifier i : dependency.getIdentifiers()) {
if ("maven".equals(i.getType()) && i.getValue().equals(ma.toString())) {
found = true;
i.setConfidence(Confidence.HIGHEST);
i.setUrl(ma.getArtifactUrl());
break;
}
}
if (!found) {
dependency.addIdentifier("maven", ma.toString(), ma.getArtifactUrl(), Confidence.HIGHEST);
}
}
} catch (IllegalArgumentException iae) {
//dependency.addAnalysisException(new AnalysisException("Invalid SHA-1"));

View File

@@ -64,7 +64,7 @@ public class NexusSearch {
public NexusSearch(URL rootURL) {
this.rootURL = rootURL;
try {
if (null != Settings.getString(Settings.KEYS.PROXY_URL)
if (null != Settings.getString(Settings.KEYS.PROXY_SERVER)
&& Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY)) {
useProxy = true;
LOGGER.fine("Using proxy");

View File

@@ -46,6 +46,7 @@ import org.owasp.dependencycheck.utils.Pair;
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class CveDB {
/**
* The logger.
*/
@@ -247,6 +248,7 @@ public class CveDB {
/**
* SQL Statement to retrieve a property from the database.
*/
@SuppressWarnings("unused")
private static final String SELECT_PROPERTY = "SELECT id, value FROM properties WHERE id = ?";
/**
* SQL Statement to insert a new property.
@@ -259,6 +261,7 @@ public class CveDB {
/**
* SQL Statement to delete a property.
*/
@SuppressWarnings("unused")
private static final String DELETE_PROPERTY = "DELETE FROM properties WHERE id = ?";
//</editor-fold>
@@ -733,8 +736,10 @@ public class CveDB {
final boolean isStruts = "apache".equals(vendor) && "struts".equals(product);
final DependencyVersion v = parseDependencyVersion(cpeId);
final boolean prevAffected = previous != null && !previous.isEmpty();
if (identifiedVersion == null || "-".equals(identifiedVersion.toString())) {
if (v == null || "-".equals(v.toString())) {
if (v == null || "-".equals(v.toString())) { //all versions
affected = true;
} else if (identifiedVersion == null || "-".equals(identifiedVersion.toString())) {
if (prevAffected) {
affected = true;
}
} else if (identifiedVersion.equals(v) || (prevAffected && identifiedVersion.compareTo(v) < 0)) {

View File

@@ -34,7 +34,7 @@ import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
import static org.owasp.dependencycheck.data.nvdcve.DatabaseProperties.MODIFIED;
import org.owasp.dependencycheck.data.update.exception.InvalidDataException;
import org.owasp.dependencycheck.data.update.exception.UpdateException;
import org.owasp.dependencycheck.data.update.task.CallableDownloadTask;
import org.owasp.dependencycheck.data.update.task.DownloadTask;
import org.owasp.dependencycheck.data.update.task.ProcessTask;
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.owasp.dependencycheck.utils.InvalidSettingException;
@@ -122,7 +122,7 @@ public class StandardUpdate {
final Set<Future<Future<ProcessTask>>> downloadFutures = new HashSet<Future<Future<ProcessTask>>>(maxUpdates);
for (NvdCveInfo cve : updateable) {
if (cve.getNeedsUpdate()) {
final CallableDownloadTask call = new CallableDownloadTask(cve, processExecutor, cveDB, Settings.getInstance());
final DownloadTask call = new DownloadTask(cve, processExecutor, cveDB, Settings.getInstance());
downloadFutures.add(downloadExecutors.submit(call));
}
}
@@ -178,7 +178,9 @@ public class StandardUpdate {
if (maxUpdates >= 1) { //ensure the modified file date gets written (we may not have actually updated it)
properties.save(updateable.get(MODIFIED));
LOGGER.log(Level.INFO, "Begin database maintenance.");
cveDB.cleanupDatabase();
LOGGER.log(Level.INFO, "End database maintenance.");
}
} finally {
closeDataStores();

View File

@@ -37,12 +37,12 @@ import org.owasp.dependencycheck.utils.Settings;
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class CallableDownloadTask implements Callable<Future<ProcessTask>> {
public class DownloadTask implements Callable<Future<ProcessTask>> {
/**
* The Logger.
*/
private static final Logger LOGGER = Logger.getLogger(CallableDownloadTask.class.getName());
private static final Logger LOGGER = Logger.getLogger(DownloadTask.class.getName());
/**
* Simple constructor for the callable download task.
@@ -54,7 +54,7 @@ public class CallableDownloadTask implements Callable<Future<ProcessTask>> {
* the dependencies have a correct reference to the global settings.
* @throws UpdateException thrown if temporary files could not be created
*/
public CallableDownloadTask(NvdCveInfo nvdCveInfo, ExecutorService processor, CveDB cveDB, Settings settings) throws UpdateException {
public DownloadTask(NvdCveInfo nvdCveInfo, ExecutorService processor, CveDB cveDB, Settings settings) throws UpdateException {
this.nvdCveInfo = nvdCveInfo;
this.processorService = processor;
this.cveDB = cveDB;
@@ -203,7 +203,7 @@ public class CallableDownloadTask implements Callable<Future<ProcessTask>> {
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, "Download Task Failed", ex);
} finally {
Settings.cleanup();
Settings.cleanup(false);
}
return null;
}

View File

@@ -79,7 +79,7 @@ public class ProcessTask implements Callable<ProcessTask> {
/**
* A reference to the callable download task.
*/
private final CallableDownloadTask filePair;
private final DownloadTask filePair;
/**
* A reference to the properties.
*/
@@ -97,7 +97,7 @@ public class ProcessTask implements Callable<ProcessTask> {
* @param settings a reference to the global settings object; this is necessary so that when the thread is started
* the dependencies have a correct reference to the global settings.
*/
public ProcessTask(final CveDB cveDB, final CallableDownloadTask filePair, Settings settings) {
public ProcessTask(final CveDB cveDB, final DownloadTask filePair, Settings settings) {
this.cveDB = cveDB;
this.filePair = filePair;
this.properties = cveDB.getDatabaseProperties();
@@ -119,7 +119,7 @@ public class ProcessTask implements Callable<ProcessTask> {
} catch (UpdateException ex) {
this.exception = ex;
} finally {
Settings.cleanup();
Settings.cleanup(false);
}
return this;
}

View File

@@ -177,6 +177,33 @@ public class Dependency implements Comparable<Dependency> {
this.filePath = filePath;
}
/**
* The file name to display in reports.
*/
private String displayName = null;
/**
* Sets the file name to display in reports.
*
* @param displayName the name to display
*/
public void setDisplayFileName(String displayName) {
this.displayName = displayName;
}
/**
* 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
*/
public String getDisplayFileName() {
if (displayName == null) {
return this.fileName;
}
return this.displayName;
}
/**
* <p>
* Gets the file path of the dependency.</p>
@@ -369,6 +396,15 @@ public class Dependency implements Comparable<Dependency> {
return EvidenceCollection.merge(this.productEvidence, this.vendorEvidence, this.versionEvidence);
}
/**
* Returns the evidence used to identify this dependency.
*
* @return an EvidenceCollection.
*/
public Set<Evidence> getEvidenceForDisplay() {
return EvidenceCollection.mergeForDisplay(this.productEvidence, this.vendorEvidence, this.versionEvidence);
}
/**
* Returns the evidence used to identify this dependency.
*

View File

@@ -220,22 +220,95 @@ public class Evidence implements Comparable<Evidence> {
* @return an integer indicating the ordering of the two objects
*/
public int compareTo(Evidence o) {
if (source.equals(o.source)) {
if (name.equals(o.name)) {
if (value.equals(o.value)) {
if (confidence.equals(o.confidence)) {
if (o == null) {
return 1;
}
if (equalsWithNullCheck(source, o.source)) {
if (equalsWithNullCheck(name, o.name)) {
if (equalsWithNullCheck(value, o.value)) {
if (equalsWithNullCheck(confidence, o.confidence)) {
return 0; //they are equal
} else {
return confidence.compareTo(o.confidence);
return compareToWithNullCheck(confidence, o.confidence);
}
} else {
return value.compareToIgnoreCase(o.value);
return compareToIgnoreCaseWithNullCheck(value, o.value);
}
} else {
return name.compareToIgnoreCase(o.name);
return compareToIgnoreCaseWithNullCheck(name, o.name);
}
} else {
return source.compareToIgnoreCase(o.source);
return compareToIgnoreCaseWithNullCheck(source, o.source);
}
}
/**
* Equality check with an exhaustive, possibly duplicative, check against nulls.
*
* @param me the value to be compared
* @param other the other value to be compared
* @return true if the values are equal; otherwise false
*/
private boolean equalsWithNullCheck(String me, String other) {
if (me == null && other == null) {
return true;
} else if (me == null || other == null) {
return false;
}
return me.equals(other);
}
/**
* Equality check with an exhaustive, possibly duplicative, check against nulls.
*
* @param me the value to be compared
* @param other the other value to be compared
* @return true if the values are equal; otherwise false
*/
private boolean equalsWithNullCheck(Confidence me, Confidence other) {
if (me == null && other == null) {
return true;
} else if (me == null || other == null) {
return false;
}
return me.equals(other);
}
/**
* Wrapper around {@link java.lang.String#compareToIgnoreCase(java.lang.String) String.compareToIgnoreCase} with an
* exhaustive, possibly duplicative, check against nulls.
*
* @param me the value to be compared
* @param other the other value to be compared
* @return true if the values are equal; otherwise false
*/
private int compareToIgnoreCaseWithNullCheck(String me, String other) {
if (me == null && other == null) {
return 0;
} else if (me == null) {
return -1; //the other string is greater then me
} else if (other == null) {
return 1; //me is greater then the other string
}
return me.compareToIgnoreCase(other);
}
/**
* Wrapper around {@link java.lang.Enum#compareTo(java.lang.Enum) Enum.compareTo} with an exhaustive, possibly
* duplicative, check against nulls.
*
* @param me the value to be compared
* @param other the other value to be compared
* @return true if the values are equal; otherwise false
*/
private int compareToWithNullCheck(Confidence me, Confidence other) {
if (me == null && other == null) {
return 0;
} else if (me == null) {
return -1; //the other string is greater then me
} else if (other == null) {
return 1; //me is greater then the other string
}
return me.compareTo(other);
}
}

View File

@@ -311,6 +311,26 @@ public class EvidenceCollection implements Iterable<Evidence> {
return ret;
}
/**
* Merges multiple EvidenceCollections together; flattening all of the evidence items by removing the confidence.
*
* @param ec One or more EvidenceCollections
* @return new set of evidence resulting from merging the evidence in the collections
*/
public static Set<Evidence> mergeForDisplay(EvidenceCollection... ec) {
final Set<Evidence> ret = new TreeSet<Evidence>();
for (EvidenceCollection col : ec) {
for (Evidence e : col) {
if (e.isUsed()) {
final Evidence newEvidence = new Evidence(e.getSource(), e.getName(), e.getValue(), null);
newEvidence.setUsed(true);
ret.add(newEvidence);
}
}
}
return ret;
}
/**
* Returns a string of evidence 'values'.
*

View File

@@ -77,19 +77,19 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
if (cpeName != null && cpeName.length() > 7) {
final String[] data = cpeName.substring(7).split(":");
if (data.length >= 1) {
this.setVendor(URLDecoder.decode(data[0].replace("+", "%2B"), "UTF-8"));
this.setVendor(urlDecode(data[0]));
}
if (data.length >= 2) {
this.setProduct(URLDecoder.decode(data[1].replace("+", "%2B"), "UTF-8"));
this.setProduct(urlDecode(data[1]));
}
if (data.length >= 3) {
version = URLDecoder.decode(data[2].replace("+", "%2B"), "UTF-8");
version = urlDecode(data[2]);
}
if (data.length >= 4) {
revision = URLDecoder.decode(data[3].replace("+", "%2B"), "UTF-8");
revision = urlDecode(data[3]);
}
if (data.length >= 5) {
edition = URLDecoder.decode(data[4].replace("+", "%2B"), "UTF-8");
edition = urlDecode(data[4]);
}
}
}
@@ -341,4 +341,25 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
public void setEdition(String edition) {
this.edition = edition;
}
/**
* Replaces '+' with '%2B' and then URL Decodes the string attempting first UTF-8, then ASCII, then default.
*
* @param string the string to URL Decode
* @return the URL Decoded string
*/
private String urlDecode(String string) {
final String text = string.replace("+", "%2B");
String result;
try {
result = URLDecoder.decode(text, "UTF-8");
} catch (UnsupportedEncodingException ex) {
try {
result = URLDecoder.decode(text, "ASCII");
} catch (UnsupportedEncodingException ex1) {
result = URLDecoder.decode(text);
}
}
return result;
}
}

View File

@@ -54,6 +54,10 @@ public class SuppressionHandler extends DefaultHandler {
* The CWE element name.
*/
public static final String CWE = "cwe";
/**
* The GAV element name.
*/
public static final String GAV = "gav";
/**
* The cvssBelow element name.
*/
@@ -95,13 +99,10 @@ public class SuppressionHandler extends DefaultHandler {
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
currentAttributes = null;
currentAttributes = attributes;
currentText = new StringBuffer();
if (SUPPRESS.equals(qName)) {
rule = new SuppressionRule();
} else if (FILE_PATH.equals(qName)) {
currentAttributes = attributes;
}
}
@@ -123,6 +124,9 @@ public class SuppressionHandler extends DefaultHandler {
rule.setFilePath(pt);
} else if (SHA1.equals(qName)) {
rule.setSha1(currentText.toString());
} else if (GAV.equals(qName)) {
final PropertyType pt = processPropertyType();
rule.setGav(pt);
} else if (CPE.equals(qName)) {
final PropertyType pt = processPropertyType();
rule.addCpe(pt);

View File

@@ -234,6 +234,37 @@ public class SuppressionRule {
public boolean hasCve() {
return cve.size() > 0;
}
/**
* A Maven GAV to suppression.
*/
private PropertyType gav = null;
/**
* Get the value of Maven GAV.
*
* @return the value of gav
*/
public PropertyType getGav() {
return gav;
}
/**
* Set the value of Maven GAV.
*
* @param gav new value of Maven gav
*/
public void setGav(PropertyType gav) {
this.gav = gav;
}
/**
* Returns whether or not this suppression rule as GAV entries.
*
* @return whether or not this suppression rule as GAV entries
*/
public boolean hasGav() {
return gav != null;
}
/**
* Processes a given dependency to determine if any CPE, CVE, CWE, or CVSS scores should be suppressed. If any
@@ -248,12 +279,27 @@ public class SuppressionRule {
if (sha1 != null && !sha1.equalsIgnoreCase(dependency.getSha1sum())) {
return;
}
if (gav != null) {
final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
boolean gavFound = false;
while (itr.hasNext()) {
final Identifier i = itr.next();
if (identifierMatches("maven", this.gav, i)) {
gavFound = true;
break;
}
}
if (!gavFound) {
return;
}
}
if (this.hasCpe()) {
final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
while (itr.hasNext()) {
final Identifier i = itr.next();
for (PropertyType c : this.cpe) {
if (cpeMatches(c, i)) {
if (identifierMatches("cpe", c, i)) {
dependency.addSuppressedIdentifier(i);
itr.remove();
break;
@@ -309,7 +355,7 @@ public class SuppressionRule {
boolean cpeHasNoVersion(PropertyType c) {
if (c.isRegex()) {
return false;
} // cpe:/a:jboss:jboss:1.0.0:
}
if (countCharacter(c.getValue(), ':') == 3) {
return true;
}
@@ -336,26 +382,75 @@ public class SuppressionRule {
/**
* Determines if the cpeEntry specified as a PropertyType matches the given Identifier.
*
* @param cpeEntry a suppression rule entry
* @param identifierType the type of identifier ("cpe", "maven", etc.)
* @param suppressionEntry a suppression rule entry
* @param identifier a CPE identifier to check
* @return true if the entry matches; otherwise false
*/
boolean cpeMatches(PropertyType cpeEntry, Identifier identifier) {
if (cpeEntry.matches(identifier.getValue())) {
return true;
} else if (cpeHasNoVersion(cpeEntry)) {
if (cpeEntry.isCaseSensitive()) {
if (identifier.getValue().startsWith(cpeEntry.getValue())) {
return true;
}
} else {
final String id = identifier.getValue().toLowerCase();
final String check = cpeEntry.getValue().toLowerCase();
if (id.startsWith(check)) {
return true;
boolean identifierMatches(String identifierType, PropertyType suppressionEntry, Identifier identifier) {
if (identifierType.equals(identifier.getType())) {
if (suppressionEntry.matches(identifier.getValue())) {
return true;
} else if ("cpe".equals(identifierType) && cpeHasNoVersion(suppressionEntry)) {
if (suppressionEntry.isCaseSensitive()) {
return identifier.getValue().startsWith(suppressionEntry.getValue());
} else {
final String id = identifier.getValue().toLowerCase();
final String check = suppressionEntry.getValue().toLowerCase();
return id.startsWith(check);
}
}
}
return false;
}
/**
* Standard toString implementation.
*
* @return a string representation of this object
*/
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("SuppressionRule{");
if (filePath != null) {
sb.append("filePath=").append(filePath).append(",");
}
if (sha1 != null) {
sb.append("sha1=").append(sha1).append(",");
}
if (gav != null) {
sb.append("gav=").append(gav).append(",");
}
if (cpe != null && cpe.size() > 0) {
sb.append("cpe={");
for (PropertyType pt : cpe) {
sb.append(pt).append(",");
}
sb.append("}");
}
if (cwe != null && cwe.size() > 0) {
sb.append("cwe={");
for (String s : cwe) {
sb.append(s).append(",");
}
sb.append("}");
}
if (cve != null && cve.size() > 0) {
sb.append("cve={");
for (String s : cve) {
sb.append(s).append(",");
}
sb.append("}");
}
if (cvssBelow != null && cvssBelow.size() > 0) {
sb.append("cvssBelow={");
for (Float s : cvssBelow) {
sb.append(s).append(",");
}
sb.append("}");
}
sb.append("}");
return sb.toString();
}
}

View File

@@ -0,0 +1,147 @@
/*
* 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.utils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.owasp.dependencycheck.Engine;
import static org.owasp.dependencycheck.utils.FileUtils.getFileExtension;
/**
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public final class ExtractionUtil {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(ExtractionUtil.class.getName());
/**
* The buffer size to use when extracting files from the archive.
*/
private static final int BUFFER_SIZE = 4096;
/**
* Private constructor for a utility class.
*/
private ExtractionUtil() {
}
/**
* Extracts the contents of an archive into the specified directory.
*
* @param archive an archive file such as a WAR or EAR
* @param extractTo a directory to extract the contents to
* @throws ExtractionException thrown if an exception occurs while extracting the files
*/
public static void extractFiles(File archive, File extractTo) throws ExtractionException {
extractFiles(archive, extractTo, null);
}
/**
* Extracts the contents of an archive into the specified directory. The files are only extracted if they are
* supported by the analyzers loaded into the specified engine. If the engine is specified as null then all files
* are extracted.
*
* @param archive an archive file such as a WAR or EAR
* @param extractTo a directory to extract the contents to
* @param engine the scanning engine
* @throws ExtractionException thrown if there is an error extracting the files
*/
public static void extractFiles(File archive, File extractTo, Engine engine) throws ExtractionException {
if (archive == null || extractTo == null) {
return;
}
FileInputStream fis = null;
ZipInputStream zis = null;
try {
fis = new FileInputStream(archive);
} catch (FileNotFoundException ex) {
LOGGER.log(Level.FINE, null, ex);
throw new ExtractionException("Archive file was not found.", ex);
}
zis = new ZipInputStream(new BufferedInputStream(fis));
ZipEntry entry;
try {
while ((entry = zis.getNextEntry()) != null) {
if (entry.isDirectory()) {
final File d = new File(extractTo, entry.getName());
if (!d.exists() && !d.mkdirs()) {
final String msg = String.format("Unable to create '%s'.", d.getAbsolutePath());
throw new ExtractionException(msg);
}
} else {
final File file = new File(extractTo, entry.getName());
final String ext = getFileExtension(file.getName());
if (engine == null || engine.supportsExtension(ext)) {
BufferedOutputStream bos = null;
FileOutputStream fos;
try {
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos, BUFFER_SIZE);
int count;
final byte data[] = new byte[BUFFER_SIZE];
while ((count = zis.read(data, 0, BUFFER_SIZE)) != -1) {
bos.write(data, 0, count);
}
bos.flush();
} catch (FileNotFoundException ex) {
LOGGER.log(Level.FINE, null, ex);
final String msg = String.format("Unable to find file '%s'.", file.getName());
throw new ExtractionException(msg, ex);
} catch (IOException ex) {
LOGGER.log(Level.FINE, null, ex);
final String msg = String.format("IO Exception while parsing file '%s'.", file.getName());
throw new ExtractionException(msg, ex);
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException ex) {
LOGGER.log(Level.FINEST, null, ex);
}
}
}
}
}
}
} catch (IOException ex) {
final String msg = String.format("Exception reading archive '%s'.", archive.getName());
LOGGER.log(Level.FINE, msg, ex);
throw new ExtractionException(msg, ex);
} finally {
try {
zis.close();
} catch (IOException ex) {
LOGGER.log(Level.FINEST, null, ex);
}
}
}
}

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://www.owasp.org/index.php/OWASP_Dependency_Check_Suppression">
<suppress>
<notes><![CDATA[
This suppresses false positives identified on spring security.
]]></notes>
<gav regex="true">org\.springframework\.security:spring.*</gav>
<cpe>cpe:/a:mod_security:mod_security</cpe>
<cpe>cpe:/a:springsource:spring_framework</cpe>
<cpe>cpe:/a:vmware:springsource_spring_framework</cpe>
</suppress>
</suppressions>

View File

@@ -0,0 +1,10 @@
analyzer.AssemblyAnalyzer.notdeployed=GrokAssembly didn't get deployed
analyzer.AssemblyAnalyzer.grokassembly.stderr=Error from GrokAssembly: {0}
analyzer.AssemblyAnalyzer.notassembly={0} is not a .NET assembly or executable and as such cannot be analyzed by dependency-check
analyzer.AssemblyAnalyzer.grokassembly.rc=Return code {0} from GrokAssembly
analyzer.AssemblyAnalyzer.grokassembly.deployed=Extracted GrokAssembly.exe to {0}
analyzer.AssemblyAnalyzer.grokassembly.notdeployed=Could not extract GrokAssembly.exe: {0}
analyzer.AssemblyAnalyzer.grokassembly.initialization.failed=An error occurred with the .NET AssemblyAnalyzer; \
this can be ignored unless you are scanning .NET DLLs. Please see the log for more details.
analyzer.AssemblyAnalyzer.grokassembly.initialization.message=Could not execute GrokAssembly {0}
analyzer.AssemblyAnalyzer.grokassembly.notdeleted=Can't delete temporary GrokAssembly.exe

View File

@@ -41,6 +41,7 @@
<xs:choice minOccurs="0" maxOccurs="1">
<xs:element name="filePath" type="dc:regexStringType"/>
<xs:element name="sha1" type="dc:sha1Type"/>
<xs:element name="gav" type="dc:regexStringType"/>
</xs:choice>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="cpe" type="dc:regexStringType"/>

View File

@@ -532,11 +532,11 @@ arising out of or in connection with the use of this tool, the analysis performe
#foreach($dependency in $dependencies)
#set($lnkcnt=$lnkcnt+1)
<li class="#if($dependency.getVulnerabilities().size()==0)notvulnerable#else vulnerable#end">
<a href="#l${lnkcnt}_$enc.html($enc.url($dependency.Sha1sum))">$enc.html($dependency.FileName)</a>
<a href="#l${lnkcnt}_$enc.html($enc.url($dependency.Sha1sum))">$enc.html($dependency.DisplayFileName)</a>
#if($dependency.getRelatedDependencies().size()>0)
<ul>
#foreach($related in $dependency.getRelatedDependencies())
<li>$enc.html($related.FileName)</li>
<li>$enc.html($related.DisplayFileName)</li>
#end
</ul>
#end
@@ -549,7 +549,7 @@ arising out of or in connection with the use of this tool, the analysis performe
#set($vsctr=0) ##counter to create unique groups for vulnerable software
#foreach($dependency in $dependencies)
#set($lnkcnt=$lnkcnt+1)
<h3 class="subsectionheader standardsubsection#if($dependency.getVulnerabilities().size()==0) notvulnerable#end"><a name="l${lnkcnt}_$enc.html($dependency.Sha1sum)"></a>$enc.html($dependency.FileName)</h3>
<h3 class="subsectionheader standardsubsection#if($dependency.getVulnerabilities().size()==0) notvulnerable#end"><a name="l${lnkcnt}_$enc.html($dependency.Sha1sum)"></a>$enc.html($dependency.DisplayFileName)</h3>
<div class="subsectioncontent#if($dependency.getVulnerabilities().size()==0) notvulnerable#end">
#if ($dependency.description)
<p><b>Description:</b>&nbsp;$enc.html($dependency.description)<br/></p>
@@ -571,7 +571,7 @@ arising out of or in connection with the use of this tool, the analysis performe
<div id="content$cnt" class="subsectioncontent standardsubsection hidden">
<table class="lined fullwidth" border="0">
<tr><th class="left" style="width:10%;">Source</th><th class="left" style="width:20%;">Name</th><th class="left" style="width:70%;">Value</th></tr>
#foreach($evidence in $dependency.getEvidenceUsed())
#foreach($evidence in $dependency.getEvidenceForDisplay())
<tr><td>$enc.html($evidence.getSource())</td><td>$enc.html($evidence.getName())</td><td>$enc.html($evidence.getValue())</td></tr>
#end
</table>
@@ -582,7 +582,7 @@ arising out of or in connection with the use of this tool, the analysis performe
<div id="content$cnt" class="subsectioncontent standardsubsection hidden">
<ul>
#foreach($related in $dependency.getRelatedDependencies())
<li>$enc.html($related.FileName)
<li>$enc.html($related.DisplayFileName)
<ul>
<li>File Path:&nbsp;$enc.html($related.FilePath)</li>
<li>SHA1:&nbsp;$enc.html($related.Sha1sum)</li>
@@ -612,7 +612,7 @@ arising out of or in connection with the use of this tool, the analysis performe
#end
#end
<h4 id="header$cnt" class="subsectionheader white">Identifiers</h4>
##:&nbsp;<a href="http://web.nvd.nist.gov/view/vuln/search-results?cpe=$enc.url($cpevalue)" target="_blank">$enc.html($cpevalue)</a></h4>
##:&nbsp;<a href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($cpevalue)" target="_blank">$enc.html($cpevalue)</a></h4>
<div id="content$cnt" class="subsectioncontent standardsubsection">
#if ($dependency.getIdentifiers().size()==0)
<ul><li><b>None</b></li></ul>
@@ -668,13 +668,20 @@ arising out of or in connection with the use of this tool, the analysis performe
</ul>
#end
</p>
<p>Vulnerable Software &amp; Versions:&nbsp;(<a href="#" onclick="toggleDisplay(this,'.vs$vsctr'); return false;">show all</a>)<ul>
<li class="vs$vsctr"><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/search-results?cpe=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
<li class="vs$vsctr">...</li>
#foreach($vs in $vuln.getVulnerableSoftware())
<li class="vs$vsctr hidden"><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/search-results?cpe=$enc.url($vs.name)">$enc.html($vs.name)</a> #if($vs.hasPreviousVersion()) and all previous versions#end</li>
#if ($vuln.getVulnerableSoftware().size()<2)
<p>Vulnerable Software &amp; Versions:<ul>
<li class="vs$vsctr"><a target="_blank" href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
</ul></p>
#else
<p>Vulnerable Software &amp; Versions:&nbsp;(<a href="#" onclick="toggleDisplay(this,'.vs$vsctr'); return false;">show all</a>)<ul>
<li class="vs$vsctr"><a target="_blank" href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
<li class="vs$vsctr">...</li>
#foreach($vs in $vuln.getVulnerableSoftware())
<li class="vs$vsctr hidden"><a target="_blank" href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($vs.name)">$enc.html($vs.name)</a> #if($vs.hasPreviousVersion()) and all previous versions#end</li>
#end
</ul></p>
#end
</ul></p>
#end
</div>
#end
@@ -692,7 +699,7 @@ arising out of or in connection with the use of this tool, the analysis performe
#foreach($dependency in $dependencies)
#if ($dependency.getSuppressedIdentifiers().size()>0 || $dependency.getSuppressedVulnerabilities().size()>0)
#set($lnkcnt=$lnkcnt+1)
<h3 class="subsectionheader standardsubsection">$enc.html($dependency.FileName)</h3>
<h3 class="subsectionheader standardsubsection">$enc.html($dependency.DisplayFileName)</h3>
<div class="subsectioncontent">
#if ($dependency.description)
<p><b>Description:</b>&nbsp;$enc.html($dependency.description)<br/></p>
@@ -714,7 +721,7 @@ arising out of or in connection with the use of this tool, the analysis performe
<div id="content$cnt" class="subsectioncontent standardsubsection hidden">
<table class="lined fullwidth" border="0">
<tr><th class="left" style="width:10%;">Source</th><th class="left" style="width:20%;">Name</th><th class="left" style="width:70%;">Value</th></tr>
#foreach($evidence in $dependency.getEvidenceUsed())
#foreach($evidence in $dependency.getEvidenceForDisplay())
<tr><td>$enc.html($evidence.getSource())</td><td>$enc.html($evidence.getName())</td><td>$enc.html($evidence.getValue())</td></tr>
#end
</table>
@@ -725,7 +732,7 @@ arising out of or in connection with the use of this tool, the analysis performe
<div id="content$cnt" class="subsectioncontent standardsubsection hidden">
<ul>
#foreach($related in $dependency.getRelatedDependencies())
<li>$enc.html($related.FileName)
<li>$enc.html($related.DisplayFileName)
<ul>
<li>File Path:&nbsp;$enc.html($related.FilePath)</li>
<li>SHA1:&nbsp;$enc.html($related.Sha1sum)</li>
@@ -744,7 +751,7 @@ arising out of or in connection with the use of this tool, the analysis performe
#end
#end
<h4 id="header$cnt" class="subsectionheader white">Suppressed Identifiers</h4>
##:&nbsp;<a href="http://web.nvd.nist.gov/view/vuln/search-results?cpe=$enc.url($cpevalue)" target="_blank">$enc.html($cpevalue)</a></h4>
##:&nbsp;<a href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($cpevalue)" target="_blank">$enc.html($cpevalue)</a></h4>
<div id="content$cnt" class="subsectioncontent standardsubsection">
#if ($dependency.getSuppressedIdentifiers().size()==0)
<ul><li><b>None</b></li></ul>
@@ -796,13 +803,19 @@ arising out of or in connection with the use of this tool, the analysis performe
</ul>
#end
</p>
<p>Vulnerable Software &amp; Versions:&nbsp;(<a href="#" onclick="toggleDisplay(this,'.vs$vsctr'); return false;">show all</a>)<ul>
<li class="vs$vsctr"><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/search-results?cpe=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
<li class="vs$vsctr">...</li>
#foreach($vs in $vuln.getVulnerableSoftware())
<li class="vs$vsctr hidden"><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/search-results?cpe=$enc.url($vs.name)">$enc.html($vs.name)</a> #if($vs.hasPreviousVersion()) and all previous versions#end</li>
#if ($vuln.getVulnerableSoftware().size()<2)
<p>Vulnerable Software &amp; Versions:<ul>
git st<li class="vs$vsctr"><a target="_blank" href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
</ul></p>
#else
<p>Vulnerable Software &amp; Versions:&nbsp;(<a href="#" onclick="toggleDisplay(this,'.vs$vsctr'); return false;">show all</a>)<ul>
<li class="vs$vsctr"><a target="_blank" href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
<li class="vs$vsctr">...</li>
#foreach($vs in $vuln.getVulnerableSoftware())
<li class="vs$vsctr hidden"><a target="_blank" href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($vs.name)">$enc.html($vs.name)</a> #if($vs.hasPreviousVersion()) and all previous versions#end</li>
#end
</ul></p>
#end
</ul></p>
#end
</div>
#end

View File

@@ -222,10 +222,10 @@ arising out of or in connection with the use of this tool, the analysis performe
($vuln.cvssScore)
<td>#set($cnt=$cnt+1)
#if($dependency.getRelatedDependencies().size()>0)<span id="header$cnt" class="expandable collapsedList">#end
$enc.html($dependency.FileName)
$enc.html($dependency.DisplayFileName)
#if($dependency.getRelatedDependencies().size()>0)&nbsp;&nbsp;&nbsp;</span><div id="content$cnt" class="hidden">#end
#foreach($related in $dependency.getRelatedDependencies())
$enc.html($related.FileName)<br/>
$enc.html($related.DisplayFileName)<br/>
#end
#if($dependency.getRelatedDependencies().size()>0)</div#end
</td>

View File

@@ -36,7 +36,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<dependencies>
#foreach($dependency in $dependencies)
<dependency>
<fileName>$enc.xml($dependency.FileName)</fileName>
<fileName>$enc.xml($dependency.DisplayFileName)</fileName>
<filePath>$enc.xml($dependency.FilePath)</filePath>
<md5>$enc.xml($dependency.Md5sum)</md5>
<sha1>$enc.xml($dependency.Sha1sum)</sha1>
@@ -68,7 +68,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</relatedDependencies>
#end
<evidenceCollected>
#foreach($evidence in $dependency.getEvidenceUsed())
#foreach($evidence in $dependency.getEvidenceForDisplay())
<evidence>
<source>$enc.xml($evidence.getSource())</source>
<name>$enc.xml($evidence.getName())</name>

View File

@@ -32,6 +32,6 @@ public class BaseTest {
@AfterClass
public static void tearDownClass() throws Exception {
Settings.cleanup();
Settings.cleanup(true);
}
}

View File

@@ -17,31 +17,78 @@
*/
package org.owasp.dependencycheck.analyzer;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import org.junit.Before;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.suppression.SuppressionParseException;
import org.owasp.dependencycheck.suppression.SuppressionRule;
import org.owasp.dependencycheck.utils.Settings;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class AbstractSuppressionAnalyzerTest extends BaseTest {
private AbstractSuppressionAnalyzer instance;
@Before
public void setUp() throws Exception {
public void createObjectUnderTest() throws Exception {
instance = new AbstractSuppressionAnalyzerImpl();
}
/**
* Test of getSupportedExtensions method, of class AbstractSuppressionAnalyzer.
*/
@Test
public void testGetSupportedExtensions() {
Set<String> result = instance.getSupportedExtensions();
assertNull(result);
}
/**
* Test of getRules method, of class AbstractSuppressionAnalyzer for suppression file declared as URL.
*/
@Test
public void testGetRulesFromSuppressionFileFromURL() throws Exception {
setSupressionFileFromURL();
instance.initialize();
int expCount = 5;
List<SuppressionRule> result = instance.getRules();
assertTrue(expCount <= result.size());
}
/**
* Test of getRules method, of class AbstractSuppressionAnalyzer for suppression file declared as URL.
*/
@Test
public void testGetRulesFromSuppressionFileInClasspath() throws Exception {
Settings.setString(Settings.KEYS.SUPPRESSION_FILE, "suppressions.xml");
instance.initialize();
int expCount = 5;
List<SuppressionRule> result = instance.getRules();
assertTrue(expCount <= result.size());
}
@Test(expected = SuppressionParseException.class)
public void testFailureToLocateSuppressionFileAnywhere() throws Exception {
Settings.setString(Settings.KEYS.SUPPRESSION_FILE, "doesnotexist.xml");
instance.initialize();
}
private void setSupressionFileFromURL() throws Exception {
try {
final String uri = this.getClass().getClassLoader().getResource("suppressions.xml").toURI().toURL().toString();
Settings.setString(Settings.KEYS.SUPPRESSION_FILE, uri);
@@ -52,37 +99,6 @@ public class AbstractSuppressionAnalyzerTest extends BaseTest {
}
}
/**
* Test of getSupportedExtensions method, of class AbstractSuppressionAnalyzer.
*/
@Test
public void testGetSupportedExtensions() {
AbstractSuppressionAnalyzer instance = new AbstractSuppressionAnalyzerImpl();
Set<String> result = instance.getSupportedExtensions();
assertNull(result);
}
/**
* Test of initialize method, of class AbstractSuppressionAnalyzer.
*/
@Test
public void testInitialize() throws Exception {
AbstractSuppressionAnalyzer instance = new AbstractSuppressionAnalyzerImpl();
instance.initialize();
}
/**
* Test of getRules method, of class AbstractSuppressionAnalyzer.
*/
@Test
public void testGetRules() throws Exception {
AbstractSuppressionAnalyzer instance = new AbstractSuppressionAnalyzerImpl();
instance.initialize();
int expCount = 5;
List<SuppressionRule> result = instance.getRules();
assertEquals(expCount, result.size());
}
public class AbstractSuppressionAnalyzerImpl extends AbstractSuppressionAnalyzer {
@Override

View File

@@ -115,16 +115,13 @@ public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase {
FalsePositiveAnalyzer fp = new FalsePositiveAnalyzer();
fp.analyze(dep, null);
// for (Identifier i : dep.getIdentifiers()) {
// System.out.println(i.getValue());
// }
if (expResult != null) {
Identifier expIdentifier = new Identifier("cpe", expResult, expResult);
Assert.assertTrue("Incorrect match: { dep:'" + dep.getFileName() + "' }", dep.getIdentifiers().contains(expIdentifier));
} else if (dep.getIdentifiers().isEmpty()) {
Assert.assertTrue("Match found when an Identifier should not have been found: { dep:'" + dep.getFileName() + "' }", dep.getIdentifiers().isEmpty());
} else {
Assert.assertTrue("Match found when an Identifier should not have been found: { dep:'" + dep.getFileName() + "', identifier:'" + dep.getIdentifiers().iterator().next().getValue() + "' }", dep.getIdentifiers().isEmpty());
for (Identifier i : dep.getIdentifiers()) {
Assert.assertFalse(String.format("%s - found a CPE identifier when should have been none (found '%s')", dep.getFileName(), i.getValue()), "cpe".equals(i.getType()));
}
}
}
@@ -170,7 +167,10 @@ public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase {
String expResultSpring = "cpe:/a:springsource:spring_framework:2.5.5";
String expResultSpring3 = "cpe:/a:vmware:springsource_spring_framework:3.0.0";
Assert.assertTrue("Apache Common Validator - found an identifier?", commonValidator.getIdentifiers().isEmpty());
for (Identifier i : commonValidator.getIdentifiers()) {
Assert.assertFalse("Apache Common Validator - found a CPE identifier?", "cpe".equals(i.getType()));
}
Assert.assertTrue("Incorrect match size - struts", struts.getIdentifiers().size() >= 1);
Assert.assertTrue("Incorrect match - struts", struts.getIdentifiers().contains(expIdentifier));
Assert.assertTrue("Incorrect match size - spring3 - " + spring3.getIdentifiers().size(), spring3.getIdentifiers().size() >= 1);

View File

@@ -56,6 +56,7 @@ public class FalsePositiveAnalyzerTest {
public void testAnalyze() throws Exception {
Dependency dependency = new Dependency();
dependency.setFileName("pom.xml");
dependency.setFilePath("pom.xml");
dependency.addIdentifier("cpe", "cpe:/a:file:file:1.2.1", "http://some.org/url");
Engine engine = null;
FalsePositiveAnalyzer instance = new FalsePositiveAnalyzer();

View File

@@ -61,19 +61,26 @@ public class VulnerabilitySuppressionAnalyzerIntegrationTest extends AbstractDat
@Test
public void testAnalyze() throws Exception {
File file = new File(this.getClass().getClassLoader().getResource("FileHelpers.2.0.0.0.nupkg").getPath());
File suppression = new File(this.getClass().getClassLoader().getResource("FileHelpers.2.0.0.0.suppression.xml").getPath());
File file = new File(this.getClass().getClassLoader().getResource("commons-fileupload-1.2.1.jar").getPath());
File suppression = new File(this.getClass().getClassLoader().getResource("commons-fileupload-1.2.1.suppression.xml").getPath());
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false);
Engine engine = new Engine();
engine.scan(file);
engine.analyzeDependencies();
Dependency dependency = getDependency(engine, file);
assertTrue(dependency.getVulnerabilities().size() > 0);
int cveSize = dependency.getVulnerabilities().size();
int cpeSize = dependency.getIdentifiers().size();
assertTrue(cveSize > 0);
assertTrue(cpeSize > 0);
Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppression.getAbsolutePath());
VulnerabilitySuppressionAnalyzer instance = new VulnerabilitySuppressionAnalyzer();
instance.initialize();
instance.analyze(dependency, engine);
assertTrue(dependency.getVulnerabilities().size() == 0);
cveSize = cveSize > 1 ? cveSize - 2 : 0;
cpeSize = cpeSize > 0 ? cpeSize - 1 : 0;
assertTrue(dependency.getVulnerabilities().size() == cveSize);
assertTrue(dependency.getIdentifiers().size() == cpeSize);
engine.cleanup();
}

View File

@@ -17,8 +17,12 @@
*/
package org.owasp.dependencycheck.data.update;
import java.io.File;
import java.util.Calendar;
import org.junit.Before;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.utils.Settings;
/**
*
@@ -26,6 +30,32 @@ import org.owasp.dependencycheck.BaseTest;
*/
public class NvdCveUpdaterIntegrationTest extends BaseTest {
@Before
public void setUp() throws Exception {
int year = Calendar.getInstance().get(Calendar.YEAR);
if (year <= 2014) {
File f = new File(NvdCveUpdaterIntegrationTest.class.getClassLoader().getResource("nvdcve-2.0-2014.xml").getPath());
String baseURL = f.toURI().toURL().toString();
String modified12 = baseURL.replace("nvdcve-2.0-2014.xml", "nvdcve-modified.xml");
String modified20 = baseURL.replace("nvdcve-2.0-2014.xml", "nvdcve-2.0-modified.xml");
String full12 = baseURL.replace("nvdcve-2.0-2014.xml", "nvdcve-%d.xml");
String full20 = baseURL.replace("nvdcve-2.0-2014.xml", "nvdcve-2.0-%d.xml");
// cve.url-1.2.modified=http://nvd.nist.gov/download/nvdcve-modified.xml
// cve.url-2.0.modified=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
// cve.startyear=2014
// cve.url-2.0.base=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
// cve.url-1.2.base=http://nvd.nist.gov/download/nvdcve-%d.xml
Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, modified12);
Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, modified20);
Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, full12);
Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, full20);
Settings.setString(Settings.KEYS.CVE_START_YEAR, "2014");
} else {
System.err.println("Consider updating the local data files to make the NvdCveUpdaterIntegrationTest perform faster");
}
}
/**
* Test of update method, of class NvdCveUpdater.
*/

View File

@@ -67,16 +67,16 @@ public class StandardUpdateIntegrationTest extends BaseTest {
result = instance.withinRange(lastRun, current, range);
assertEquals(expResult, result);
}
/**
* Test of update method, of class StandardUpdate.
*/
@Test
public void testUpdate() throws Exception {
StandardUpdate instance = getStandardUpdateTask();
instance.update();
//TODO make this an actual test
}
// test removed as it is duplicative of the EngineIntegrationTest and the NvdCveUpdaterIntergraionTest
// /**
// * Test of update method, of class StandardUpdate.
// */
// @Test
// public void testUpdate() throws Exception {
// StandardUpdate instance = getStandardUpdateTask();
// instance.update();
// //TODO make this an actual test
// }
/**
* Test of updatesNeeded method, of class StandardUpdate.

View File

@@ -339,55 +339,70 @@ public class SuppressionRuleTest {
}
/**
* Test of cpeMatches method, of class SuppressionRule.
* Test of identifierMatches method, of class SuppressionRule.
*/
@Test
public void testCpeMatches() {
Identifier identifier = new Identifier("cwe", "cpe:/a:microsoft:.net_framework:4.5", "some url not needed for this test");
Identifier identifier = new Identifier("cpe", "cpe:/a:microsoft:.net_framework:4.5", "some url not needed for this test");
PropertyType cpe = new PropertyType();
cpe.setValue("cpe:/a:microsoft:.net_framework:4.5");
SuppressionRule instance = new SuppressionRule();
boolean expResult = true;
boolean result = instance.cpeMatches(cpe, identifier);
boolean result = instance.identifierMatches("cpe", cpe, identifier);
assertEquals(expResult, result);
cpe.setValue("cpe:/a:microsoft:.net_framework:4.0");
expResult = false;
result = instance.cpeMatches(cpe, identifier);
result = instance.identifierMatches("cpe", cpe, identifier);
assertEquals(expResult, result);
cpe.setValue("CPE:/a:microsoft:.net_framework:4.5");
cpe.setCaseSensitive(true);
expResult = false;
result = instance.cpeMatches(cpe, identifier);
result = instance.identifierMatches("cpe", cpe, identifier);
assertEquals(expResult, result);
cpe.setValue("cpe:/a:microsoft:.net_framework");
cpe.setCaseSensitive(false);
expResult = true;
result = instance.cpeMatches(cpe, identifier);
result = instance.identifierMatches("cpe", cpe, identifier);
assertEquals(expResult, result);
cpe.setValue("cpe:/a:microsoft:.*");
cpe.setRegex(true);
expResult = true;
result = instance.cpeMatches(cpe, identifier);
result = instance.identifierMatches("cpe", cpe, identifier);
assertEquals(expResult, result);
cpe.setValue("CPE:/a:microsoft:.*");
cpe.setRegex(true);
cpe.setCaseSensitive(true);
expResult = false;
result = instance.cpeMatches(cpe, identifier);
result = instance.identifierMatches("cpe", cpe, identifier);
assertEquals(expResult, result);
cpe.setValue("cpe:/a:apache:.*");
cpe.setRegex(true);
cpe.setCaseSensitive(false);
expResult = false;
result = instance.cpeMatches(cpe, identifier);
result = instance.identifierMatches("cpe", cpe, identifier);
assertEquals(expResult, result);
identifier = new Identifier("maven", "org.springframework:spring-core:2.5.5", "https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.springframework&a=spring-core&v=2.5.5&e=jar");
cpe.setValue("org.springframework:spring-core:2.5.5");
cpe.setRegex(false);
cpe.setCaseSensitive(false);
expResult = true;
result = instance.identifierMatches("maven", cpe, identifier);
assertEquals(expResult, result);
cpe.setValue("org\\.springframework\\.security:spring.*");
cpe.setRegex(true);
cpe.setCaseSensitive(false);
expResult = false;
result = instance.identifierMatches("maven", cpe, identifier);
assertEquals(expResult, result);
}
@@ -398,7 +413,7 @@ public class SuppressionRuleTest {
public void testProcess() {
File struts = new File(this.getClass().getClassLoader().getResource("struts2-core-2.1.2.jar").getPath());
Dependency dependency = new Dependency(struts);
dependency.addIdentifier("cwe", "cpe:/a:microsoft:.net_framework:4.5", "some url not needed for this test");
dependency.addIdentifier("cpe", "cpe:/a:microsoft:.net_framework:4.5", "some url not needed for this test");
String sha1 = dependency.getSha1sum();
dependency.setSha1sum("384FAA82E193D4E4B0546059CA09572654BC3970");
Vulnerability v = createVulnerability();
@@ -455,9 +470,9 @@ public class SuppressionRuleTest {
assertTrue(dependency.getIdentifiers().isEmpty());
assertTrue(dependency.getSuppressedIdentifiers().size() == 1);
dependency.addIdentifier("cwe", "cpe:/a:microsoft:.net_framework:4.0", "some url not needed for this test");
dependency.addIdentifier("cwe", "cpe:/a:microsoft:.net_framework:4.5", "some url not needed for this test");
dependency.addIdentifier("cwe", "cpe:/a:microsoft:.net_framework:5.0", "some url not needed for this test");
dependency.addIdentifier("cpe", "cpe:/a:microsoft:.net_framework:4.0", "some url not needed for this test");
dependency.addIdentifier("cpe", "cpe:/a:microsoft:.net_framework:4.5", "some url not needed for this test");
dependency.addIdentifier("cpe", "cpe:/a:microsoft:.net_framework:5.0", "some url not needed for this test");
pt = new PropertyType();
pt.setValue("cpe:/a:microsoft:.net_framework");
instance.addCpe(pt);
@@ -467,6 +482,43 @@ public class SuppressionRuleTest {
assertTrue(dependency.getSuppressedIdentifiers().size() == 3);
}
/**
* Test of process method, of class SuppressionRule.
*/
@Test
public void testProcessGAV() {
File spring = new File(this.getClass().getClassLoader().getResource("spring-security-web-3.0.0.RELEASE.jar").getPath());
Dependency dependency = new Dependency(spring);
dependency.addIdentifier("cpe", "cpe:/a:vmware:springsource_spring_framework:3.0.0", "some url not needed for this test");
dependency.addIdentifier("cpe", "cpe:/a:springsource:spring_framework:3.0.0", "some url not needed for this test");
dependency.addIdentifier("cpe", "cpe:/a:mod_security:mod_security:3.0.0", "some url not needed for this test");
dependency.addIdentifier("cpe", "cpe:/a:vmware:springsource_spring_security:3.0.0", "some url not needed for this test");
dependency.addIdentifier("maven", "org.springframework.security:spring-security-web:3.0.0.RELEASE", "some url not needed for this test");
//cpe
SuppressionRule instance = new SuppressionRule();
PropertyType pt = new PropertyType();
pt.setValue("org\\.springframework\\.security:spring.*");
pt.setRegex(true);
pt.setCaseSensitive(false);
instance.setGav(pt);
pt = new PropertyType();
pt.setValue("cpe:/a:mod_security:mod_security");
instance.addCpe(pt);
pt = new PropertyType();
pt.setValue("cpe:/a:springsource:spring_framework");
instance.addCpe(pt);
pt = new PropertyType();
pt.setValue("cpe:/a:vmware:springsource_spring_framework");
instance.addCpe(pt);
instance.process(dependency);
assertEquals(2, dependency.getIdentifiers().size());
}
private Vulnerability createVulnerability() {
Vulnerability v = new Vulnerability();
v.setCwe("CWE-287 Improper Authentication");

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://www.owasp.org/index.php/OWASP_Dependency_Check_Suppression">
<suppress>
<notes><![CDATA[
file name: FileHelpers.2.0.0.0.nupkg
]]></notes>
<sha1>30FB37D6163CF16E3BA740343BECDD14D5457619</sha1>
<cve>CVE-2007-1536</cve>
</suppress>
</suppressions>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://www.owasp.org/index.php/OWASP_Dependency_Check_Suppression">
<suppress>
<notes><![CDATA[
file name: commons-fileupload-1.2.1.jar
]]></notes>
<sha1>384FAA82E193D4E4B0546059CA09572654BC3970</sha1>
<cpe>cpe:/a:apache:commons_fileupload:1.2.1</cpe>
</suppress>
<suppress>
<notes><![CDATA[
file name: commons-fileupload-1.2.1.jar
]]></notes>
<sha1>384FAA82E193D4E4B0546059CA09572654BC3970</sha1>
<cve>CVE-2014-0050</cve>
</suppress>
<suppress>
<notes><![CDATA[
file name: commons-fileupload-1.2.1.jar
]]></notes>
<sha1>384FAA82E193D4E4B0546059CA09572654BC3970</sha1>
<cve>CVE-2013-0248</cve>
</suppress>
</suppressions>

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.0</version>
<version>1.2.2</version>
</parent>
<groupId>org.owasp</groupId>

View File

@@ -15,7 +15,6 @@ limitations under the License.
Copyright (c) 2013 Jeremy Long. All Rights Reserved.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<url>http://maven.apache.org</url>
@@ -23,7 +22,7 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.0</version>
<version>1.2.2</version>
</parent>
<artifactId>dependency-check-maven</artifactId>
@@ -277,6 +276,11 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
<artifactId>dependency-check-core</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-utils</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>

View File

@@ -147,15 +147,6 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR
@SuppressWarnings({"CanBeFinal", "FieldCanBeLocal"})
@Parameter(property = "externalReport", defaultValue = "false", required = true)
private boolean externalReport = false;
/**
* The Proxy URL.
*
* @deprecated Please use mavenSettings instead
*/
@SuppressWarnings({"CanBeFinal", "FieldCanBeLocal"})
@Parameter(property = "proxyUrl", defaultValue = "", required = false)
@Deprecated
private String proxyUrl = null;
/**
* The maven settings.
@@ -171,33 +162,6 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR
@Parameter(property = "mavenSettingsProxyId", required = false)
private String mavenSettingsProxyId;
/**
* The Proxy Port.
*
* @deprecated Please use mavenSettings instead
*/
@SuppressWarnings({"CanBeFinal", "FieldCanBeLocal"})
@Parameter(property = "proxyPort", defaultValue = "", required = false)
@Deprecated
private String proxyPort = null;
/**
* The Proxy username.
*
* @deprecated Please use mavenSettings instead
*/
@SuppressWarnings({"CanBeFinal", "FieldCanBeLocal"})
@Parameter(property = "proxyUsername", defaultValue = "", required = false)
@Deprecated
private String proxyUsername = null;
/**
* The Proxy password.
*
* @deprecated Please use mavenSettings instead
*/
@SuppressWarnings({"CanBeFinal", "FieldCanBeLocal"})
@Parameter(property = "proxyPassword", defaultValue = "", required = false)
@Deprecated
private String proxyPassword = null;
/**
* The Connection Timeout.
*/
@@ -348,6 +312,16 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR
@Parameter(property = "pathToMono", defaultValue = "", required = false)
private String pathToMono;
/**
* The Proxy URL.
*
* @deprecated Please use mavenSettings instead
*/
@SuppressWarnings({"CanBeFinal", "FieldCanBeLocal"})
@Parameter(property = "proxyUrl", defaultValue = "", required = false)
@Deprecated
private String proxyUrl = null;
// </editor-fold>
/**
* Executes the Dependency-Check on the dependent libraries.
@@ -613,7 +587,8 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR
*/
private int writeSiteReportDependencyEvidenceUsed(Dependency d, int collapsibleHeaderCount, Sink sink) {
int cnt = collapsibleHeaderCount;
if (d.getEvidenceUsed() != null && d.getEvidenceUsed().size() > 0) {
final Set<Evidence> evidence = d.getEvidenceForDisplay();
if (evidence != null && evidence.size() > 0) {
cnt += 1;
sink.sectionTitle4();
sink.rawText("Evidence Collected <a href=\"javascript:toggleElement(this, 'evidence" + cnt + "')\">[+]</a>");
@@ -625,7 +600,7 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR
writeTableHeaderCell(sink, "Name");
writeTableHeaderCell(sink, "Value");
sink.tableRow_();
for (Evidence e : d.getEvidenceUsed()) {
for (Evidence e : evidence) {
sink.tableRow();
writeTableCell(sink, e.getSource());
writeTableCell(sink, e.getName());
@@ -776,12 +751,12 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR
// </editor-fold>
/**
* Returns the maven settings proxy url.
* Returns the maven settings proxy server.
*
* @param proxy the maven proxy
* @return the proxy url
*/
private String getMavenSettingsProxyUrl(Proxy proxy) {
private String getMavenSettingsProxyServer(Proxy proxy) {
return new StringBuilder(proxy.getProtocol()).append("://").append(proxy.getHost()).toString();
}
@@ -835,9 +810,13 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
if (proxyUrl != null && !proxyUrl.isEmpty()) {
logger.warning("Deprecated configuration detected, proxyUrl will be ignored; use the maven settings to configure the proxy instead");
}
final Proxy proxy = getMavenProxy();
if (proxy != null) {
Settings.setString(Settings.KEYS.PROXY_URL, getMavenSettingsProxyUrl(proxy));
Settings.setString(Settings.KEYS.PROXY_SERVER, getMavenSettingsProxyServer(proxy));
Settings.setString(Settings.KEYS.PROXY_PORT, Integer.toString(proxy.getPort()));
final String userName = proxy.getUsername();
final String password = proxy.getPassword();
@@ -847,18 +826,6 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR
}
}
if (proxyUrl != null && !proxyUrl.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_URL, proxyUrl);
}
if (proxyPort != null && !proxyPort.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort);
}
if (proxyUsername != null && !proxyUsername.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_USERNAME, proxyUsername);
}
if (proxyPassword != null && !proxyPassword.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_PASSWORD, proxyPassword);
}
if (connectionTimeout != null && !connectionTimeout.isEmpty()) {
Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
}
@@ -952,7 +919,7 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR
"Unable to connect to the dependency-check database; analysis has stopped");
logger.log(Level.FINE, "", ex);
} finally {
Settings.cleanup();
Settings.cleanup(true);
if (engine != null) {
engine.cleanup();
}
@@ -993,7 +960,7 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR
"Unable to connect to the dependency-check database; analysis has stopped");
logger.log(Level.FINE, "", ex);
} finally {
Settings.cleanup();
Settings.cleanup(true);
if (engine != null) {
engine.cleanup();
}

View File

@@ -55,17 +55,6 @@ databaseUser | The username used when connecting to the database.
databasePassword | The password used when connecting to the database. | &nbsp;
Deprecated Configuration
Proxy Configuration
====================
The following properties have been deprecated. These can still be set in
the dependency-check-maven plugin's configuration. However, future versions
will remove these properties. Instead using these properties you should
use [Maven's settings](https://maven.apache.org/settings.html#Proxies) to
configure a proxy.
Property | Description | Default Value
---------------------|------------------------------------|------------------
proxyUrl | The Proxy URL. | &nbsp;
proxyPort | The Proxy Port. | &nbsp;
proxyUsername | Defines the proxy user name. | &nbsp;
proxyPassword | Defines the proxy password. | &nbsp;
Use [Maven's settings](https://maven.apache.org/settings.html#Proxies) to configure a proxy server.

View File

@@ -0,0 +1,280 @@
<!--
This file is part of dependency-check-utils.
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) 2014 - Jeremy Long. All Rights Reserved.
-->
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.2</version>
</parent>
<artifactId>dependency-check-utils</artifactId>
<name>Dependency-Check Utils</name>
<description>Dependency-check-utils a collection of common utlity classes used within dependency-check.</description>
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
<distributionManagement>
<site>
<id>github-pages-site</id>
<name>Deployment through GitHub's site deployment plugin</name>
<url>${basedir}/../target/site/${project.version}/dependency-check-ant</url>
</site>
</distributionManagement>
<!-- end copy -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.6</version>
<configuration>
<instrumentation>
<ignoreTrivial>true</ignoreTrivial>
</instrumentation>
<check>
<branchRate>85</branchRate>
<lineRate>85</lineRate>
<haltOnFailure>false</haltOnFailure>
<totalBranchRate>85</totalBranchRate>
<totalLineRate>85</totalLineRate>
<packageLineRate>85</packageLineRate>
<packageBranchRate>85</packageBranchRate>
<regexes>
<regex>
<pattern>.*\$.*</pattern>
<branchRate>0</branchRate>
<lineRate>0</lineRate>
</regex>
</regexes>
</check>
</configuration>
<executions>
<execution>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
<configuration>
<systemProperties>
<property>
<name>temp.directory</name>
<value>${project.build.directory}/temp</value>
</property>
</systemProperties>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.16</version>
<configuration>
<systemProperties>
<property>
<name>temp.directory</name>
<value>${project.build.directory}/temp</value>
</property>
</systemProperties>
<includes>
<include>**/*IntegrationTest.java</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<showDeprecation>false</showDeprecation>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.3</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.doxia</groupId>
<artifactId>doxia-module-markdown</artifactId>
<version>1.5</version>
</dependency>
</dependencies>
<configuration>
<skipDeploy>true</skipDeploy>
<reportPlugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>2.7</version>
<reportSets>
<reportSet>
<reports>
<report>index</report>
<report>summary</report>
<report>license</report>
<report>help</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<reportSets>
<reportSet>
<id>default</id>
<reports>
<report>javadoc</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.1</version>
<reportSets>
<reportSet>
<reports>
<report>dependency-updates-report</report>
<report>plugin-updates-report</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>
<version>2.4</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.6</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>2.16</version>
<reportSets>
<reportSet>
<reports>
<report>report-only</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>taglist-maven-plugin</artifactId>
<version>2.4</version>
<configuration>
<tagListOptions>
<tagClasses>
<tagClass>
<displayName>Todo Work</displayName>
<tags>
<tag>
<matchString>todo</matchString>
<matchType>ignoreCase</matchType>
</tag>
<tag>
<matchString>FIXME</matchString>
<matchType>exact</matchType>
</tag>
</tags>
</tagClass>
</tagClasses>
</tagListOptions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.11</version>
<configuration>
<enableRulesSummary>false</enableRulesSummary>
<configLocation>${basedir}/../src/main/config/checkstyle-checks.xml</configLocation>
<headerLocation>${basedir}/../src/main/config/checkstyle-header.txt</headerLocation>
<suppressionsLocation>${basedir}/../src/main/config/checkstyle-suppressions.xml</suppressionsLocation>
<suppressionsFileExpression>checkstyle.suppressions.file</suppressionsFileExpression>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.0.1</version>
<configuration>
<targetJdk>1.6</targetJdk>
<linkXref>true</linkXref>
<sourceEncoding>utf-8</sourceEncoding>
<rulesets>
<ruleset>../src/main/config/dcrules.xml</ruleset>
<ruleset>/rulesets/java/basic.xml</ruleset>
<ruleset>/rulesets/java/imports.xml</ruleset>
<ruleset>/rulesets/java/unusedcode.xml</ruleset>
</rulesets>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>2.5.3</version>
</plugin>
</reportPlugins>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -166,7 +166,7 @@ public final class Downloader {
try {
lastModifiedFile = new File(url.toURI());
} catch (URISyntaxException ex) {
final String msg = String.format("Unable to locate '%s'; is the cve.url-2.0.modified property set correctly?", url.toString());
final String msg = String.format("Unable to locate '%s'", url.toString());
throw new DownloadFailedException(msg);
}
timestamp = lastModifiedFile.lastModified();
@@ -176,7 +176,12 @@ public final class Downloader {
conn = URLConnectionFactory.createHttpURLConnection(url);
conn.setRequestMethod("HEAD");
conn.connect();
timestamp = conn.getLastModified();
final int t = conn.getResponseCode();
if (t >= 200 && t < 300) {
timestamp = conn.getLastModified();
} else {
throw new DownloadFailedException("HEAD request returned a non-200 status code");
}
} catch (URLConnectionFailureException ex) {
throw new DownloadFailedException("Error creating URL Connection for HTTP HEAD request.", ex);
} catch (IOException ex) {

View File

@@ -17,21 +17,13 @@
*/
package org.owasp.dependencycheck.utils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.owasp.dependencycheck.Engine;
/**
* A collection of utilities for processing information about files.
@@ -54,11 +46,6 @@ public final class FileUtils {
*/
private static final String BIT_BUCKET_WIN = "NUL";
/**
* The buffer size to use when extracting files from the archive.
*/
private static final int BUFFER_SIZE = 4096;
/**
* Private constructor for a utility class.
*/
@@ -155,99 +142,6 @@ public final class FileUtils {
return jarPath.getParentFile();
}
/**
* Extracts the contents of an archive into the specified directory.
*
* @param archive an archive file such as a WAR or EAR
* @param extractTo a directory to extract the contents to
* @throws ExtractionException thrown if an exception occurs while extracting the files
*/
public static void extractFiles(File archive, File extractTo) throws ExtractionException {
extractFiles(archive, extractTo, null);
}
/**
* Extracts the contents of an archive into the specified directory. The files are only extracted if they are
* supported by the analyzers loaded into the specified engine. If the engine is specified as null then all files
* are extracted.
*
* @param archive an archive file such as a WAR or EAR
* @param extractTo a directory to extract the contents to
* @param engine the scanning engine
* @throws ExtractionException thrown if there is an error extracting the files
*/
public static void extractFiles(File archive, File extractTo, Engine engine) throws ExtractionException {
if (archive == null || extractTo == null) {
return;
}
FileInputStream fis = null;
ZipInputStream zis = null;
try {
fis = new FileInputStream(archive);
} catch (FileNotFoundException ex) {
LOGGER.log(Level.FINE, null, ex);
throw new ExtractionException("Archive file was not found.", ex);
}
zis = new ZipInputStream(new BufferedInputStream(fis));
ZipEntry entry;
try {
while ((entry = zis.getNextEntry()) != null) {
if (entry.isDirectory()) {
final File d = new File(extractTo, entry.getName());
if (!d.exists() && !d.mkdirs()) {
final String msg = String.format("Unable to create '%s'.", d.getAbsolutePath());
throw new ExtractionException(msg);
}
} else {
final File file = new File(extractTo, entry.getName());
final String ext = getFileExtension(file.getName());
if (engine == null || engine.supportsExtension(ext)) {
BufferedOutputStream bos = null;
FileOutputStream fos;
try {
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos, BUFFER_SIZE);
int count;
final byte data[] = new byte[BUFFER_SIZE];
while ((count = zis.read(data, 0, BUFFER_SIZE)) != -1) {
bos.write(data, 0, count);
}
bos.flush();
} catch (FileNotFoundException ex) {
LOGGER.log(Level.FINE, null, ex);
final String msg = String.format("Unable to find file '%s'.", file.getName());
throw new ExtractionException(msg, ex);
} catch (IOException ex) {
LOGGER.log(Level.FINE, null, ex);
final String msg = String.format("IO Exception while parsing file '%s'.", file.getName());
throw new ExtractionException(msg, ex);
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException ex) {
LOGGER.log(Level.FINEST, null, ex);
}
}
}
}
}
}
} catch (IOException ex) {
final String msg = String.format("Exception reading archive '%s'.", archive.getName());
LOGGER.log(Level.FINE, msg, ex);
throw new ExtractionException(msg, ex);
} finally {
try {
zis.close();
} catch (IOException ex) {
LOGGER.log(Level.FINEST, null, ex);
}
}
}
/**
* Return the bit bucket for the OS. '/dev/null' for Unix and 'NUL' for Windows
*

View File

@@ -110,9 +110,16 @@ public final class Settings {
*/
public static final String CVE_SCHEMA_2_0 = "cve.url-2.0.base";
/**
* The properties key for the proxy url.
* The properties key for the proxy server.
*
* @deprecated use {@link org.owasp.dependencycheck.utils.Settings.KEYS#PROXY_SERVER} instead.
*/
public static final String PROXY_URL = "proxy.url";
@Deprecated
public static final String PROXY_URL = "proxy.server";
/**
* The properties key for the proxy server.
*/
public static final String PROXY_SERVER = "proxy.server";
/**
* The properties key for the proxy port - this must be an integer value.
*/
@@ -215,12 +222,14 @@ public final class Settings {
/**
* Private constructor for the Settings class. This class loads the properties files.
*
* @param propertiesFilePath the path to the base properties file to load
*/
private Settings() {
private Settings(String propertiesFilePath) {
InputStream in = null;
props = new Properties();
try {
in = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
in = this.getClass().getClassLoader().getResourceAsStream(propertiesFilePath);
props.load(in);
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Unable to load default settings.");
@@ -242,14 +251,34 @@ public final class Settings {
* However, you must also call Settings.cleanup() to properly release resources.
*/
public static void initialize() {
localSettings.set(new Settings());
localSettings.set(new Settings(PROPERTIES_FILE));
}
/**
* Initializes the thread local settings object. Note, to use the settings object you must call this method.
* However, you must also call Settings.cleanup() to properly release resources.
*
* @param propertiesFilePath the path to the base properties file to load
*/
public static void initialize(String propertiesFilePath) {
localSettings.set(new Settings(propertiesFilePath));
}
/**
* Cleans up resources to prevent memory leaks.
*
*/
public static void cleanup() {
if (tempDirectory != null && tempDirectory.exists()) {
cleanup(true);
}
/**
* Cleans up resources to prevent memory leaks.
*
* @param deleteTemporary flag indicating whether any temporary directories generated should be removed
*/
public static void cleanup(boolean deleteTemporary) {
if (deleteTemporary && tempDirectory != null && tempDirectory.exists()) {
FileUtils.delete(tempDirectory);
}
try {

View File

@@ -51,7 +51,7 @@ public final class URLConnectionFactory {
public static HttpURLConnection createHttpURLConnection(URL url) throws URLConnectionFailureException {
HttpURLConnection conn = null;
Proxy proxy = null;
final String proxyUrl = Settings.getString(Settings.KEYS.PROXY_URL);
final String proxyUrl = Settings.getString(Settings.KEYS.PROXY_SERVER);
try {
if (proxyUrl != null) {
final int proxyPort = Settings.getInt(Settings.KEYS.PROXY_PORT);

View File

@@ -0,0 +1,11 @@
/**
* <html>
* <head>
* <title>org.owasp.dependencycheck.utils</title>
* </head>
* <body>
* Includes various utility classes such as a Settings wrapper, utilities to make URL Connections, etc.
* </body>
* </html>
*/
package org.owasp.dependencycheck.utils;

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
This file is part of dependency-check-ant.
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) 2014 Jeremy Long. All Rights Reserved.
-->
<project name="dependency-check-ant">
<bannerLeft>
<name>dependency-check-utils</name>
</bannerLeft>
<body>
<breadcrumbs>
<item name="dependency-check" href="../index.html"/>
</breadcrumbs>
<menu ref="Project Documentation" />
<menu ref="reports" />
</body>
</project>

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2014 OWASP.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.owasp.dependencycheck.utils;
import org.junit.AfterClass;
import org.junit.BeforeClass;
/**
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class BaseTest {
@BeforeClass
public static void setUpClass() throws Exception {
Settings.initialize();
}
@AfterClass
public static void tearDownClass() throws Exception {
Settings.cleanup(true);
}
}

View File

@@ -21,7 +21,6 @@ import java.io.File;
import java.net.URL;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
/**
*
@@ -39,7 +38,7 @@ public class DownloaderIntegrationTest extends BaseTest {
// Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, "1000");
// Settings.setString(Settings.KEYS.PROXY_PORT, "8080");
// Settings.setString(Settings.KEYS.PROXY_URL, "127.0.0.1");
// Settings.setString(Settings.KEYS.PROXY_SERVER, "127.0.0.1");
URL url = new URL(Settings.getString(Settings.KEYS.CVE_MODIFIED_20_URL));
File outputPath = new File("target/downloaded_cve.xml");
Downloader.fetchFile(url, outputPath);

View File

@@ -19,12 +19,9 @@ package org.owasp.dependencycheck.utils;
import java.io.File;
import java.net.URL;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.utils.Downloader;
/**
*
@@ -32,25 +29,9 @@ import org.junit.Test;
*/
public class DownloaderTest {
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() throws Exception {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
@Test
public void testGetLastModified_file() throws Exception {
File f = new File("target/test-classes/nvdcve-2.0-2012.xml");
File f = new File("target/test-classes/dependencycheck.properties");
URL url = new URL("file:///" + f.getCanonicalPath());
long timestamp = Downloader.getLastModified(url);
assertTrue("timestamp equal to zero?", timestamp > 0);

View File

@@ -23,7 +23,6 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
/**
*

View File

@@ -22,7 +22,6 @@ import java.io.IOException;
import java.net.URISyntaxException;
import org.junit.Assert;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
/**
*

View File

@@ -0,0 +1,57 @@
application.name=${pom.name}
application.version=${pom.version}
autoupdate=true
max.download.threads=3
#temp.directory defaults to System.getProperty("java.io.tmpdir")
#temp.directory=[path to temp directory]
# the path to the data directory; the [JAR] signifies to use the relative path
# to the dependency-check-core JAR file. This path is only used to construct
# the connection string for the H2 driver (or other drivers that require a file path
# to be supplied. If you are using another database (MySQL, Oracle, etc.) this property
# will not be used. The data.directory will be resolved and if the connection string
# below contains a %s then the data.directory will replace the %s.
data.directory=[JAR]/data
data.connection_string=jdbc:h2:file:%s;FILE_LOCK=SERIALIZED;AUTOCOMMIT=ON;
#data.connection_string=jdbc:h2:file:%s;AUTO_SERVER=TRUE;AUTOCOMMIT=ON;
#data.connection_string=jdbc:mysql://localhost:3306/dependencycheck
# user name and password for the database connection. The inherent case is to use H2.
# As such, this unsecure username/password exist.
data.user=dcuser
data.password=DC-Pass1337!
# The following are only used if the DB Driver is not JDBC4 compliant and/or the driver
# is not in the current classpath. Setting these properties will add the give path(s) to
# the class loader and then register the driver with the DriverManager. If the class is
# not in the path you must specify both the driver name (aka the fully qualified driver name)
# and the driver path. The driver path can be a semi-colon separated list of files/directories
# to ensure any and all needed files can be added to the classpath to load the driver.
# For non-JDBC4 drivers in the classpath only the driver_name needs to be set.
# For MOST situations these properties likely do not need to be set.
data.driver_name=org.h2.Driver
data.driver_path=
# the path to the cpe xml file
cpe.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.2.xml.gz
# the path to the cpe meta data file.
cpe.meta.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.2.meta
# the number of days that the modified nvd cve data holds data for. We don't need
# to update the other files if we are within this timespan. Per NIST this file
# holds 8 days of updates, we are using 7 just to be safe.
cve.url.modified.validfordays=7
# the path to the modified nvd cve xml file.
cve.url-1.2.modified=http://nvd.nist.gov/download/nvdcve-modified.xml
cve.url-2.0.modified=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
cve.startyear=2014
cve.url-2.0.base=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
cve.url-1.2.base=http://nvd.nist.gov/download/nvdcve-%d.xml
# 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/
# If set to true, the proxy will still ONLY be used if the proxy properties (proxy.url, proxy.port)
# are configured
analyzer.nexus.proxy=true

View File

@@ -0,0 +1 @@
proxy.port=80

View File

@@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This file is part of Dependency-Check.
@@ -14,13 +15,12 @@ See the License for the specific language governing permissions and
limitations under the License.
Copyright (c) 2012 - Jeremy Long
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.0</version>
<version>1.2.2</version>
<packaging>pom</packaging>
<modules>
@@ -29,6 +29,7 @@ Copyright (c) 2012 - Jeremy Long
<module>dependency-check-ant</module>
<module>dependency-check-maven</module>
<module>dependency-check-jenkins</module>
<module>dependency-check-utils</module>
</modules>
<name>Dependency-Check</name>
<url>https://github.com/jeremylong/DependencyCheck.git</url>
@@ -244,4 +245,4 @@ Copyright (c) 2012 - Jeremy Long
<type>jar</type>
</dependency>
</dependencies>
</project>
</project>

View File

@@ -0,0 +1,16 @@
Archive Analyzer
==============
Dependency-check includes an analyzer an archive analyzer that will attempt
to extract files from the archive that are supported by the other file type
analyzers.
Files Types Scanned: ZIP, EAR, WAR, JAR, SAR, APK, NUPKG, TAR, GZ, TGZ
Additional file extensions for ZIP archives can be added, see the configuration
section in the Maven, Ant, or CLI interfaces for more information on configuration.
Note, since this analyzer does examine the contents of a JAR file there are times
that you may see additional entries in the report and/or warnings in the log file (if used)
for DLL or EXE files contained within the JAR file. In almost all cases these can
be ignored as it is fairly rare to have a .NET dll or exe within a JAR file.

View File

@@ -0,0 +1,10 @@
Assembly Analyzer
==============
Dependency-check includes an analyzer that scans .NET dll and exe files and collect as
much information it can about the files as it can. The information collected
is internally referred to 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.
Files Types Scanned: EXE, DLL

View File

@@ -0,0 +1,11 @@
Jar Analyzer
==============
Dependency-check includes an analyzer that scans JAR files and collect as
much information it can about the file as it can. The information collected
is internally referred to 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. Additionally, if a POM is present
the analyzer will add the Maven group, artifact, and version (GAV).
Files Types Scanned: JAR, WAR

View File

@@ -1,7 +1,7 @@
Nexus Analyzer
==============
Dependency Check includes an analyzer which will check for the Maven GAV
Dependency-check includes an analyzer that will check for the Maven GAV
(Group/Artifact/Version) information for artifacts in the scanned area. By
default the information comes from [Maven Central][1], but can be configured to
use a local repository if necessary. If the artifact's hash is found in the

View File

@@ -0,0 +1,13 @@
Nuspec Analyzer
==============
Dependency-check includes an analyzer that will scan NuGet's Nuspec file to
collect information about the component being used. The evidence collected
is used by other analyzers to determine if there are any known vulnerabilities
associated with the component.
Note, the Nuspec Analyzer does not scan dependencies defined. However, if
the dependencies have been downloaded and may be included in the scan depending
on configuration.
Files Types Scanned: NUSPEC

View File

@@ -64,6 +64,15 @@ HTML version of the report. The other common scenario would be to ignore all CVE
]]></notes>
<cvssBelow>7</cvssBelow>
</suppress>
<suppress>
<notes><![CDATA[
This suppresses false positives identified on spring security.
]]></notes>
<gav regex="true">org\.springframework\.security:spring.*</gav>
<cpe>cpe:/a:vmware:springsource_spring_framework</cpe>
<cpe>cpe:/a:springsource:spring_framework</cpe>
<cpe>cpe:/a:mod_security:mod_security</cpe>
</suppress>
</suppressions>
```

File diff suppressed because one or more lines are too long

View File

@@ -84,9 +84,23 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
<item name="Sample Report" href="./SampleReport.html">
<description>Sample Report</description>
</item>
</menu>
<menu name="File Type Analyzers">
<item name="Archive Analyzer" href="./archive-analyzer.html">
<description>Archive Analyzer</description>
</item>
<item name="Jar Analyzer" href="./jar-analyzer.html">
<description>Jar Analyzer</description>
</item>
<item name="Nexus Analyzer" href="./nexus-analyzer.html">
<description>Nexus Analyzer</description>
</item>
<item name="Assembly Analyzer" href="./assembly-analyzer.html">
<description>Assembly Analyzer</description>
</item>
<item name="Nuspec Analyzer" href="./nuspec-analyzer.html">
<description>Nuspec Analyzer</description>
</item>
</menu>
<menu name="Modules">
<item name="dependency-check-core" href="./dependency-check-core/index.html">