From d31e0453bd497b9a6de8f10a8b9f7b1e92c52ea1 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Mon, 20 Feb 2017 07:01:05 -0500 Subject: [PATCH 1/4] fix for #660 --- .../main/resources/dependencycheck-base-suppression.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dependency-check-core/src/main/resources/dependencycheck-base-suppression.xml b/dependency-check-core/src/main/resources/dependencycheck-base-suppression.xml index 409bf11e6..ddc239276 100644 --- a/dependency-check-core/src/main/resources/dependencycheck-base-suppression.xml +++ b/dependency-check-core/src/main/resources/dependencycheck-base-suppression.xml @@ -507,4 +507,12 @@ ^io\.jsonwebtoken:jjwt:.*$ cpe:/a:sonatype:nexus + + + ^commons-validator:commons-validator:.*$ + cpe:/a:apache:http_server + cpe:/a:apache:apache_http_server + From a5990ea6f39b0c4d5dec9ccfb06815ebc145285c Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Tue, 21 Feb 2017 06:38:31 -0500 Subject: [PATCH 2/4] update to #657 to allow sorted vulnerable software in repots; also, sorting an array list is faster then building a treeset --- .../dependency/Vulnerability.java | 42 ++++++++++++++++--- .../main/resources/templates/HtmlReport.vsl | 8 ++-- .../main/resources/templates/XmlReport.vsl | 8 ++-- 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Vulnerability.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Vulnerability.java index aac408a02..1720edda8 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Vulnerability.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Vulnerability.java @@ -18,10 +18,11 @@ package org.owasp.dependencycheck.dependency; import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; import org.apache.commons.lang3.builder.CompareToBuilder; /** @@ -139,6 +140,21 @@ public class Vulnerability implements Serializable, Comparable { return references; } + /** + * Returns the list of references. This is primarily used within the + * generated reports. + * + * @param sorted whether the returned list should be sorted + * @return the list of references + */ + public List getReferences(boolean sorted) { + List sortedRefs = new ArrayList<>(this.references); + if (sorted) { + Collections.sort(sortedRefs); + } + return sortedRefs; + } + /** * Set the value of references. * @@ -181,6 +197,21 @@ public class Vulnerability implements Serializable, Comparable { return vulnerableSoftware; } + /** + * Returns a sorted list of vulnerable software. This is primarily used for + * display within reports. + * + * @param sorted whether or not the list should be sorted + * @return the list of vulnerable software + */ + public List getVulnerableSoftware(boolean sorted) { + List sortedVulnerableSoftware = new ArrayList<>(this.vulnerableSoftware); + if (sorted) { + Collections.sort(sortedVulnerableSoftware); + } + return sortedVulnerableSoftware; + } + /** * Set the value of vulnerableSoftware. * @@ -398,15 +429,14 @@ public class Vulnerability implements Serializable, Comparable { final StringBuilder sb = new StringBuilder("Vulnerability "); sb.append(this.name); sb.append("\nReferences:\n"); - SortedSet sortedReferences = new TreeSet(this.references); - for (Reference reference : sortedReferences) { + for (Reference reference : getReferences(true)) { sb.append("=> "); sb.append(reference); sb.append("\n"); } sb.append("\nSoftware:\n"); - SortedSet sortedVulnerableSoftware = new TreeSet(this.vulnerableSoftware); - for (VulnerableSoftware software : sortedVulnerableSoftware) { + + for (VulnerableSoftware software : getVulnerableSoftware(true)) { sb.append("=> "); sb.append(software); sb.append("\n"); diff --git a/dependency-check-core/src/main/resources/templates/HtmlReport.vsl b/dependency-check-core/src/main/resources/templates/HtmlReport.vsl index 7da1e3c15..02035e96e 100644 --- a/dependency-check-core/src/main/resources/templates/HtmlReport.vsl +++ b/dependency-check-core/src/main/resources/templates/HtmlReport.vsl @@ -842,7 +842,7 @@ Getting Help: $enc.html($vuln.description) #if ($vuln.getReferences().size()>0) @@ -857,7 +857,7 @@ Getting Help: Vulnerable Software & Versions: (show all)
  • $enc.html($vuln.matchedCPE) #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end
  • ...
  • - #foreach($vs in $vuln.getVulnerableSoftware()) + #foreach($vs in $vuln.getVulnerableSoftware(true)) #end

@@ -977,7 +977,7 @@ Getting Help: $enc.html($vuln.description) #if ($vuln.getReferences().size()>0) @@ -991,7 +991,7 @@ Getting Help: Vulnerable Software & Versions: (show all)
  • $enc.html($vuln.matchedCPE) #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end
  • ...
  • - #foreach($vs in $vuln.getVulnerableSoftware()) + #foreach($vs in $vuln.getVulnerableSoftware(true)) #end

diff --git a/dependency-check-core/src/main/resources/templates/XmlReport.vsl b/dependency-check-core/src/main/resources/templates/XmlReport.vsl index 8e71e1dc7..0bfd8c49c 100644 --- a/dependency-check-core/src/main/resources/templates/XmlReport.vsl +++ b/dependency-check-core/src/main/resources/templates/XmlReport.vsl @@ -141,7 +141,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. #end $enc.xml($vuln.description) -#foreach($ref in $vuln.getReferences()) +#foreach($ref in $vuln.getReferences(true)) $enc.xml($ref.source) $enc.xml($ref.url) @@ -150,7 +150,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. #end -#foreach($vs in $vuln.getVulnerableSoftware()) +#foreach($vs in $vuln.getVulnerableSoftware(true)) $enc.xml($vs.name) #end @@ -172,7 +172,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. #end $enc.xml($vuln.description) -#foreach($ref in $vuln.getReferences()) +#foreach($ref in $vuln.getReferences(true)) $enc.xml($ref.source) $enc.xml($ref.url) @@ -181,7 +181,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. #end -#foreach($vs in $vuln.getVulnerableSoftware()) +#foreach($vs in $vuln.getVulnerableSoftware(true)) $enc.xml($vs.name) #end From 2ea0eb3c640c866f771f655de0097449f7935abf Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Tue, 21 Feb 2017 06:40:02 -0500 Subject: [PATCH 3/4] correct fix for issue #660; correctly handle organization from the pom --- .../dependencycheck/analyzer/JarAnalyzer.java | 10 +- .../owasp/dependencycheck/xml/pom/Model.java | 22 +++++ .../dependencycheck/xml/pom/PomHandler.java | 98 +++++++++++-------- .../dependencycheck/xml/pom/PomUtils.java | 12 +-- .../dependencycheck-base-suppression.xml | 8 -- .../dependencycheck/xml/pom/PomUtilsTest.java | 13 ++- 6 files changed, 105 insertions(+), 58 deletions(-) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java index 8cba0c48c..dca3b7b6e 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java @@ -166,9 +166,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { */ private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(EXTENSIONS).build(); - // - // /** * Returns the FileFilter. @@ -541,6 +539,12 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { addMatchingValues(classes, org, dependency.getVendorEvidence()); addMatchingValues(classes, org, dependency.getProductEvidence()); } + // org name + final String orgUrl = pom.getOrganizationUrl(); + if (orgUrl != null && !orgUrl.isEmpty()) { + dependency.getVendorEvidence().addEvidence("pom", "organization url", orgUrl, Confidence.MEDIUM); + dependency.getProductEvidence().addEvidence("pom", "organization url", orgUrl, Confidence.LOW); + } //pom name final String pomName = pom.getName(); if (pomName @@ -1110,6 +1114,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { * Stores information about a class name. */ protected static class ClassNameInformation { + /** * The fully qualified class name. */ @@ -1180,6 +1185,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { public void setName(String name) { this.name = name; } + /** * Get the value of packageStructure * diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/Model.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/Model.java index 0d6ac691e..132f10daf 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/Model.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/Model.java @@ -39,6 +39,10 @@ public class Model { * The organization name. */ private String organization; + /** + * The organization URL. + */ + private String organizationUrl; /** * The description. */ @@ -112,6 +116,24 @@ public class Model { this.organization = organization; } + /** + * Get the value of organizationUrl. + * + * @return the value of organizationUrl + */ + public String getOrganizationUrl() { + return organizationUrl; + } + + /** + * Set the value of organizationUrl. + * + * @param organizationUrl new value of organizationUrl + */ + public void setOrganizationUrl(String organizationUrl) { + this.organizationUrl = organizationUrl; + } + /** * Get the value of description. * diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomHandler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomHandler.java index 669ab9d0d..198ce2e12 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomHandler.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomHandler.java @@ -101,7 +101,7 @@ public class PomHandler extends DefaultHandler { * The current node text being extracted from the element. */ private StringBuilder currentText; - + /** * Handles the start element event. * @@ -132,48 +132,66 @@ public class PomHandler extends DefaultHandler { public void endElement(String uri, String localName, String qName) throws SAXException { stack.pop(); final String parentNode = stack.peek(); - if (PROJECT.equals(parentNode)) { - if (GROUPID.equals(qName)) { - model.setGroupId(currentText.toString()); - } else if (ARTIFACTID.equals(qName)) { - model.setArtifactId(currentText.toString()); - } else if (VERSION.equals(qName)) { - model.setVersion(currentText.toString()); - } else if (NAME.equals(qName)) { - model.setName(currentText.toString()); - } else if (ORGANIZATION.equals(qName)) { - model.setOrganization(currentText.toString()); - } else if (DESCRIPTION.equals(qName)) { - model.setDescription(currentText.toString()); - } else if (URL.equals(qName)) { - model.setProjectURL(currentText.toString()); - } - } else if (PARENT.equals(parentNode)) { - if (GROUPID.equals(qName)) { - model.setParentGroupId(currentText.toString()); - } else if (ARTIFACTID.equals(qName)) { - model.setParentArtifactId(currentText.toString()); - } else if (VERSION.equals(qName)) { - model.setParentVersion(currentText.toString()); - } - } else if (LICENSE.equals(parentNode)) { - if (license != null) { + if (null != parentNode) switch (parentNode) { + case PROJECT: + if (null != qName) switch (qName) { + case GROUPID: + model.setGroupId(currentText.toString()); + break; + case ARTIFACTID: + model.setArtifactId(currentText.toString()); + break; + case VERSION: + model.setVersion(currentText.toString()); + break; + case NAME: + model.setName(currentText.toString()); + break; + case DESCRIPTION: + model.setDescription(currentText.toString()); + break; + case URL: + model.setProjectURL(currentText.toString()); + break; + default: + break; + } break; + case ORGANIZATION: if (NAME.equals(qName)) { - license.setName(currentText.toString()); + model.setOrganization(currentText.toString()); } else if (URL.equals(qName)) { - license.setUrl(currentText.toString()); - } - //} else { - //TODO add error logging - } - } else if (LICENSES.equals(parentNode)) { - if (LICENSE.equals(qName)) { + model.setOrganizationUrl(currentText.toString()); + } break; + case PARENT: + if (null != qName) switch (qName) { + case GROUPID: + model.setParentGroupId(currentText.toString()); + break; + case ARTIFACTID: + model.setParentArtifactId(currentText.toString()); + break; + case VERSION: + model.setParentVersion(currentText.toString()); + break; + default: + break; + } break; + case LICENSE: if (license != null) { - model.addLicense(license); - //} else { - //TODO add error logging - } - } + if (NAME.equals(qName)) { + license.setName(currentText.toString()); + } else if (URL.equals(qName)) { + license.setUrl(currentText.toString()); + } + } break; + case LICENSES: + if (LICENSE.equals(qName)) { + if (license != null) { + model.addLicense(license); + } + } break; + default: + break; } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomUtils.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomUtils.java index 6f3aa4987..4a6d2e8fc 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomUtils.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomUtils.java @@ -47,7 +47,7 @@ public final class PomUtils { * Reads in the specified POM and converts it to a Model. * * @param file the pom.xml file - * @return returns a + * @return returns an object representation of the POM * @throws AnalysisException is thrown if there is an exception extracting * or parsing the POM {@link Model} object */ @@ -59,14 +59,12 @@ public final class PomUtils { throw new AnalysisException(String.format("Unable to parse pom '%s'", file.getPath())); } return model; + } catch (AnalysisException ex) { + throw ex; } catch (PomParseException ex) { LOGGER.warn("Unable to parse pom '{}'", file.getPath()); LOGGER.debug("", ex); throw new AnalysisException(ex); - } catch (IOException ex) { - LOGGER.warn("Unable to parse pom '{}'(IO Exception)", file.getPath()); - LOGGER.debug("", ex); - throw new AnalysisException(ex); } catch (Throwable ex) { LOGGER.warn("Unexpected error during parsing of the pom '{}'", file.getPath()); LOGGER.debug("", ex); @@ -79,7 +77,7 @@ public final class PomUtils { * * @param path the path to the pom.xml file within the jar file * @param jar the jar file to extract the pom from - * @return returns a + * @return returns an object representation of the POM * @throws AnalysisException is thrown if there is an exception extracting * or parsing the POM {@link Model} object */ @@ -93,6 +91,8 @@ public final class PomUtils { if (model == null) { throw new AnalysisException(String.format("Unable to parse pom '%s/%s'", jar.getName(), path)); } + } catch (AnalysisException ex) { + throw ex; } catch (SecurityException ex) { LOGGER.warn("Unable to parse pom '{}' in jar '{}'; invalid signature", path, jar.getName()); LOGGER.debug("", ex); diff --git a/dependency-check-core/src/main/resources/dependencycheck-base-suppression.xml b/dependency-check-core/src/main/resources/dependencycheck-base-suppression.xml index ddc239276..409bf11e6 100644 --- a/dependency-check-core/src/main/resources/dependencycheck-base-suppression.xml +++ b/dependency-check-core/src/main/resources/dependencycheck-base-suppression.xml @@ -507,12 +507,4 @@ ^io\.jsonwebtoken:jjwt:.*$ cpe:/a:sonatype:nexus - - - ^commons-validator:commons-validator:.*$ - cpe:/a:apache:http_server - cpe:/a:apache:apache_http_server - diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/pom/PomUtilsTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/pom/PomUtilsTest.java index f16c05724..3b5c285bf 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/pom/PomUtilsTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/pom/PomUtilsTest.java @@ -24,13 +24,17 @@ import static org.junit.Assert.*; import org.owasp.dependencycheck.BaseTest; /** + * Test the PomUtils object. * - * @author jeremy + * @author Jeremy Long */ public class PomUtilsTest extends BaseTest { /** * Test of readPom method, of class PomUtils. + * + * @throws java.lang.Exception thrown when the test fails due to an + * exception */ @Test public void testReadPom_File() throws Exception { @@ -38,7 +42,12 @@ public class PomUtilsTest extends BaseTest { String expResult = "Direct Web Remoting"; Model result = PomUtils.readPom(file); assertEquals(expResult, result.getName()); - + + expResult = "get ahead"; + assertEquals(expResult, result.getOrganization()); + expResult = "http://getahead.ltd.uk/dwr"; + assertEquals(expResult, result.getOrganizationUrl()); + file = BaseTest.getResourceAsFile(this, "jmockit-1.26.pom"); expResult = "Main"; result = PomUtils.readPom(file); From 1367be510cddde1353af0b503340b1a03efcbf88 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Tue, 21 Feb 2017 07:02:05 -0500 Subject: [PATCH 4/4] correct fix for issue #660; correctly handle organization from the pom --- dependency-check-core/src/test/resources/dwr-pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dependency-check-core/src/test/resources/dwr-pom.xml b/dependency-check-core/src/test/resources/dwr-pom.xml index 1306c1a9c..0c43f0e84 100644 --- a/dependency-check-core/src/test/resources/dwr-pom.xml +++ b/dependency-check-core/src/test/resources/dwr-pom.xml @@ -25,6 +25,11 @@ https://dwr.dev.java.net/servlets/SummarizeList?listName=announce + + + get ahead + http://getahead.ltd.uk/dwr + joe_walker