Compare commits

..

53 Commits

Author SHA1 Message Date
Jeremy Long
92bd305b00 version 1.2.5
Former-commit-id: b3fe4ea80c4286684eda15a3b9f46cebc4f09ee8
2014-09-16 19:47:17 -04:00
Jeremy Long
f71eb09f74 updated sample report
Former-commit-id: 1de33769f71be8c86116b4a17d8282c69e0abed6
2014-09-16 19:47:07 -04:00
Jeremy Long
83d4a7bc18 moved test case dependency,jersey client, to the allTests profile
Former-commit-id: 58da4d9c21803362133f74c168aea256c51a5824
2014-09-16 05:24:43 -04:00
Jeremy Long
29595324c4 added suppression rules for jersey-client
Former-commit-id: cb8f4081c6d0fc2128a3a3dfda294a541c16adec
2014-09-13 07:10:17 -04:00
Jeremy Long
f9064e526f added test jar to the extended profile test dependencies
Former-commit-id: b24966e3936afd9337dbea5476a696ddf46efc65
2014-09-13 07:09:54 -04:00
Jeremy Long
93ec2e8639 fixed javadoc
Former-commit-id: d06907a74a6fd4cf9ac5e5774af63eda5aba02b3
2014-09-13 05:50:49 -04:00
Jeremy Long
0e2a31709a added test cases to ensure setting the base flag will prevent the identifier from being added to the suppressedIdentifiers collection
Former-commit-id: d369797a3b14fc2c42621d273d6f314e968848b9
2014-09-13 05:45:05 -04:00
Jeremy Long
c785b39eda added assertion to validate that the base flag is being processed
Former-commit-id: 0364e57af8f548d010f17f948492e9472433c675
2014-09-13 05:44:09 -04:00
Jeremy Long
8fab2f58da added the base property and skipped adding the vulnerability or identifier to the suppressed collection if this is a base suppression rule
Former-commit-id: a668d7d8b9345b6ad44bfff1ced4ab783a1f90d8
2014-09-13 05:43:16 -04:00
Jeremy Long
e44ee3bfe1 added parsing of the base flag
Former-commit-id: 02f533177846bcd4a98b31f851e91f438e1ddeaa
2014-09-13 05:42:01 -04:00
Jeremy Long
62065c9d28 corrected the removal of an identifier so that iterator.remove was correctly used
Former-commit-id: 252507772242cc7ff42ef9f310cfca3bec7cb075
2014-09-13 05:41:26 -04:00
Jeremy Long
c76275275f added the base=true flag to all base suppressions
Former-commit-id: ac77f3fc4ff80c182b7736554a1960e186e67d69
2014-09-13 05:40:37 -04:00
Jeremy Long
257f78879d added base attribute to suppression rules
Former-commit-id: bcadbd75b99471a56d604c2f158570305e9b4010
2014-09-13 05:40:06 -04:00
Jeremy Long
894263809c added base flag to one suppression entry
Former-commit-id: 7d6bbf36e5e35c2ee2fe8c901281996a34706036
2014-09-13 05:39:38 -04:00
Jeremy Long
c503935d6a updated to correctly close the ObjectOutputStream based on guidance from the CERT Java Secure Coding Standard
Former-commit-id: 1c7b929055f273d49b1203c117d7bb12162cfdb2
2014-09-12 06:36:00 -04:00
Jeremy Long
d4756c9eb8 updated base suppression list to include sandbox:sandbox - a php app
Former-commit-id: 087a4c5af2afd03a1d4703d2e1e5a1607a2e7ac9
2014-09-12 06:34:23 -04:00
Jeremy Long
0004767775 added fix for issue #147 to address springsource, non-core spring, jars being idenified as cpe://a:springsource:springframwork
Former-commit-id: 0a3182123be78a3f450cdef0bcc395907d27730a
2014-09-10 17:55:04 -04:00
Jeremy Long
74908642c7 added test dependency
Former-commit-id: fa4846dfa384639114f32ed3b7a0d91347b8dabf
2014-09-10 17:39:31 -04:00
Jeremy Long
aadfb71c98 fixed test case by removing a temporary test entry in DetermineCPE_full
Former-commit-id: 0f91c7b8e1d536c9d15176dc2d9a439da4e8ccdc
2014-09-10 17:37:54 -04:00
Jeremy Long
1244af649d updated to improve CPE matching so that if a broad match occured (cpe with no version number) we use the highest confidence version when generating the CPE identifier
Former-commit-id: 6e8c87a71522b1ca7cfa9d72ca419a792d1b17e7
2014-09-09 15:10:08 -04:00
Jeremy Long
7bd48cc811 updated version analysis to reduce false positives and increase accurate detection
Former-commit-id: 6097160434b7e98182738706790d82cdbd867175
2014-09-09 15:07:28 -04:00
Jeremy Long
8f3ce38418 re-ordered operations so that a new lucene index is no longer created on each call to calDetermineCPE_full
Former-commit-id: e2af1d893b47afe1ed36d1ab1e6840d47757b509
2014-09-07 08:28:44 -04:00
Jeremy Long
1b2d9b4245 fixed minor display bug
Former-commit-id: 65e1adcdc7677490907ee6eca68bf1174d355a3c
2014-09-07 07:20:45 -04:00
Jeremy Long
c6b2b34fde removed duplicative test of downloading XML
Former-commit-id: 97d1371609af2cc9583b0ac071a8606c93a34fbe
2014-09-07 06:59:50 -04:00
Jeremy Long
e58fc13fdb additional looping corrections in determineCPE() to break early if an identifier is found
Former-commit-id: 4ec4ffe598d9870a793da8980bb863633c1967d7
2014-09-06 19:09:38 -04:00
Jeremy Long
922d53d2e4 Increased the confidence on the pom artifact and groupid
Former-commit-id: b052b50353197e0f7cb419e6f618f2320da11183
2014-09-06 19:08:22 -04:00
Jeremy Long
fec53b3951 corrected looping in determineCPE()
Former-commit-id: 329f20687223f38273b2e23601b05fcea2b9122f
2014-09-06 06:37:12 -04:00
Jeremy Long
e72e2c6a02 corrected documention error with the reporting sets
Former-commit-id: ab503e5a710a69624a3216edea880e614b003ba8
2014-09-01 08:19:46 -04:00
Jeremy Long
08d001ee05 checkstyle corrections
Former-commit-id: ecc262c75890ef4c8760cb41e7948cb6decdf5d5
2014-09-01 08:13:53 -04:00
Jeremy Long
99d8a07f4a updated documentation as part of resolution for issue #144
Former-commit-id: f47171e52e22e75c582bed47c9d0e9df3945e148
2014-09-01 08:13:34 -04:00
Jeremy Long
eef565134b update to correct issue #79 - the internal report format is no longer supported
Former-commit-id: 4dc9a83008a75d97f3838aa1a41f1d93eb39f2de
2014-09-01 07:39:54 -04:00
Jeremy Long
9d78293437 fix for issue #128 - the application will no longer throw an exception on large files when generating the hash digest
Former-commit-id: aae811e5d10ca0ee5ac7316fa992b5c45e43d2be
2014-09-01 07:30:04 -04:00
Jeremy Long
fc0a556e5f checkstyle and findbugs corrections
Former-commit-id: 2bf90876b7c88bccb93135a0be43f01e49c3cd30
2014-08-30 15:51:24 -04:00
Jeremy Long
b6b070584f checkstyle corrections, added javadoc, etc.
Former-commit-id: 2b806cb8527a627d400644465bcf9f04d687d729
2014-08-30 15:19:52 -04:00
Jeremy Long
e13225eee6 initial version of aggreation completed for issue #19 - some cleanup still needs to happen before final release
Former-commit-id: 98c9af3004e2c725d0dca5d6847b65a4646c6a73
2014-08-30 07:50:27 -04:00
Jeremy Long
da20fb2922 added velocity-tools to base suppression as it should not be reported as struts
Former-commit-id: 4649d95a091def05ae249da42aa7d6f845b14d59
2014-08-30 07:48:02 -04:00
Jeremy Long
459c2beb12 noop
Former-commit-id: a51d953d0c60c39d845d69d66c87db8b904382c4
2014-08-29 05:41:31 -04:00
Jeremy Long
f1cc44dead removed the externalReport option
Former-commit-id: 4cc3ec2638140f8320eb8946d2154dae330786b0
2014-08-29 05:38:40 -04:00
Jeremy Long
d24cfdc382 resolved merge conflict
Former-commit-id: 4806c0c99bd35d64135ee22a12018e6a92c54059
2014-08-16 07:41:55 -04:00
Jeremy Long
ae4cc543f6 corrected outputFile name to correctly use the target directory from project.getBuild().getDirectory()
Former-commit-id: 7ef2ca45e502e945e7356f9c63845eb4e7b532fc
2014-08-16 07:30:34 -04:00
Jeremy Long
abdb3d17f9 added initial plumbing to support report aggregation per issue #19 - report aggregation is still not complete
Former-commit-id: df248d0c1a7f3628653717029f034a46afde742b
2014-08-16 07:29:35 -04:00
Jeremy Long
4095c5da38 made serializable
Former-commit-id: 27d8084ea981766791df05c5e9ef61dbe40ba32c
2014-08-16 07:27:28 -04:00
Jeremy Long
78fab728e4 added an additional generate method
Former-commit-id: 44b78b525da45918f3b4bc77b368f88e49361c95
2014-08-15 06:22:54 -04:00
Jeremy Long
52097a6867 initial version of the ReportAggregationMojo
Former-commit-id: e15575413d625c6b5c5f3d73f5a739e1890eec27
2014-08-15 06:02:04 -04:00
Jeremy Long
cb990b55b5 added the apache 2.0 license to the header
Former-commit-id: f7d5558f565abe9c3e1a04f79666137e4f67e017
2014-08-15 06:00:30 -04:00
Jeremy Long
5070fe303a added the configuration value mavenSettingsProxyId to inform users that if you have multiple proxies defined in settings.xml you can choose which one should be used
Former-commit-id: 20fa4a92d446fd30a882e07c37897907fb1638b1
2014-08-15 05:59:39 -04:00
Jeremy Long
b4405ebf3e minor changes to the TOC table - removed # of related dependencies and renamed CVE Impact to Highest Severity to clear up ambiguity
Former-commit-id: b8b14ab120d889057864eb6f93cadad9773b9171
2014-08-15 05:58:10 -04:00
Jeremy Long
d9e6bf5068 Merge pull request #145 from erik-wramner/fix-maven-proxy-bug
Modified Maven plugin to use proxy host as is, not as an URL. This works...

Former-commit-id: 53e28e6799ef13ca3d88ed00aaa1e0c3f24aa04b
2014-08-15 05:37:14 -04:00
erik-wramner
6822188f52 Modified Maven plugin to use proxy host as is, not as an URL. This works correctly for our proxy server with Maven 3.
Former-commit-id: 02e97e359b1c5d6d9f1dc9149c9fbed510d31559
2014-08-10 12:15:00 +02:00
Jeremy Long
15858d03ff moved reporting functions from the core maven plugin to a utility class
Former-commit-id: d63d2a7a5031038b9f86bbe94fc4a198374bd9f3
2014-08-08 14:44:26 -04:00
Jeremy Long
814a733258 moved reporting functions from the core maven plugin to a utility class
Former-commit-id: 0d8507b8534320189ea5f36d0fc1cac7d0843c0f
2014-08-08 14:43:00 -04:00
Jeremy Long
3ce85d8ca9 rework of report generation and added fix for proxy (patch for proxy was from Erik Wramner) to close issue #136
Former-commit-id: afc81123b31189618ade397b830bf421db2918f8
2014-08-08 14:42:23 -04:00
Jeremy Long
d3bff2f39d version 1.2.5-SNAPSHOT
Former-commit-id: 85ed1238022348f1e9496ffe3c95d4ff8e3d09c3
2014-08-05 18:55:30 -04:00
34 changed files with 2384 additions and 2630 deletions

View File

@@ -15,13 +15,12 @@ limitations under the License.
Copyright (c) 2013 - Jeremy Long. All Rights Reserved. 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/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> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.owasp</groupId> <groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId> <artifactId>dependency-check-parent</artifactId>
<version>1.2.4</version> <version>1.2.5</version>
</parent> </parent>
<artifactId>dependency-check-ant</artifactId> <artifactId>dependency-check-ant</artifactId>

View File

@@ -15,13 +15,12 @@ limitations under the License.
Copyright (c) 2012 - Jeremy Long. All Rights Reserved. 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"> <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> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.owasp</groupId> <groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId> <artifactId>dependency-check-parent</artifactId>
<version>1.2.4</version> <version>1.2.5</version>
</parent> </parent>
<artifactId>dependency-check-cli</artifactId> <artifactId>dependency-check-cli</artifactId>

View File

@@ -20,7 +20,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<parent> <parent>
<groupId>org.owasp</groupId> <groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId> <artifactId>dependency-check-parent</artifactId>
<version>1.2.4</version> <version>1.2.5</version>
</parent> </parent>
<artifactId>dependency-check-core</artifactId> <artifactId>dependency-check-core</artifactId>
@@ -621,6 +621,13 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<scope>provided</scope> <scope>provided</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.1.0.RELEASE</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
</dependencies> </dependencies>
<profiles> <profiles>
<profile> <profile>
@@ -737,6 +744,13 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<scope>provided</scope> <scope>provided</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.12</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
</dependencies> </dependencies>
</profile> </profile>
</profiles> </profiles>

View File

@@ -18,6 +18,7 @@
package org.owasp.dependencycheck; package org.owasp.dependencycheck;
import java.io.File; import java.io.File;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.HashSet; import java.util.HashSet;
@@ -52,7 +53,7 @@ import org.owasp.dependencycheck.utils.Settings;
* *
* @author Jeremy Long <jeremy.long@owasp.org> * @author Jeremy Long <jeremy.long@owasp.org>
*/ */
public class Engine { public class Engine implements Serializable {
/** /**
* The list of dependencies. * The list of dependencies.
@@ -61,19 +62,19 @@ public class Engine {
/** /**
* A Map of analyzers grouped by Analysis phase. * A Map of analyzers grouped by Analysis phase.
*/ */
private final EnumMap<AnalysisPhase, List<Analyzer>> analyzers; private transient final EnumMap<AnalysisPhase, List<Analyzer>> analyzers;
/** /**
* A Map of analyzers grouped by Analysis phase. * A Map of analyzers grouped by Analysis phase.
*/ */
private final Set<FileTypeAnalyzer> fileTypeAnalyzers; private transient final Set<FileTypeAnalyzer> fileTypeAnalyzers;
/** /**
* The ClassLoader to use when dynamically loading Analyzer and Update services. * The ClassLoader to use when dynamically loading Analyzer and Update services.
*/ */
private ClassLoader serviceClassLoader; private transient ClassLoader serviceClassLoader;
/** /**
* The Logger for use throughout the class. * The Logger for use throughout the class.
*/ */
private static final Logger LOGGER = Logger.getLogger(Engine.class.getName()); private transient static final Logger LOGGER = Logger.getLogger(Engine.class.getName());
/** /**
* Creates a new Engine. * Creates a new Engine.

View File

@@ -170,29 +170,10 @@ public class CPEAnalyzer implements Analyzer {
* @throws ParseException is thrown when the Lucene query cannot be parsed. * @throws ParseException is thrown when the Lucene query cannot be parsed.
*/ */
protected void determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException { protected void determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException {
Confidence confidence = Confidence.HIGHEST; //TODO test dojo-war against this. we shold get dojo-toolkit:dojo-toolkit AND dojo-toolkit:toolkit
String vendors = "";
String vendors = addEvidenceWithoutDuplicateTerms("", dependency.getVendorEvidence(), confidence); String products = "";
String products = addEvidenceWithoutDuplicateTerms("", dependency.getProductEvidence(), confidence); for (Confidence confidence : Confidence.values()) {
/* bug fix for #40 - version evidence is not showing up as "used" in the reports if there is no
* CPE identified. As such, we are "using" the evidence and ignoring the results. */
addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), confidence);
int ctr = 0;
do {
if (!vendors.isEmpty() && !products.isEmpty()) {
final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getProductEvidence().getWeighting(),
dependency.getVendorEvidence().getWeighting());
for (IndexEntry e : entries) {
if (verifyEntry(e, dependency)) {
final String vendor = e.getVendor();
final String product = e.getProduct();
determineIdentifiers(dependency, vendor, product);
}
}
}
confidence = reduceConfidence(confidence);
if (dependency.getVendorEvidence().contains(confidence)) { if (dependency.getVendorEvidence().contains(confidence)) {
vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), confidence); vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), confidence);
} }
@@ -201,10 +182,26 @@ public class CPEAnalyzer implements Analyzer {
} }
/* bug fix for #40 - version evidence is not showing up as "used" in the reports if there is no /* bug fix for #40 - version evidence is not showing up as "used" in the reports if there is no
* CPE identified. As such, we are "using" the evidence and ignoring the results. */ * CPE identified. As such, we are "using" the evidence and ignoring the results. */
if (dependency.getVersionEvidence().contains(confidence)) { // if (dependency.getVersionEvidence().contains(confidence)) {
addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), confidence); // addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), confidence);
// }
if (!vendors.isEmpty() && !products.isEmpty()) {
final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getProductEvidence().getWeighting(),
dependency.getVendorEvidence().getWeighting());
boolean identifierAdded = false;
for (IndexEntry e : entries) {
if (verifyEntry(e, dependency)) {
final String vendor = e.getVendor();
final String product = e.getProduct();
identifierAdded |= determineIdentifiers(dependency, vendor, product, confidence);
}
}
if (identifierAdded) {
break;
}
} }
} while ((++ctr) < 4); }
} }
/** /**
@@ -239,22 +236,6 @@ public class CPEAnalyzer implements Analyzer {
return sb.toString().trim(); return sb.toString().trim();
} }
/**
* Reduces the given confidence by one level. This returns LOW if the confidence passed in is not HIGH.
*
* @param c the confidence to reduce.
* @return One less then the confidence passed in.
*/
private Confidence reduceConfidence(final Confidence c) {
if (c == Confidence.HIGHEST) {
return Confidence.HIGH;
} else if (c == Confidence.HIGH) {
return Confidence.MEDIUM;
} else {
return Confidence.LOW;
}
}
/** /**
* <p> * <p>
* Searches the Lucene CPE index to identify possible CPE entries associated with the supplied vendor, product, and * Searches the Lucene CPE index to identify possible CPE entries associated with the supplied vendor, product, and
@@ -508,14 +489,19 @@ public class CPEAnalyzer implements Analyzer {
* @param dependency the Dependency being analyzed * @param dependency the Dependency being analyzed
* @param vendor the vendor for the CPE being analyzed * @param vendor the vendor for the CPE being analyzed
* @param product the product for the CPE being analyzed * @param product the product for the CPE being analyzed
* @return <code>true</code> if an identifier was added to the dependency; otherwise <code>false</code>
* @throws UnsupportedEncodingException is thrown if UTF-8 is not supported * @throws UnsupportedEncodingException is thrown if UTF-8 is not supported
*/ */
private void determineIdentifiers(Dependency dependency, String vendor, String product) throws UnsupportedEncodingException { private boolean determineIdentifiers(Dependency dependency, String vendor, String product, Confidence currentConfidence) throws UnsupportedEncodingException {
final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product); final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product);
DependencyVersion bestGuess = new DependencyVersion("-"); DependencyVersion bestGuess = new DependencyVersion("-");
Confidence bestGuessConf = null; Confidence bestGuessConf = null;
boolean hasBroadMatch = false;
final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>(); final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>();
for (Confidence conf : Confidence.values()) { for (Confidence conf : Confidence.values()) {
// if (conf.compareTo(currentConfidence) > 0) {
// break;
// }
for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) { for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) {
final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue()); final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue());
if (evVer == null) { if (evVer == null) {
@@ -528,9 +514,12 @@ public class CPEAnalyzer implements Analyzer {
} else { } else {
dbVer = DependencyVersionUtil.parseVersion(vs.getVersion()); dbVer = DependencyVersionUtil.parseVersion(vs.getVersion());
} }
if (dbVer == null //special case, no version specified - everything is vulnerable if (dbVer == null) { //special case, no version specified - everything is vulnerable
|| evVer.equals(dbVer)) { //yeah! exact match hasBroadMatch = true;
final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8"));
final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.BROAD_MATCH, conf);
collected.add(match);
} else if (evVer.equals(dbVer)) { //yeah! exact match
final String url = String.format(NVD_SEARCH_URL, 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); final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf);
collected.add(match); collected.add(match);
@@ -556,7 +545,11 @@ public class CPEAnalyzer implements Analyzer {
} }
} }
final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString()); final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString());
final String url = null; String url = null;
if (hasBroadMatch) { //if we have a broad match we can add the URL to the best guess.
final String cpeUrlName = String.format("cpe:/a:%s:%s", vendor, product);
url = String.format(NVD_SEARCH_URL, URLEncoder.encode(cpeUrlName, "UTF-8"));
}
if (bestGuessConf == null) { if (bestGuessConf == null) {
bestGuessConf = Confidence.LOW; bestGuessConf = Confidence.LOW;
} }
@@ -566,6 +559,7 @@ public class CPEAnalyzer implements Analyzer {
Collections.sort(collected); Collections.sort(collected);
final IdentifierConfidence bestIdentifierQuality = collected.get(0).getConfidence(); final IdentifierConfidence bestIdentifierQuality = collected.get(0).getConfidence();
final Confidence bestEvidenceQuality = collected.get(0).getEvidenceConfidence(); final Confidence bestEvidenceQuality = collected.get(0).getEvidenceConfidence();
boolean identifierAdded = false;
for (IdentifierMatch m : collected) { for (IdentifierMatch m : collected) {
if (bestIdentifierQuality.equals(m.getConfidence()) if (bestIdentifierQuality.equals(m.getConfidence())
&& bestEvidenceQuality.equals(m.getEvidenceConfidence())) { && bestEvidenceQuality.equals(m.getEvidenceConfidence())) {
@@ -576,8 +570,10 @@ public class CPEAnalyzer implements Analyzer {
i.setConfidence(bestEvidenceQuality); i.setConfidence(bestEvidenceQuality);
} }
dependency.addIdentifier(i); dependency.addIdentifier(i);
identifierAdded = true;
} }
} }
return identifierAdded;
} }
/** /**
@@ -592,7 +588,12 @@ public class CPEAnalyzer implements Analyzer {
/** /**
* A best guess for the CPE. * A best guess for the CPE.
*/ */
BEST_GUESS BEST_GUESS,
/**
* The entire vendor/product group must be added (without a guess at version) because there is a CVE with a VS
* that only specifies vendor/product.
*/
BROAD_MATCH
} }
/** /**

View File

@@ -86,12 +86,42 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
public void analyze(Dependency dependency, Engine engine) throws AnalysisException { public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
removeJreEntries(dependency); removeJreEntries(dependency);
removeBadMatches(dependency); removeBadMatches(dependency);
removeBadSpringMatches(dependency);
removeWrongVersionMatches(dependency); removeWrongVersionMatches(dependency);
removeSpuriousCPE(dependency); removeSpuriousCPE(dependency);
removeDuplicativeEntriesFromJar(dependency, engine); removeDuplicativeEntriesFromJar(dependency, engine);
addFalseNegativeCPEs(dependency); addFalseNegativeCPEs(dependency);
} }
private void removeBadSpringMatches(Dependency dependency) {
String mustContain = null;
for (Identifier i : dependency.getIdentifiers()) {
if ("maven".contains(i.getType())) {
if (i.getValue() != null && i.getValue().startsWith("org.springframework.")) {
int endPoint = i.getValue().indexOf(":", 19);
if (endPoint >= 0) {
mustContain = i.getValue().substring(19, endPoint).toLowerCase();
break;
}
}
}
}
if (mustContain != null) {
Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
while (itr.hasNext()) {
Identifier i = itr.next();
if ("cpe".contains(i.getType())
&& i.getValue() != null
&& i.getValue().startsWith("cpe:/a:springsource:")
&& !i.getValue().toLowerCase().contains(mustContain)) {
itr.remove();
//dependency.getIdentifiers().remove(i);
}
}
}
}
/** /**
* <p> * <p>
* Intended to remove spurious CPE entries. By spurious we mean duplicate, less specific CPE entries.</p> * Intended to remove spurious CPE entries. By spurious we mean duplicate, less specific CPE entries.</p>

View File

@@ -587,7 +587,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
groupid = groupid.substring(4); groupid = groupid.substring(4);
} }
foundSomething = true; foundSomething = true;
dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGH); dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGHEST);
dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW); dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW);
addMatchingValues(classes, groupid, dependency.getVendorEvidence()); addMatchingValues(classes, groupid, dependency.getVendorEvidence());
addMatchingValues(classes, groupid, dependency.getProductEvidence()); addMatchingValues(classes, groupid, dependency.getProductEvidence());
@@ -616,7 +616,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
artifactid = artifactid.substring(4); artifactid = artifactid.substring(4);
} }
foundSomething = true; foundSomething = true;
dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGH); dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGHEST);
dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW); dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW);
addMatchingValues(classes, artifactid, dependency.getVendorEvidence()); addMatchingValues(classes, artifactid, dependency.getVendorEvidence());
addMatchingValues(classes, artifactid, dependency.getProductEvidence()); addMatchingValues(classes, artifactid, dependency.getProductEvidence());

View File

@@ -19,6 +19,7 @@ package org.owasp.dependencycheck.dependency;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Set; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
@@ -35,7 +36,7 @@ import org.owasp.dependencycheck.utils.FileUtils;
* *
* @author Jeremy Long <jeremy.long@owasp.org> * @author Jeremy Long <jeremy.long@owasp.org>
*/ */
public class Dependency implements Comparable<Dependency> { public class Dependency implements Serializable, Comparable<Dependency> {
/** /**
* The logger. * The logger.

View File

@@ -17,12 +17,14 @@
*/ */
package org.owasp.dependencycheck.dependency; package org.owasp.dependencycheck.dependency;
import java.io.Serializable;
/** /**
* Evidence is a piece of information about a Dependency. * Evidence is a piece of information about a Dependency.
* *
* @author Jeremy Long <jeremy.long@owasp.org> * @author Jeremy Long <jeremy.long@owasp.org>
*/ */
public class Evidence implements Comparable<Evidence> { public class Evidence implements Serializable, Comparable<Evidence> {
/** /**
* Creates a new Evidence object. * Creates a new Evidence object.

View File

@@ -17,6 +17,7 @@
*/ */
package org.owasp.dependencycheck.dependency; package org.owasp.dependencycheck.dependency;
import java.io.Serializable;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
@@ -36,7 +37,7 @@ import org.owasp.dependencycheck.utils.UrlStringUtils;
* *
* @author Jeremy Long <jeremy.long@owasp.org> * @author Jeremy Long <jeremy.long@owasp.org>
*/ */
public class EvidenceCollection implements Iterable<Evidence> { public class EvidenceCollection implements Serializable, Iterable<Evidence> {
/** /**
* The logger. * The logger.

View File

@@ -17,11 +17,13 @@
*/ */
package org.owasp.dependencycheck.dependency; package org.owasp.dependencycheck.dependency;
import java.io.Serializable;
/** /**
* *
* @author Jeremy Long <jeremy.long@owasp.org> * @author Jeremy Long <jeremy.long@owasp.org>
*/ */
public class Identifier implements Comparable<Identifier> { public class Identifier implements Serializable, Comparable<Identifier> {
/** /**
* Constructs a new Identifier with the specified data. * Constructs a new Identifier with the specified data.

View File

@@ -103,6 +103,12 @@ public class SuppressionHandler extends DefaultHandler {
currentText = new StringBuffer(); currentText = new StringBuffer();
if (SUPPRESS.equals(qName)) { if (SUPPRESS.equals(qName)) {
rule = new SuppressionRule(); rule = new SuppressionRule();
final String base = currentAttributes.getValue("base");
if (base != null) {
rule.setBase(Boolean.parseBoolean(base));
} else {
rule.setBase(false);
}
} }
} }

View File

@@ -266,6 +266,26 @@ public class SuppressionRule {
return gav != null; return gav != null;
} }
private boolean base;
/**
* Get the value of base
*
* @return the value of base
*/
public boolean isBase() {
return base;
}
/**
* Set the value of base
*
* @param base new value of base
*/
public void setBase(boolean base) {
this.base = base;
}
/** /**
* Processes a given dependency to determine if any CPE, CVE, CWE, or CVSS scores should be suppressed. If any * Processes a given dependency to determine if any CPE, CVE, CWE, or CVSS scores should be suppressed. If any
* should be, they are removed from the dependency. * should be, they are removed from the dependency.
@@ -300,7 +320,9 @@ public class SuppressionRule {
final Identifier i = itr.next(); final Identifier i = itr.next();
for (PropertyType c : this.cpe) { for (PropertyType c : this.cpe) {
if (identifierMatches("cpe", c, i)) { if (identifierMatches("cpe", c, i)) {
dependency.addSuppressedIdentifier(i); if (!isBase()) {
dependency.addSuppressedIdentifier(i);
}
itr.remove(); itr.remove();
break; break;
} }
@@ -339,7 +361,9 @@ public class SuppressionRule {
} }
} }
if (remove) { if (remove) {
dependency.addSuppressedVulnerability(v); if (!isBase()) {
dependency.addSuppressedVulnerability(v);
}
itr.remove(); itr.remove();
} }
} }

View File

@@ -189,17 +189,23 @@ public class DependencyVersion implements Iterable, Comparable<DependencyVersion
if (version == null) { if (version == null) {
return false; return false;
} }
if (Math.abs(this.versionParts.size() - version.versionParts.size()) >= 3) {
boolean ret = true; return false;
int max = (this.versionParts.size() < version.versionParts.size())
? this.versionParts.size() : version.versionParts.size();
if (max > 3) {
max = 3;
} }
final int max = (this.versionParts.size() < version.versionParts.size())
? this.versionParts.size() : version.versionParts.size();
boolean ret = true;
for (int i = 0; i < max; i++) { for (int i = 0; i < max; i++) {
if (this.versionParts.get(i) == null || !this.versionParts.get(i).equals(version.versionParts.get(i))) { String thisVersion = this.versionParts.get(i);
String otherVersion = version.getVersionParts().get(i);
if (i >= 3) {
if (thisVersion.compareToIgnoreCase(otherVersion) >= 0) {
ret = false;
break;
}
} else if (!thisVersion.equals(otherVersion)) {
ret = false; ret = false;
break; break;
} }

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://www.owasp.org/index.php/OWASP_Dependency_Check_Suppression"> <suppressions xmlns="https://www.owasp.org/index.php/OWASP_Dependency_Check_Suppression">
<suppress> <suppress base="true">
<notes><![CDATA[ <notes><![CDATA[
This suppresses false positives identified on spring security. This suppresses false positives identified on spring security.
]]></notes> ]]></notes>
@@ -9,7 +9,7 @@
<cpe>cpe:/a:springsource:spring_framework</cpe> <cpe>cpe:/a:springsource:spring_framework</cpe>
<cpe>cpe:/a:vmware:springsource_spring_framework</cpe> <cpe>cpe:/a:vmware:springsource_spring_framework</cpe>
</suppress> </suppress>
<suppress> <suppress base="true">
<notes><![CDATA[ <notes><![CDATA[
This suppreses additional false positives for the xstream library that occur because spring has a copy of this library. This suppreses additional false positives for the xstream library that occur because spring has a copy of this library.
com.springsource.com.thoughtworks.xstream-1.3.1.jar com.springsource.com.thoughtworks.xstream-1.3.1.jar
@@ -17,4 +17,25 @@
<gav regex="true">com\.thoughtworks\.xstream:xstream:.*</gav> <gav regex="true">com\.thoughtworks\.xstream:xstream:.*</gav>
<cpe>cpe:/a:springsource:spring_framework</cpe> <cpe>cpe:/a:springsource:spring_framework</cpe>
</suppress> </suppress>
<suppress base="true">
<notes><![CDATA[
Suppresses false positives on velocity tools.
]]></notes>
<gav regex="true">org\.apache\.velocity:velocity-tools:.*</gav>
<cpe>cpe:/a:apache:struts</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
Sandbox is a php blog platform and should not be flagged as a CPE for java or .net dependencies.
]]></notes>
<filePath regex="true">.*\.(jar|dll|exe|ear|war|pom)</filePath>
<cpe>cpe:/a:sandbox:sandbox</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
Suppresses false positives on Jersey core client.
]]></notes>
<gav regex="true">org\.glassfish\.jersey\.core:jersey-(client|common):.*</gav>
<cpe>cpe:/a:oracle:glassfish</cpe>
</suppress>
</suppressions> </suppressions>

View File

@@ -50,6 +50,7 @@
<xs:element name="cvssBelow" type="dc:cvssScoreType"/> <xs:element name="cvssBelow" type="dc:cvssScoreType"/>
</xs:choice> </xs:choice>
</xs:sequence> </xs:sequence>
<xs:attribute name="base" use="optional" type="xs:boolean" default="false"/>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>

View File

@@ -33,8 +33,8 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</script> </script>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function() { $(document).ready(function() {
$(".expandable").click(function (e) { $(".expandable").click(function (event) {
e = e || window.event; e = event || window.event;
var h = e.target || e.srcElement; var h = e.target || e.srcElement;
var content = "#content" + h.id.substr(6); var content = "#content" + h.id.substr(6);
var header = "#" + h.id; var header = "#" + h.id;
@@ -56,6 +56,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
$(header).addClass("expandablesubsection"); $(header).addClass("expandablesubsection");
$(header).removeClass("collaspablesubsection"); $(header).removeClass("collaspablesubsection");
} }
return false;
}); });
}); });
@@ -533,24 +534,22 @@ arising out of or in connection with the use of this tool, the analysis performe
<li class="scaninfo hidden"><i>$enc.html($prop.key)</i>: $enc.html($prop.value)</li> <li class="scaninfo hidden"><i>$enc.html($prop.key)</i>: $enc.html($prop.value)</li>
#end #end
</ul><br/> </ul><br/>
Display:&nbsp;<a href="#" title="Click to toggle display" onclick="return toggleDisplay(this,'.notvulnerable', 'Showing Vulnerable Dependencies', 'Showing All Dependencies'); return false;">Showing Vulnerable Dependencies</a><br/><br/> Display:&nbsp;<a href="#" title="Click to toggle display" onclick="return toggleDisplay(this, '.notvulnerable', 'Showing Vulnerable Dependencies', 'Showing All Dependencies'); return false;">Showing Vulnerable Dependencies</a><br/><br/>
#set($lnkcnt=0) #set($lnkcnt=0)
<table class="lined"> <table class="lined">
<tr style="text-align:left"> <tr style="text-align:left">
<th title="The name of the dependency">Dependency</th> <th title="The name of the dependency">Dependency</th>
<th title="The number of related dependencies">#&nbsp;Related</th>
<th title="The Common Platform Enumeration">CPE</th> <th title="The Common Platform Enumeration">CPE</th>
<th title="The Maven GAV Coordinates">GAV</th> <th title="The Maven GAV Coordinates">GAV</th>
<th title="The highest CVE Impact">CVE&nbsp;Impact</th> <th title="The highest CVE Severity">Highest Severity</th>
<th title="The number of Common Vulnerability and Exposure (CVE) entries">CVE&nbsp;Count</th> <th title="The number of Common Vulnerability and Exposure (CVE) entries">CVE Count</th>
<th title="The confidence rating dependency-check has for the identified CPE">CPE&nbsp;Confidence</th> <th title="The confidence rating dependency-check has for the identified CPE">CPE Confidence</th>
<th title="The count of evidence used to identify the CPE">Evidence&nbsp;Count</th> <th title="The count of evidence used to identify the CPE">Evidence Count</th>
</tr> </tr>
#foreach($dependency in $dependencies) #foreach($dependency in $dependencies)
#set($lnkcnt=$lnkcnt+1) #set($lnkcnt=$lnkcnt+1)
<tr class="#if($dependency.getVulnerabilities().size()==0)notvulnerable#else vulnerable#end"> <tr class="#if($dependency.getVulnerabilities().size()==0)notvulnerable#else vulnerable#end">
<td><a href="#l${lnkcnt}_$enc.html($enc.url($dependency.Sha1sum))">$enc.html($dependency.DisplayFileName)</a></td> <td><a href="#l${lnkcnt}_$enc.html($enc.url($dependency.Sha1sum))">$enc.html($dependency.DisplayFileName)</a></td>
<td>$dependency.getRelatedDependencies().size()</td>
#set($mavenlink="") #set($mavenlink="")
#set($cpeIdCount=0) #set($cpeIdCount=0)
#set($cpeIdConf="") #set($cpeIdConf="")
@@ -754,7 +753,7 @@ arising out of or in connection with the use of this tool, the analysis performe
<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"><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> </ul></p>
#else #else
<p>Vulnerable Software &amp; Versions:&nbsp;(<a href="#" onclick="toggleDisplay(this,'.vs$vsctr'); return false;">show all</a>)<ul> <p>Vulnerable Software &amp; Versions:&nbsp;(<a href="#" onclick="return toggleDisplay(this,'.vs$vsctr', 'show all', 'show less');">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"><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> <li class="vs$vsctr">...</li>
#foreach($vs in $vuln.getVulnerableSoftware()) #foreach($vs in $vuln.getVulnerableSoftware())
@@ -888,7 +887,7 @@ arising out of or in connection with the use of this tool, the analysis performe
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> 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> </ul></p>
#else #else
<p>Vulnerable Software &amp; Versions:&nbsp;(<a href="#" onclick="toggleDisplay(this,'.vs$vsctr'); return false;">show all</a>)<ul> <p>Vulnerable Software &amp; Versions:&nbsp;(<a href="#" onclick="return toggleDisplay(this,'.vs$vsctr', 'show all', 'show less');">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"><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> <li class="vs$vsctr">...</li>
#foreach($vs in $vuln.getVulnerableSoftware()) #foreach($vs in $vuln.getVulnerableSoftware())

View File

@@ -70,10 +70,10 @@ public class EngineIntegrationTest extends BaseTest {
@Test @Test
public void testEngine() throws Exception { public void testEngine() throws Exception {
String testClasses = "target/test-classes"; String testClasses = "target/test-classes";
// boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE); boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
// Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false); Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
Engine instance = new Engine(); Engine instance = new Engine();
// Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
instance.scan(testClasses); instance.scan(testClasses);
assertTrue(instance.getDependencies().size() > 0); assertTrue(instance.getDependencies().size() > 0);
instance.analyzeDependencies(); instance.analyzeDependencies();

View File

@@ -81,12 +81,24 @@ public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase {
*/ */
@Test @Test
public void testDetermineCPE_full() throws Exception { public void testDetermineCPE_full() throws Exception {
callDetermineCPE_full("hazelcast-2.5.jar", null); CPEAnalyzer instance = new CPEAnalyzer();
callDetermineCPE_full("spring-context-support-2.5.5.jar", "cpe:/a:vmware:springsource_spring_framework:2.5.5"); instance.open();
callDetermineCPE_full("spring-core-3.0.0.RELEASE.jar", "cpe:/a:vmware:springsource_spring_framework:3.0.0"); FileNameAnalyzer fnAnalyzer = new FileNameAnalyzer();
callDetermineCPE_full("org.mortbay.jetty.jar", "cpe:/a:mortbay_jetty:jetty:4.2"); JarAnalyzer jarAnalyzer = new JarAnalyzer();
callDetermineCPE_full("jaxb-xercesImpl-1.5.jar", null); HintAnalyzer hAnalyzer = new HintAnalyzer();
callDetermineCPE_full("ehcache-core-2.2.0.jar", null); FalsePositiveAnalyzer fp = new FalsePositiveAnalyzer();
try {
//callDetermineCPE_full("struts2-core-2.3.16.3.jar", "cpe:/a:apache:struts:2.3.16.3", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("hazelcast-2.5.jar", null, instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("spring-context-support-2.5.5.jar", "cpe:/a:vmware:springsource_spring_framework:2.5.5", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("spring-core-3.0.0.RELEASE.jar", "cpe:/a:vmware:springsource_spring_framework:3.0.0", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("org.mortbay.jetty.jar", "cpe:/a:mortbay_jetty:jetty:4.2", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("jaxb-xercesImpl-1.5.jar", null, instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("ehcache-core-2.2.0.jar", null, instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
} finally {
instance.close();
}
} }
/** /**
@@ -94,25 +106,16 @@ public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase {
* *
* @throws Exception is thrown when an exception occurs * @throws Exception is thrown when an exception occurs
*/ */
public void callDetermineCPE_full(String depName, String expResult) throws Exception { public void callDetermineCPE_full(String depName, String expResult, CPEAnalyzer instance, FileNameAnalyzer fnAnalyzer, JarAnalyzer jarAnalyzer, HintAnalyzer hAnalyzer, FalsePositiveAnalyzer fp) throws Exception {
File file = new File(this.getClass().getClassLoader().getResource(depName).getPath()); File file = new File(this.getClass().getClassLoader().getResource(depName).getPath());
Dependency dep = new Dependency(file); Dependency dep = new Dependency(file);
FileNameAnalyzer fnAnalyzer = new FileNameAnalyzer();
fnAnalyzer.analyze(dep, null); fnAnalyzer.analyze(dep, null);
JarAnalyzer jarAnalyzer = new JarAnalyzer();
jarAnalyzer.analyze(dep, null); jarAnalyzer.analyze(dep, null);
HintAnalyzer hAnalyzer = new HintAnalyzer();
hAnalyzer.analyze(dep, null); hAnalyzer.analyze(dep, null);
CPEAnalyzer instance = new CPEAnalyzer();
instance.open();
instance.analyze(dep, null); instance.analyze(dep, null);
instance.close();
FalsePositiveAnalyzer fp = new FalsePositiveAnalyzer();
fp.analyze(dep, null); fp.analyze(dep, null);
if (expResult != null) { if (expResult != null) {

View File

@@ -88,7 +88,15 @@ public class SuppressionHandlerTest {
xmlReader.parse(in); xmlReader.parse(in);
List result = handler.getSuppressionRules(); List<SuppressionRule> result = handler.getSuppressionRules();
assertTrue(result.size() > 3); assertTrue(result.size() > 3);
int baseCount = 0;
for (SuppressionRule r : result) {
if (r.isBase()) {
baseCount++;
}
}
assertTrue(baseCount > 0);
} }
} }

View File

@@ -146,6 +146,17 @@ public class SuppressionRuleTest {
List<String> result = instance.getCve(); List<String> result = instance.getCve();
assertEquals(cve, result); assertEquals(cve, result);
} }
/**
* Test of base property, of class SuppressionRule.
*/
@Test
public void testBase() {
SuppressionRule instance = new SuppressionRule();
assertFalse(instance.isBase());
instance.setBase(true);
assertTrue(instance.isBase());
}
//</editor-fold> //</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Ignored duplicate tests, left in, as empty tests, so IDE doesn't re-generate them"> //<editor-fold defaultstate="collapsed" desc="Ignored duplicate tests, left in, as empty tests, so IDE doesn't re-generate them">
@@ -424,33 +435,33 @@ public class SuppressionRuleTest {
instance.setSha1(sha1); instance.setSha1(sha1);
instance.addCwe("287"); instance.addCwe("287");
instance.process(dependency); instance.process(dependency);
assertTrue(dependency.getVulnerabilities().size() == 1); assertEquals(1, dependency.getVulnerabilities().size());
dependency.setSha1sum(sha1); dependency.setSha1sum(sha1);
instance.process(dependency); instance.process(dependency);
assertTrue(dependency.getVulnerabilities().isEmpty()); assertTrue(dependency.getVulnerabilities().isEmpty());
assertTrue(dependency.getSuppressedVulnerabilities().size() == 1); assertEquals(1, dependency.getSuppressedVulnerabilities().size());
//cvss //cvss
dependency.addVulnerability(v); dependency.addVulnerability(v);
instance = new SuppressionRule(); instance = new SuppressionRule();
instance.addCvssBelow(5f); instance.addCvssBelow(5f);
instance.process(dependency); instance.process(dependency);
assertTrue(dependency.getVulnerabilities().size() == 1); assertEquals(1, dependency.getVulnerabilities().size());
instance.addCvssBelow(8f); instance.addCvssBelow(8f);
instance.process(dependency); instance.process(dependency);
assertTrue(dependency.getVulnerabilities().isEmpty()); assertTrue(dependency.getVulnerabilities().isEmpty());
assertTrue(dependency.getSuppressedVulnerabilities().size() == 1); assertEquals(1, dependency.getSuppressedVulnerabilities().size());
//cve //cve
dependency.addVulnerability(v); dependency.addVulnerability(v);
instance = new SuppressionRule(); instance = new SuppressionRule();
instance.addCve("CVE-2012-1337"); instance.addCve("CVE-2012-1337");
instance.process(dependency); instance.process(dependency);
assertTrue(dependency.getVulnerabilities().size() == 1); assertEquals(1, dependency.getVulnerabilities().size());
instance.addCve("CVE-2013-1337"); instance.addCve("CVE-2013-1337");
instance.process(dependency); instance.process(dependency);
assertTrue(dependency.getVulnerabilities().isEmpty()); assertTrue(dependency.getVulnerabilities().isEmpty());
assertTrue(dependency.getSuppressedVulnerabilities().size() == 1); assertEquals(1, dependency.getSuppressedVulnerabilities().size());
//cpe //cpe
instance = new SuppressionRule(); instance = new SuppressionRule();
@@ -468,18 +479,21 @@ public class SuppressionRuleTest {
instance.setFilePath(pt); instance.setFilePath(pt);
instance.process(dependency); instance.process(dependency);
assertTrue(dependency.getIdentifiers().isEmpty()); assertTrue(dependency.getIdentifiers().isEmpty());
assertTrue(dependency.getSuppressedIdentifiers().size() == 1); assertEquals(1, dependency.getSuppressedIdentifiers().size());
instance = new SuppressionRule();
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.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: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"); dependency.addIdentifier("cpe", "cpe:/a:microsoft:.net_framework:5.0", "some url not needed for this test");
pt = new PropertyType(); pt = new PropertyType();
pt.setValue("cpe:/a:microsoft:.net_framework"); pt.setValue("cpe:/a:microsoft:.net_framework");
instance.addCpe(pt); instance.addCpe(pt);
assertTrue(dependency.getIdentifiers().size() == 3); instance.setBase(true);
assertEquals(3, dependency.getIdentifiers().size());
assertEquals(1, dependency.getSuppressedIdentifiers().size());
instance.process(dependency); instance.process(dependency);
assertTrue(dependency.getIdentifiers().isEmpty()); assertTrue(dependency.getIdentifiers().isEmpty());
assertTrue(dependency.getSuppressedIdentifiers().size() == 3); assertEquals(1, dependency.getSuppressedIdentifiers().size());
} }
/** /**

View File

@@ -134,14 +134,14 @@ public class DependencyVersionTest {
@Test @Test
public void testMatchesAtLeastThreeLevels() { public void testMatchesAtLeastThreeLevels() {
DependencyVersion instance = new DependencyVersion("1.2.3.4"); DependencyVersion instance = new DependencyVersion("2.3.16.3");
DependencyVersion version = new DependencyVersion("1.2.3.5"); DependencyVersion version = new DependencyVersion("2.3.16.4");
//true tests //true tests
assertEquals(true, instance.matchesAtLeastThreeLevels(version)); assertEquals(true, instance.matchesAtLeastThreeLevels(version));
version = new DependencyVersion("1.2"); version = new DependencyVersion("2.3");
assertEquals(true, instance.matchesAtLeastThreeLevels(version)); assertEquals(true, instance.matchesAtLeastThreeLevels(version));
//false tests //false tests
version = new DependencyVersion("1.2.2.5"); version = new DependencyVersion("2.3.16.1");
assertEquals(false, instance.matchesAtLeastThreeLevels(version)); assertEquals(false, instance.matchesAtLeastThreeLevels(version));
version = new DependencyVersion("2"); version = new DependencyVersion("2");
assertEquals(false, instance.matchesAtLeastThreeLevels(version)); assertEquals(false, instance.matchesAtLeastThreeLevels(version));

View File

@@ -10,7 +10,7 @@
<filePath>c:\path\to\some.jar</filePath> <filePath>c:\path\to\some.jar</filePath>
<cpe>cpe:/a:csv:csv:1.0</cpe> <cpe>cpe:/a:csv:csv:1.0</cpe>
</suppress> </suppress>
<suppress> <suppress base="true">
<notes><![CDATA[ <notes><![CDATA[
This suppresses any jboss:jboss cpe for any test.jar in any directory. This suppresses any jboss:jboss cpe for any test.jar in any directory.
]]></notes> ]]></notes>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>org.owasp</groupId> <groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId> <artifactId>dependency-check-parent</artifactId>
<version>1.2.4</version> <version>1.2.5</version>
</parent> </parent>
<groupId>org.owasp</groupId> <groupId>org.owasp</groupId>
<artifactId>dependency-check-jenkins</artifactId> <artifactId>dependency-check-jenkins</artifactId>

View File

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

View File

@@ -0,0 +1,462 @@
/*
* This file is part of dependency-check-maven.
*
* 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.
*/
package org.owasp.dependencycheck.maven;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.reporting.MavenReport;
import org.apache.maven.reporting.MavenReportException;
/**
* <p>
* This is an abstract reporting mojo that enables report aggregation. Some of the code in the this class was copied
* from the CoberturaReportMojo (http://mojo.codehaus.org/cobertura-maven-plugin/, version 2.6). The authors of the
* CoberturaReportMojo were <a href="will.gwaltney@sas.com">Will Gwaltney</a> and
* <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>. There working example of how to do report aggregation was
* invaluable.</p>
* <p>
* An important point about using this abstract class is that it is intended for one to write some form of serialized
* data (via the {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#writeDataFile() }; note that the
* <code>writeDataFile()</code> function is called automatically after either {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#executeNonAggregateReport(org.apache.maven.doxia.sink.Sink,
* org.apache.maven.doxia.sink.SinkFactory, java.util.Locale)
* } or {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#executeAggregateReport(org.apache.maven.doxia.sink.Sink,
* org.apache.maven.doxia.sink.SinkFactory, java.util.Locale)
* } are called. When <code>executeAggregateReport()</code> is implemented, one can call {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#getChildDataFiles()
* } to obtain a list of the data files to aggregate.</p>
*
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public abstract class ReportAggregationMojo extends AbstractMojo implements MavenReport {
/**
* The Maven Project Object.
*/
@Component
private MavenProject project;
/**
* Logger field reference.
*/
private static final Logger LOGGER = Logger.getLogger(ReportAggregationMojo.class.getName());
/**
* List of Maven project of the current build
*/
@Parameter(readonly = true, required = true, property = "reactorProjects")
private List<MavenProject> reactorProjects;
/**
* Generate aggregate reports in multi-module projects.
*/
@Parameter(property = "aggregate", defaultValue = "false")
private boolean aggregate;
/**
* Sets whether or not the external report format should be used.
*/
@Parameter(property = "metaFileName", defaultValue = "dependency-check.ser", required = true)
private String dataFileName;
/**
* Specifies the destination directory for the generated Dependency-Check report. This generally maps to
* "target/site".
*/
@Parameter(property = "reportOutputDirectory", defaultValue = "${project.reporting.outputDirectory}", required = true)
private File reportOutputDirectory;
/**
* Sets the Reporting output directory.
*
* @param directory the output directory
*/
@Override
public void setReportOutputDirectory(File directory) {
reportOutputDirectory = directory;
}
/**
* Returns the output directory.
*
* @return the output directory
*/
@Override
public File getReportOutputDirectory() {
return reportOutputDirectory;
}
/**
* Returns the output directory for the given project.
*
* @param project the Maven project to get the output directory for
* @return the output directory for the given project
*/
public File getReportOutputDirectory(MavenProject project) {
final Object o = project.getContextValue(getOutputDirectoryContextKey());
if (o != null && o instanceof File) {
return (File) o;
}
return null;
}
/**
* Returns whether this is an external report. This method always returns true.
*
* @return <code>true</code>
*/
@Override
public final boolean isExternalReport() {
return true;
}
/**
* The collection of child projects.
*/
private final Map<MavenProject, Set<MavenProject>> projectChildren = new HashMap<MavenProject, Set<MavenProject>>();
/**
* Called before execute; allows for any setup that is needed. If this is overridden you must call
* </code>super.preExecute()</code>.
*
* @throws MojoExecutionException thrown if there is an issue executing the mojo
* @throws MojoFailureException thrown if there is an issue executing the mojo
*/
protected void preExecute() throws MojoExecutionException, MojoFailureException {
buildAggregateInfo();
}
/**
* Called when the mojo is being executed.
*
* @throws MojoExecutionException thrown if there is an issue executing the mojo
* @throws MojoFailureException thrown if there is an issue executing the mojo
*/
protected abstract void performExecute() throws MojoExecutionException, MojoFailureException;
/**
* Runs after the mojo has executed. This implementation will call <code>writeDataFile()</code>. As such, it is
* important that if this method is overriden that <code>super.postExecute()</code> is called.
*
* @throws MojoExecutionException thrown if there is an issue executing the mojo
* @throws MojoFailureException thrown if there is an issue executing the mojo
*/
protected void postExecute() throws MojoExecutionException, MojoFailureException {
final File written = writeDataFile();
if (written != null) {
project.setContextValue(getDataFileContextKey(), written.getAbsolutePath());
}
}
/**
* Returns the key used to store the path to the data file that is saved by <code>writeDataFile()</code>. This key
* is used in the <code>MavenProject.(set|get)ContextValue</code>.
*
* @return the key used to store the path to the data file
*/
protected String getDataFileContextKey() {
return "dependency-check-path-" + this.getDataFileName();
}
/**
* Returns the key used to store the path to the output directory. When generating the report in the
* <code>executeAggregateReport()</code> the output directory should be obtained by using this key.
*
* @return the key used to store the path to the output directory
*/
protected String getOutputDirectoryContextKey() {
return "dependency-output-dir-" + this.getDataFileName();
}
/**
* Is called by Maven to execute the mojo.
*
* @throws MojoExecutionException thrown if there is an issue executing the mojo
* @throws MojoFailureException thrown if there is an issue executing the mojo
*/
public final void execute() throws MojoExecutionException, MojoFailureException {
try {
preExecute();
performExecute();
} finally {
postExecute();
}
}
/**
* Runs prior to the site report generation.
*
* @throws MavenReportException if a maven report exception occurs
*/
protected void preGenerate() throws MavenReportException {
buildAggregateInfo();
project.setContextValue(getOutputDirectoryContextKey(), getReportOutputDirectory());
}
/**
* Executes after the site report has been generated.
*
* @throws MavenReportException if a maven report exception occurs
*/
protected void postGenerate() throws MavenReportException {
final File written = writeDataFile();
if (written != null) {
project.setContextValue(getDataFileContextKey(), written.getAbsolutePath());
}
}
/**
* Generates the non aggregate report.
*
* @param locale the locale to use when generating the report
* @throws MavenReportException if a maven report exception occurs
*/
protected abstract void executeNonAggregateReport(Locale locale) throws MavenReportException;
/**
* Generates the aggregate Site Report.
*
* @param project the maven project used to generate the aggregate report
* @param locale the locale to use when generating the report
* @throws MavenReportException if a maven report exception occurs
*/
protected abstract void executeAggregateReport(MavenProject project, Locale locale) throws MavenReportException;
/**
* Generates the Dependency-Check Site Report.
*
* @param sink the sink to write the report to
* @param locale the locale to use when generating the report
* @throws MavenReportException if a maven report exception occurs
* @deprecated use {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale) instead.
*/
@Deprecated
public final void generate(@SuppressWarnings("deprecation") org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException {
generate((Sink) sink, locale);
}
/**
* Generates the Dependency-Check Site Report.
*
* @param sink the sink to write the report to
* @param locale the locale to use when generating the report
* @throws MavenReportException if a maven report exception occurs
*/
public final void generate(Sink sink, Locale locale) throws MavenReportException {
try {
preGenerate();
if (canGenerateNonAggregateReport()) {
executeNonAggregateReport(locale);
}
if (canGenerateAggregateReport()) {
for (MavenProject proj : reactorProjects) {
if (!isMultiModule(proj)) {
continue;
}
executeAggregateReport(proj, locale);
}
}
} finally {
postGenerate();
}
}
/**
* Returns whether or not the mojo can generate a non-aggregate report for this project.
*
* @return <code>true</code> if a non-aggregate report can be generated, otherwise <code>false</code>
*/
protected abstract boolean canGenerateNonAggregateReport();
/**
* Returns whether or not we can generate any aggregate reports at this time.
*
* @return <code>true</code> if an aggregate report can be generated, otherwise <code>false</code>
*/
protected abstract boolean canGenerateAggregateReport();
/**
* Returns the name of the data file that contains the serialized data.
*
* @return the name of the data file that contains the serialized data
*/
protected String getDataFileName() {
return dataFileName;
}
/**
* Writes the data file to disk in the target directory.
*
* @return the File object referencing the data file that was written
*/
protected abstract File writeDataFile();
/**
* Collects the information needed for building aggregate reports.
*/
private void buildAggregateInfo() {
// build parent-child map
for (MavenProject proj : reactorProjects) {
Set<MavenProject> depList = projectChildren.get(proj.getParent());
if (depList == null) {
depList = new HashSet<MavenProject>();
projectChildren.put(proj.getParent(), depList);
}
depList.add(proj);
}
}
/**
* Returns a list containing all the recursive, non-pom children of the given project, never <code>null</code>.
*
* @return a list of child projects
*/
protected List<MavenProject> getAllChildren() {
return getAllChildren(project);
}
/**
* Returns a list containing all the recursive, non-pom children of the given project, never <code>null</code>.
*
* @param parentProject the parent project to collect the child project references
* @return a list of child projects
*/
protected List<MavenProject> getAllChildren(MavenProject parentProject) {
final Set<MavenProject> children = projectChildren.get(parentProject);
if (children == null) {
return Collections.emptyList();
}
final List<MavenProject> result = new ArrayList<MavenProject>();
for (MavenProject child : children) {
if (isMultiModule(child)) {
result.addAll(getAllChildren(child));
} else {
result.add(child);
}
}
return result;
}
/**
* Returns a list of data files that were produced by the direct children of the given MavenProject.
*
* @param project the Maven project to obtain the child data files from
* @return a list of the data files
*/
protected List<File> getAllChildDataFiles(MavenProject project) {
final List<MavenProject> children = getAllChildren(project);
return getDataFiles(children);
}
/**
* Returns any existing output files from the given list of projects.
*
* @param projects the list of projects to obtain the output files from
* @return a list of output files
*/
protected List<File> getDataFiles(List<MavenProject> projects) {
final List<File> files = new ArrayList<File>();
for (MavenProject proj : projects) {
final Object path = project.getContextValue(getDataFileContextKey());
if (path == null) {
final String msg = String.format("Unable to aggregate data for '%s' - aggregate data file was not generated",
proj.getName());
LOGGER.warning(msg);
} else {
final File outputFile = new File((String) path);
if (outputFile.exists()) {
files.add(outputFile);
} else {
if (!isMultiModule(project)) {
final String msg = String.format("Unable to aggregate data for '%s' - missing data file '%s'",
proj.getName(), outputFile.getPath());
LOGGER.warning(msg);
}
}
}
}
return files;
}
/**
* Test if the project has pom packaging
*
* @param mavenProject Project to test
* @return <code>true</code> if it has a pom packaging; otherwise <code>false</code>
*/
protected boolean isMultiModule(MavenProject mavenProject) {
return "pom".equals(mavenProject.getPackaging());
}
/**
* Test if the current project has pom packaging
*
* @return <code>true</code> if it has a pom packaging; otherwise <code>false</code>
*/
protected boolean isMultiModule() {
return isMultiModule(project);
}
/**
* Check whether the current project is the last project in a multi-module build. If the maven build is not a
* multi-module project then this will always return true.
*
* @return <code>true</code> if the current project is the last project in a multi-module build; otherwise
* <code>false</code>
*/
protected boolean isLastProject() {
return project.equals(reactorProjects.get(reactorProjects.size() - 1));
}
/**
* Returns whether or not the mojo is configured to perform report aggregation.
*
* @return <code>true</code> if report aggregation is enabled; otherwise <code>false</code>
*/
public boolean isAggregate() {
return aggregate;
}
/**
* Returns a reference to the current project. This method is used instead of auto-binding the project via component
* annotation in concrete implementations of this. If the child has a <code>@Component MavenProject project;</code>
* defined then the abstract class (i.e. this class) will not have access to the current project (just the way Maven
* works with the binding).
*
* @return returns a reference to the current project
*/
protected MavenProject getProject() {
return project;
}
}

View File

@@ -0,0 +1,456 @@
/*
* This file is part of dependency-check-maven.
*
* 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.
*/
package org.owasp.dependencycheck.maven;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.maven.doxia.sink.Sink;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Evidence;
import org.owasp.dependencycheck.dependency.Identifier;
import org.owasp.dependencycheck.dependency.Reference;
import org.owasp.dependencycheck.dependency.Vulnerability;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
import org.owasp.dependencycheck.reporting.ReportGenerator;
/**
* A utility class that encapsulates the report generation for dependency-check-maven.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
final class ReportingUtil {
/**
* Logger field reference.
*/
private static final Logger LOGGER = Logger.getLogger(ReportingUtil.class.getName());
/**
* Empty private constructor for this utility class.
*/
private ReportingUtil() {
}
/**
* Generates the reports for a given dependency-check engine.
*
* @param engine a dependency-check engine
* @param outDirectory the directory to write the reports to
* @param projectName the name of the project that a report is being generated for
* @param format the format of the report to generate
*/
static void generateExternalReports(Engine engine, File outDirectory, String projectName, String format) {
DatabaseProperties prop = null;
CveDB cve = null;
try {
cve = new CveDB();
cve.open();
prop = cve.getDatabaseProperties();
} catch (DatabaseException ex) {
LOGGER.log(Level.FINE, "Unable to retrieve DB Properties", ex);
} finally {
if (cve != null) {
cve.close();
}
}
final ReportGenerator r = new ReportGenerator(projectName, engine.getDependencies(), engine.getAnalyzers(), prop);
try {
r.generateReports(outDirectory.getCanonicalPath(), format);
} catch (IOException ex) {
LOGGER.log(Level.SEVERE,
"Unexpected exception occurred during analysis; please see the verbose error log for more details.");
LOGGER.log(Level.FINE, null, ex);
} catch (Throwable ex) {
LOGGER.log(Level.SEVERE,
"Unexpected exception occurred during analysis; please see the verbose error log for more details.");
LOGGER.log(Level.FINE, null, ex);
}
}
/**
* Generates a dependency-check report using the Maven Site format.
*
* @param engine the engine used to scan the dependencies
* @param sink the sink to write the data to
* @param projectName the name of the project
*/
static void generateMavenSiteReport(final Engine engine, Sink sink, String projectName) {
final List<Dependency> dependencies = engine.getDependencies();
writeSiteReportHeader(sink, projectName);
writeSiteReportTOC(sink, dependencies);
int cnt = 0;
for (Dependency d : dependencies) {
writeSiteReportDependencyHeader(sink, d);
cnt = writeSiteReportDependencyEvidenceUsed(d, cnt, sink);
cnt = writeSiteReportDependencyRelatedDependencies(d, cnt, sink);
writeSiteReportDependencyIdentifiers(d, sink);
writeSiteReportDependencyVulnerabilities(d, sink, cnt);
}
sink.body_();
}
// <editor-fold defaultstate="collapsed" desc="various writeXXXXX methods to generate the Site Report">
/**
* Writes the vulnerabilities to the site report.
*
* @param d the dependency
* @param sink the sink to write the data to
* @param collapsibleHeaderCount the collapsible header count
*/
private static void writeSiteReportDependencyVulnerabilities(Dependency d, Sink sink, int collapsibleHeaderCount) {
int cnt = collapsibleHeaderCount;
if (d.getVulnerabilities() != null && !d.getVulnerabilities().isEmpty()) {
for (Vulnerability v : d.getVulnerabilities()) {
sink.paragraph();
sink.bold();
try {
sink.link("http://web.nvd.nist.gov/view/vuln/detail?vulnId=" + URLEncoder.encode(v.getName(), "US-ASCII"));
sink.text(v.getName());
sink.link_();
sink.bold_();
} catch (UnsupportedEncodingException ex) {
sink.text(v.getName());
sink.bold_();
sink.lineBreak();
sink.text("http://web.nvd.nist.gov/view/vuln/detail?vulnId=" + v.getName());
}
sink.paragraph_();
sink.paragraph();
sink.text("Severity: ");
if (v.getCvssScore() < 4.0) {
sink.text("Low");
} else {
if (v.getCvssScore() >= 7.0) {
sink.text("High");
} else {
sink.text("Medium");
}
}
sink.lineBreak();
sink.text("CVSS Score: " + v.getCvssScore());
if (v.getCwe() != null && !v.getCwe().isEmpty()) {
sink.lineBreak();
sink.text("CWE: ");
sink.text(v.getCwe());
}
sink.paragraph_();
sink.paragraph();
sink.text(v.getDescription());
if (v.getReferences() != null && !v.getReferences().isEmpty()) {
sink.list();
for (Reference ref : v.getReferences()) {
sink.listItem();
sink.text(ref.getSource());
sink.text(" - ");
sink.link(ref.getUrl());
sink.text(ref.getName());
sink.link_();
sink.listItem_();
}
sink.list_();
}
sink.paragraph_();
if (v.getVulnerableSoftware() != null && !v.getVulnerableSoftware().isEmpty()) {
sink.paragraph();
cnt += 1;
sink.rawText("Vulnerable Software <a href=\"javascript:toggleElement(this, 'vulnSoft" + cnt + "')\">[-]</a>");
sink.rawText("<div id=\"vulnSoft" + cnt + "\" style=\"display:block\">");
sink.list();
for (VulnerableSoftware vs : v.getVulnerableSoftware()) {
sink.listItem();
try {
sink.link("http://web.nvd.nist.gov/view/vuln/search-results?cpe=" + URLEncoder.encode(vs.getName(), "US-ASCII"));
sink.text(vs.getName());
sink.link_();
if (vs.hasPreviousVersion()) {
sink.text(" and all previous versions.");
}
} catch (UnsupportedEncodingException ex) {
sink.text(vs.getName());
if (vs.hasPreviousVersion()) {
sink.text(" and all previous versions.");
}
sink.text(" (http://web.nvd.nist.gov/view/vuln/search-results?cpe=" + vs.getName() + ")");
}
sink.listItem_();
}
sink.list_();
sink.rawText("</div>");
sink.paragraph_();
}
}
}
}
/**
* Writes the identifiers to the site report.
*
* @param d the dependency
* @param sink the sink to write the data to
*/
private static void writeSiteReportDependencyIdentifiers(Dependency d, Sink sink) {
if (d.getIdentifiers() != null && !d.getIdentifiers().isEmpty()) {
sink.sectionTitle4();
sink.text("Identifiers");
sink.sectionTitle4_();
sink.list();
for (Identifier i : d.getIdentifiers()) {
sink.listItem();
sink.text(i.getType());
sink.text(": ");
if (i.getUrl() != null && i.getUrl().length() > 0) {
sink.link(i.getUrl());
sink.text(i.getValue());
sink.link_();
} else {
sink.text(i.getValue());
}
if (i.getDescription() != null && i.getDescription().length() > 0) {
sink.lineBreak();
sink.text(i.getDescription());
}
sink.listItem_();
}
sink.list_();
}
}
/**
* Writes the related dependencies to the site report.
*
* @param d the dependency
* @param sink the sink to write the data to
* @param collapsibleHeaderCount the collapsible header count
* @return the collapsible header count
*/
private static int writeSiteReportDependencyRelatedDependencies(Dependency d, int collapsibleHeaderCount, Sink sink) {
int cnt = collapsibleHeaderCount;
if (d.getRelatedDependencies() != null && !d.getRelatedDependencies().isEmpty()) {
cnt += 1;
sink.sectionTitle4();
sink.rawText("Related Dependencies <a href=\"javascript:toggleElement(this, 'related" + cnt + "')\">[+]</a>");
sink.sectionTitle4_();
sink.rawText("<div id=\"related" + cnt + "\" style=\"display:none\">");
sink.list();
for (Dependency r : d.getRelatedDependencies()) {
sink.listItem();
sink.text(r.getFileName());
sink.list();
writeListItem(sink, "File Path: " + r.getFilePath());
writeListItem(sink, "SHA1: " + r.getSha1sum());
writeListItem(sink, "MD5: " + r.getMd5sum());
sink.list_();
sink.listItem_();
}
sink.list_();
sink.rawText("</div>");
}
return cnt;
}
/**
* Writes the evidence used to the site report.
*
* @param d the dependency
* @param sink the sink to write the data to
* @param collapsibleHeaderCount the collapsible header count
* @return the collapsible header count
*/
private static int writeSiteReportDependencyEvidenceUsed(Dependency d, int collapsibleHeaderCount, Sink sink) {
int cnt = collapsibleHeaderCount;
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>");
sink.sectionTitle4_();
sink.rawText("<div id=\"evidence" + cnt + "\" style=\"display:none\">");
sink.table();
sink.tableRow();
writeTableHeaderCell(sink, "Source");
writeTableHeaderCell(sink, "Name");
writeTableHeaderCell(sink, "Value");
sink.tableRow_();
for (Evidence e : evidence) {
sink.tableRow();
writeTableCell(sink, e.getSource());
writeTableCell(sink, e.getName());
writeTableCell(sink, e.getValue());
sink.tableRow_();
}
sink.table_();
sink.rawText("</div>");
}
return cnt;
}
/**
* Writes the dependency header to the site report.
*
* @param d the dependency
* @param sink the sink to write the data to
*/
private static void writeSiteReportDependencyHeader(Sink sink, Dependency d) {
sink.sectionTitle2();
sink.anchor("sha1" + d.getSha1sum());
sink.text(d.getFileName());
sink.anchor_();
sink.sectionTitle2_();
if (d.getDescription() != null && d.getDescription().length() > 0) {
sink.paragraph();
sink.bold();
sink.text("Description: ");
sink.bold_();
sink.text(d.getDescription());
sink.paragraph_();
}
if (d.getLicense() != null && d.getLicense().length() > 0) {
sink.paragraph();
sink.bold();
sink.text("License: ");
sink.bold_();
if (d.getLicense().startsWith("http://") && !d.getLicense().contains(" ")) {
sink.link(d.getLicense());
sink.text(d.getLicense());
sink.link_();
} else {
sink.text(d.getLicense());
}
sink.paragraph_();
}
}
/**
* Adds a list item to the site report.
*
* @param sink the sink to write the data to
* @param text the text to write
*/
private static void writeListItem(Sink sink, String text) {
sink.listItem();
sink.text(text);
sink.listItem_();
}
/**
* Adds a table cell to the site report.
*
* @param sink the sink to write the data to
* @param text the text to write
*/
private static void writeTableCell(Sink sink, String text) {
sink.tableCell();
sink.text(text);
sink.tableCell_();
}
/**
* Adds a table header cell to the site report.
*
* @param sink the sink to write the data to
* @param text the text to write
*/
private static void writeTableHeaderCell(Sink sink, String text) {
sink.tableHeaderCell();
sink.text(text);
sink.tableHeaderCell_();
}
/**
* Writes the TOC for the site report.
*
* @param sink the sink to write the data to
* @param dependencies the dependencies that are being reported on
*/
private static void writeSiteReportTOC(Sink sink, final List<Dependency> dependencies) {
sink.list();
for (Dependency d : dependencies) {
sink.listItem();
sink.link("#sha1" + d.getSha1sum());
sink.text(d.getFileName());
sink.link_();
if (!d.getVulnerabilities().isEmpty()) {
sink.rawText(" <font style=\"color:red\">•</font>");
}
if (!d.getRelatedDependencies().isEmpty()) {
sink.list();
for (Dependency r : d.getRelatedDependencies()) {
writeListItem(sink, r.getFileName());
}
sink.list_();
}
sink.listItem_();
}
sink.list_();
}
/**
* Writes the site report header.
*
* @param sink the sink to write the data to
* @param projectName the name of the project
*/
private static void writeSiteReportHeader(Sink sink, String projectName) {
sink.head();
sink.title();
sink.text("Dependency-Check Report: " + projectName);
sink.title_();
sink.head_();
sink.body();
sink.rawText("<script type=\"text/javascript\">");
sink.rawText("function toggleElement(el, targetId) {");
sink.rawText("if (el.innerText == '[+]') {");
sink.rawText(" el.innerText = '[-]';");
sink.rawText(" document.getElementById(targetId).style.display='block';");
sink.rawText("} else {");
sink.rawText(" el.innerText = '[+]';");
sink.rawText(" document.getElementById(targetId).style.display='none';");
sink.rawText("}");
sink.rawText("}");
sink.rawText("</script>");
sink.section1();
sink.sectionTitle1();
sink.text("Project: " + projectName);
sink.sectionTitle1_();
sink.date();
final Date now = new Date();
sink.text(DateFormat.getDateTimeInstance().format(now));
sink.date_();
sink.section1_();
}
// </editor-fold>
}

View File

@@ -4,8 +4,8 @@ The following properties can be set on the dependency-check-maven plugin.
Property | Description | Default Value Property | Description | Default Value
---------------------|------------------------------------|------------------ ---------------------|------------------------------------|------------------
aggregate | Sets whether report aggregation will be performed for multi-module site reports. This option only affects the report generation when configured within the reporting section. | false
autoUpdate | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. | true autoUpdate | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. | true
externalReport | When using as a Site plugin this parameter sets whether or not the external report format should be used. | false
outputDirectory | The location to write the report(s). Note, this is not used if generating the report as part of a `mvn site` build | 'target' outputDirectory | The location to write the report(s). Note, this is not used if generating the report as part of a `mvn site` build | 'target'
failBuildOnCVSS | Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail. | 11 failBuildOnCVSS | Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail. | 11
format | The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the Site plugin unless the externalReport is set to true. | HTML 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
@@ -31,7 +31,7 @@ jarAnalyzer | Sets whether Jar Analyzer will be used.
nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. | true nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. | true
nexusUrl | Defines the Nexus URL. | https://repository.sonatype.org/service/local/ nexusUrl | Defines the Nexus URL. | https://repository.sonatype.org/service/local/
nexusUsesProxy | Whether or not the defined proxy should be used when connecting to Nexus. | true nexusUsesProxy | Whether or not the defined proxy should be used when connecting to Nexus. | true
nuspecAnalyzerEnabled | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | true nuspecAnalyzerEnabled | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | true
assemblyAnalyzerEnabled | Sets whether or not the .NET Assembly Analyzer should be used. | true assemblyAnalyzerEnabled | Sets whether or not the .NET Assembly Analyzer should be used. | true
pathToMono | The path to Mono for .NET assembly analysis on non-windows systems | &nbsp; pathToMono | The path to Mono for .NET assembly analysis on non-windows systems | &nbsp;
@@ -40,21 +40,27 @@ Advanced Configuration
The following properties can be configured in the plugin. However, they are less frequently changed. One exception The following properties can be configured in the plugin. However, they are less frequently changed. One exception
may be the cvedUrl properties, which can be used to host a mirror of the NVD within an enterprise environment. may be the cvedUrl properties, which can be used to host a mirror of the NVD within an enterprise environment.
Property | Description | Default Value Property | Description | Default Value
---------------------|-------------------------------------------------------------------------|------------------ ---------------------|--------------------------------------------------------------------------|------------------
cveUrl12Modified | URL for the modified CVE 1.2 | http://nvd.nist.gov/download/nvdcve-modified.xml cveUrl12Modified | URL for the modified CVE 1.2. | http://nvd.nist.gov/download/nvdcve-modified.xml
cveUrl20Modified | URL for the modified CVE 2.0 | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml cveUrl20Modified | URL for the modified CVE 2.0. | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
cveUrl12Base | Base URL for each year's CVE 1.2, the %d will be replaced with the year | http://nvd.nist.gov/download/nvdcve-%d.xml cveUrl12Base | Base URL for each year's CVE 1.2, the %d will be replaced with the year. | http://nvd.nist.gov/download/nvdcve-%d.xml
cveUrl20Base | Base URL for each year's CVE 2.0, the %d will be replaced with the year | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml cveUrl20Base | Base URL for each year's CVE 2.0, the %d will be replaced with the year. | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
connectionTimeout | The URL Connection Timeout. | &nbsp; connectionTimeout | Sets the URL Connection Timeout used when downloading external data. | &nbsp;
dataDirectory | Data directory to hold SQL CVEs contents. This should generally not be changed. | &nbsp; dataDirectory | Sets the data directory to hold SQL CVEs contents. This should generally not be changed. | &nbsp;
databaseDriverName | The name of the database driver. Example: org.h2.Driver. | &nbsp; databaseDriverName | The name of the database driver. Example: org.h2.Driver. | &nbsp;
databaseDriverPath | The path to the database driver JAR file; only used if the driver is not in the class path. | &nbsp; databaseDriverPath | The path to the database driver JAR file; only used if the driver is not in the class path. | &nbsp;
connectionString | The connection string used to connect to the database. | &nbsp; connectionString | The connection string used to connect to the database. | &nbsp;
databaseUser | The username used when connecting to the database. | &nbsp; databaseUser | The username used when connecting to the database. | &nbsp;
databasePassword | The password used when connecting to the database. | &nbsp; databasePassword | The password used when connecting to the database. | &nbsp;
metaFileName | Sets the name of the file to use for storing the metadata about the project. | dependency-check.ser
Proxy Configuration Proxy Configuration
==================== ====================
Use [Maven's settings](https://maven.apache.org/settings.html#Proxies) to configure a proxy server. Use [Maven's settings](https://maven.apache.org/settings.html#Proxies) to configure a proxy server. If multiple proxies
are configured in the Maven settings file you must tell dependency-check which proxy to use with the following property:
Property | Description | Default Value
---------------------|--------------------------------------------------------------------------------------|------------------
mavenSettingsProxyId | The id for the proxy, configured via settings.xml, that dependency-check should use. | &nbsp;

View File

@@ -17,7 +17,9 @@ Create the DependencyCheck-report.html in the target directory
```xml ```xml
<project> <project>
...
<build> <build>
...
<plugins> <plugins>
... ...
<plugin> <plugin>
@@ -41,11 +43,48 @@ Create the DependencyCheck-report.html in the target directory
``` ```
$H$H$H Example 2: $H$H$H Example 2:
Create an aggregated dependency-check report within the site
```xml
<project>
...
<reporting>
...
<plugins>
...
<plugin>
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>${project.version}</version>
<configuration>
<aggregate>true</aggregate>
</configuration>
<reportSets>
<reportSet>
<reports>
<report>check</report>
</reports>
</reportSet>
</reportSets>
</plugin>
</plugin>
...
</plugins>
...
</reporting>
...
</project>
```
$H$H$H Example 3:
Create the DependencyCheck-report.html and fail the build for CVSS greater then 8 Create the DependencyCheck-report.html and fail the build for CVSS greater then 8
```xml ```xml
<project> <project>
...
<build> <build>
...
<plugins> <plugins>
... ...
<plugin> <plugin>
@@ -71,44 +110,14 @@ Create the DependencyCheck-report.html and fail the build for CVSS greater then
</project> </project>
``` ```
$H$H$H Example 3:
Create the dependency-check report within the site
```xml
<project>
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<configuration>
<reportPlugins>
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>${project.version}</version>
<configuration>
<externalReport>false</externalReport>
</configuration>
</plugin>
</reportPlugins>
</configuration>
</plugin>
...
</plugins>
...
</build>
...
</project>
```
$H$H$H Example 4: $H$H$H Example 4:
Create the DependencyCheck-report.html and skip artifacts no bundled in distribution (Provided and Runtime scope) Create the DependencyCheck-report.html and skip artifacts not bundled in distribution (Provided and Runtime scope)
```xml ```xml
<project> <project>
...
<build> <build>
...
<plugins> <plugins>
... ...
<plugin> <plugin>
@@ -140,7 +149,9 @@ Create the DependencyCheck-report.html and use internal mirroring of CVE content
```xml ```xml
<project> <project>
...
<build> <build>
...
<plugins> <plugins>
... ...
<plugin> <plugin>

View File

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

View File

@@ -63,8 +63,22 @@ public final class Checksum {
try { try {
fis = new FileInputStream(file); fis = new FileInputStream(file);
FileChannel ch = fis.getChannel(); FileChannel ch = fis.getChannel();
MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length()); long remainingToRead = file.length();
digest.update(byteBuffer); long start = 0;
while (remainingToRead > 0) {
long amountToRead;
if (remainingToRead > Integer.MAX_VALUE) {
remainingToRead -= Integer.MAX_VALUE;
amountToRead = Integer.MAX_VALUE;
} else {
amountToRead = remainingToRead;
remainingToRead = 0;
}
MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, start, amountToRead);
digest.update(byteBuffer);
start += amountToRead;
}
// BufferedInputStream bis = new BufferedInputStream(fis); // BufferedInputStream bis = new BufferedInputStream(fis);
// DigestInputStream dis = new DigestInputStream(bis, digest); // DigestInputStream dis = new DigestInputStream(bis, digest);
// //yes, we are reading in a buffer for performance reasons - 1 byte at a time is SLOW // //yes, we are reading in a buffer for performance reasons - 1 byte at a time is SLOW

View File

@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
This file is part of Dependency-Check. This file is part of Dependency-Check.
@@ -15,12 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
Copyright (c) 2012 - Jeremy Long 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> <modelVersion>4.0.0</modelVersion>
<groupId>org.owasp</groupId> <groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId> <artifactId>dependency-check-parent</artifactId>
<version>1.2.4</version> <version>1.2.5</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<modules> <modules>

File diff suppressed because one or more lines are too long