diff --git a/.gitignore b/.gitignore index 5fff7a394..b79573ae8 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ # Eclipse project files .classpath .project +.settings +maven-eclipse.xml +.externalToolBuilders # Netbeans configuration nb-configuration.xml /target/ diff --git a/dependency-check-core/pom.xml b/dependency-check-core/pom.xml index fc649713b..38f41f4b5 100644 --- a/dependency-check-core/pom.xml +++ b/dependency-check-core/pom.xml @@ -400,6 +400,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. 3.1 false + -Xlint:unchecked 1.6 1.6 diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java index 3dfb16489..e29454205 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java @@ -168,99 +168,133 @@ public class Engine implements Serializable { * Scans an array of files or directories. If a directory is specified, it will be scanned recursively. Any * dependencies identified are added to the dependency collection. * - * @since v0.3.2.5 + * @param paths an array of paths to files or directories to be analyzed + * @return the list of dependencies scanned * - * @param paths an array of paths to files or directories to be analyzed. + * @since v0.3.2.5 */ - public void scan(String[] paths) { + public List scan(String[] paths) { + List deps = new ArrayList(); for (String path : paths) { final File file = new File(path); - scan(file); + List d = scan(file); + if (d != null) { + deps.addAll(d); + } } + return deps; } /** * Scans a given file or directory. If a directory is specified, it will be scanned recursively. Any dependencies * identified are added to the dependency collection. * - * @param path the path to a file or directory to be analyzed. + * @param path the path to a file or directory to be analyzed + * @return the list of dependencies scanned */ - public void scan(String path) { + public List scan(String path) { if (path.matches("^.*[\\/]\\*\\.[^\\/:*|?<>\"]+$")) { final String[] parts = path.split("\\*\\."); final String[] ext = new String[]{parts[parts.length - 1]}; final File dir = new File(path.substring(0, path.length() - ext[0].length() - 2)); if (dir.isDirectory()) { final List files = (List) org.apache.commons.io.FileUtils.listFiles(dir, ext, true); - scan(files); + return scan(files); } else { final String msg = String.format("Invalid file path provided to scan '%s'", path); LOGGER.log(Level.SEVERE, msg); } } else { final File file = new File(path); - scan(file); + return scan(file); } + return null; } /** * Scans an array of files or directories. If a directory is specified, it will be scanned recursively. Any * dependencies identified are added to the dependency collection. * - * @since v0.3.2.5 - * * @param files an array of paths to files or directories to be analyzed. + * @return the list of dependencies + * + * @since v0.3.2.5 */ - public void scan(File[] files) { + public List scan(File[] files) { + List deps = new ArrayList(); for (File file : files) { - scan(file); + List d = scan(file); + if (d != null) { + deps.addAll(d); + } } + return deps; } /** * Scans a list of files or directories. If a directory is specified, it will be scanned recursively. Any * dependencies identified are added to the dependency collection. * - * @since v0.3.2.5 + * @param files a set of paths to files or directories to be analyzed + * @return the list of dependencies scanned * - * @param files a set of paths to files or directories to be analyzed. + * @since v0.3.2.5 */ - public void scan(Set files) { + public List scan(Set files) { + List deps = new ArrayList(); for (File file : files) { - scan(file); + List d = scan(file); + if (d != null) { + deps.addAll(d); + } } + return deps; } /** * Scans a list of files or directories. If a directory is specified, it will be scanned recursively. Any * dependencies identified are added to the dependency collection. * - * @since v0.3.2.5 + * @param files a set of paths to files or directories to be analyzed + * @return the list of dependencies scanned * - * @param files a set of paths to files or directories to be analyzed. + * @since v0.3.2.5 */ - public void scan(List files) { + public List scan(List files) { + List deps = new ArrayList(); for (File file : files) { - scan(file); + List d = scan(file); + if (d != null) { + deps.addAll(d); + } } + return deps; } /** * Scans a given file or directory. If a directory is specified, it will be scanned recursively. Any dependencies * identified are added to the dependency collection. * + * @param file the path to a file or directory to be analyzed + * @return the list of dependencies scanned + * * @since v0.3.2.4 * - * @param file the path to a file or directory to be analyzed. */ - public void scan(File file) { + public List scan(File file) { if (file.exists()) { if (file.isDirectory()) { - scanDirectory(file); + return scanDirectory(file); } else { - scanFile(file); + Dependency d = scanFile(file); + if (d != null) { + List deps = new ArrayList(); + deps.add(d); + return deps; + } } } + return null; } /** @@ -268,42 +302,50 @@ public class Engine implements Serializable { * * @param dir the directory to scan. */ - protected void scanDirectory(File dir) { + protected List scanDirectory(File dir) { final File[] files = dir.listFiles(); + List deps = new ArrayList(); if (files != null) { for (File f : files) { if (f.isDirectory()) { - scanDirectory(f); + List d = scanDirectory(f); + if (d != null) { + deps.addAll(d); + } } else { - scanFile(f); + Dependency d = scanFile(f); + deps.add(d); } } } + return deps; } /** * Scans a specified file. If a dependency is identified it is added to the dependency collection. * - * @param file The file to scan. + * @param file The file to scan + * @return the scanned dependency */ - protected void scanFile(File file) { + protected Dependency scanFile(File file) { if (!file.isFile()) { final String msg = String.format("Path passed to scanFile(File) is not a file: %s. Skipping the file.", file.toString()); LOGGER.log(Level.FINE, msg); - return; + return null; } final String fileName = file.getName(); final String extension = FileUtils.getFileExtension(fileName); + Dependency dependency = null; if (extension != null) { if (supportsExtension(extension)) { - final Dependency dependency = new Dependency(file); + dependency = new Dependency(file); dependencies.add(dependency); } } else { - final String msg = String.format("No file extension found on file '%s'. The file was not analyzed.", - file.toString()); + final String msg = String.format("No file extension found on file '%s'. The file was not analyzed.", file.toString()); LOGGER.log(Level.FINEST, msg); } + return dependency; } /** @@ -439,8 +481,7 @@ public class Engine implements Serializable { } catch (UpdateException ex) { LOGGER.log(Level.WARNING, "Unable to update Cached Web DataSource, using local data instead. Results may not include recent vulnerabilities."); - LOGGER.log(Level.FINE, - String.format("Unable to update details for %s", source.getClass().getName()), ex); + LOGGER.log(Level.FINE, String.format("Unable to update details for %s", source.getClass().getName()), ex); } } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java index 04f6626a4..d55017d31 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java @@ -110,7 +110,7 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer { static { final String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS); if (additionalZipExt != null) { - final HashSet ext = new HashSet(Arrays.asList(additionalZipExt)); + final HashSet ext = new HashSet(Arrays.asList(additionalZipExt)); ZIPPABLES.addAll(ext); } EXTENSIONS.addAll(ZIPPABLES); @@ -221,9 +221,8 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer { final String displayPath = String.format("%s%s", dependency.getFilePath(), d.getActualFilePath().substring(tmpDir.getAbsolutePath().length())); - final String displayName = String.format("%s[%s]", + final String displayName = String.format("%s: %s", dependency.getFileName(), - File.separator, d.getFileName()); d.setFilePath(displayPath); d.setFileName(displayName); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java index 97779a515..c75d428d2 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java @@ -188,7 +188,9 @@ public class CPEAnalyzer implements Analyzer { if (!vendors.isEmpty() && !products.isEmpty()) { final List entries = searchCPE(vendors, products, dependency.getProductEvidence().getWeighting(), dependency.getVendorEvidence().getWeighting()); - + if (entries == null) { + continue; + } boolean identifierAdded = false; for (IndexEntry e : entries) { if (verifyEntry(e, dependency)) { @@ -250,27 +252,24 @@ public class CPEAnalyzer implements Analyzer { * @param vendorWeightings a list of strings to use to add weighting factors to the vendor field * @param productWeightings Adds a list of strings that will be used to add weighting factors to the product search * @return a list of possible CPE values - * @throws CorruptIndexException when the Lucene index is corrupt - * @throws IOException when the Lucene index is not found - * @throws ParseException when the generated query is not valid */ protected List searchCPE(String vendor, String product, - Set vendorWeightings, Set productWeightings) - throws CorruptIndexException, IOException, ParseException { + Set vendorWeightings, Set productWeightings) { + final ArrayList ret = new ArrayList(MAX_QUERY_RESULTS); final String searchString = buildSearch(vendor, product, vendorWeightings, productWeightings); if (searchString == null) { return ret; } - - final TopDocs docs = cpe.search(searchString, MAX_QUERY_RESULTS); - for (ScoreDoc d : docs.scoreDocs) { - if (d.score >= 0.08) { - final Document doc = cpe.getDocument(d.doc); - final IndexEntry entry = new IndexEntry(); - entry.setVendor(doc.get(Fields.VENDOR)); - entry.setProduct(doc.get(Fields.PRODUCT)); + try { + final TopDocs docs = cpe.search(searchString, MAX_QUERY_RESULTS); + for (ScoreDoc d : docs.scoreDocs) { + if (d.score >= 0.08) { + final Document doc = cpe.getDocument(d.doc); + final IndexEntry entry = new IndexEntry(); + entry.setVendor(doc.get(Fields.VENDOR)); + entry.setProduct(doc.get(Fields.PRODUCT)); // if (d.score < 0.08) { // System.out.print(entry.getVendor()); // System.out.print(":"); @@ -278,13 +277,25 @@ public class CPEAnalyzer implements Analyzer { // System.out.print(":"); // System.out.println(d.score); // } - entry.setSearchScore(d.score); - if (!ret.contains(entry)) { - ret.add(entry); + entry.setSearchScore(d.score); + if (!ret.contains(entry)) { + ret.add(entry); + } } } + return ret; + } catch (ParseException ex) { + final String msg = String.format("Unable to parse: %s", searchString); + Logger.getLogger(CPEAnalyzer.class.getName()).log(Level.WARNING, + "An error occured querying the CPE data. See the log for more details."); + Logger.getLogger(CPEAnalyzer.class.getName()).log(Level.INFO, msg, ex); + } catch (IOException ex) { + final String msg = String.format("IO Error with search string: %s", searchString); + Logger.getLogger(CPEAnalyzer.class.getName()).log(Level.WARNING, + "An error occured reading CPE data. See the log for more details."); + Logger.getLogger(CPEAnalyzer.class.getName()).log(Level.INFO, msg, ex); } - return ret; + return null; } /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.java index e4bc0a6b1..8910f704d 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.java @@ -73,7 +73,7 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer { public void analyze(Dependency dependency, Engine engine) throws AnalysisException { //strip any path information that may get added by ArchiveAnalyzer, etc. - final File f = new File(dependency.getFileName()); + final File f = dependency.getActualFile(); String fileName = f.getName(); //remove file extension 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 ba0ea23f6..10ae90ad7 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 @@ -327,11 +327,11 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { final String displayPath = String.format("%s%s%s", dependency.getFilePath(), File.separator, - path); //.replaceAll("[\\/]", File.separator)); + path); final String displayName = String.format("%s%s%s", dependency.getFileName(), File.separator, - path); //.replaceAll("[\\/]", File.separator)); + path); newDependency.setFileName(displayName); newDependency.setFilePath(displayPath); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java index dbee6a5d7..1a21ba2b0 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java @@ -24,13 +24,13 @@ import java.net.URL; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; + import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.data.nexus.MavenArtifact; import org.owasp.dependencycheck.data.nexus.NexusSearch; import org.owasp.dependencycheck.dependency.Confidence; import org.owasp.dependencycheck.dependency.Dependency; -import org.owasp.dependencycheck.dependency.Identifier; import org.owasp.dependencycheck.utils.Settings; /** @@ -152,29 +152,7 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer { public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException { try { final MavenArtifact ma = searcher.searchSha1(dependency.getSha1sum()); - if (ma.getGroupId() != null && !"".equals(ma.getGroupId())) { - dependency.getVendorEvidence().addEvidence("nexus", "groupid", ma.getGroupId(), Confidence.HIGH); - } - if (ma.getArtifactId() != null && !"".equals(ma.getArtifactId())) { - dependency.getProductEvidence().addEvidence("nexus", "artifactid", ma.getArtifactId(), Confidence.HIGH); - } - if (ma.getVersion() != null && !"".equals(ma.getVersion())) { - dependency.getVersionEvidence().addEvidence("nexus", "version", ma.getVersion(), Confidence.HIGH); - } - if (ma.getArtifactUrl() != null && !"".equals(ma.getArtifactUrl())) { - boolean found = false; - for (Identifier i : dependency.getIdentifiers()) { - if ("maven".equals(i.getType()) && i.getValue().equals(ma.toString())) { - found = true; - i.setConfidence(Confidence.HIGHEST); - i.setUrl(ma.getArtifactUrl()); - break; - } - } - if (!found) { - dependency.addIdentifier("maven", ma.toString(), ma.getArtifactUrl(), Confidence.HIGHEST); - } - } + dependency.addAsEvidence("nexus", ma, Confidence.HIGH); } catch (IllegalArgumentException iae) { //dependency.addAnalysisException(new AnalysisException("Invalid SHA-1")); LOGGER.info(String.format("invalid sha-1 hash on %s", dependency.getFileName())); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cwe/CweDB.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cwe/CweDB.java index ce2410ec5..5e81ea4fa 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cwe/CweDB.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cwe/CweDB.java @@ -29,10 +29,12 @@ import java.util.logging.Logger; * @author Jeremy Long */ public final class CweDB { + /** * The Logger. */ private static final Logger LOGGER = Logger.getLogger(CweDB.class.getName()); + /** * Empty private constructor as this is a utility class. */ @@ -55,7 +57,9 @@ public final class CweDB { final String filePath = "data/cwe.hashmap.serialized"; final InputStream input = CweDB.class.getClassLoader().getResourceAsStream(filePath); oin = new ObjectInputStream(input); - return (HashMap) oin.readObject(); + @SuppressWarnings("unchecked") + HashMap ret = (HashMap) oin.readObject(); + return ret; } catch (ClassNotFoundException ex) { LOGGER.log(Level.WARNING, "Unable to load CWE data. This should not be an issue."); LOGGER.log(Level.FINE, null, ex); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Dependency.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Dependency.java index 7ba9c5224..ef1117148 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Dependency.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Dependency.java @@ -26,6 +26,7 @@ import java.util.SortedSet; import java.util.TreeSet; import java.util.logging.Level; import java.util.logging.Logger; +import org.owasp.dependencycheck.data.nexus.MavenArtifact; import org.owasp.dependencycheck.utils.Checksum; import org.owasp.dependencycheck.utils.FileUtils; @@ -316,6 +317,39 @@ public class Dependency implements Serializable, Comparable { this.identifiers.add(i); } + /** + * Adds the maven artifact as evidence. + * + * @param source The source of the evidence + * @param mavenArtifact The maven artifact + * @param confidence The confidence level of this evidence + */ + public void addAsEvidence(String source, MavenArtifact mavenArtifact, Confidence confidence) { + if (mavenArtifact.getGroupId() != null && !mavenArtifact.getGroupId().isEmpty()) { + this.getVendorEvidence().addEvidence(source, "groupid", mavenArtifact.getGroupId(), confidence); + } + if (mavenArtifact.getArtifactId() != null && !mavenArtifact.getArtifactId().isEmpty()) { + this.getProductEvidence().addEvidence(source, "artifactid", mavenArtifact.getArtifactId(), confidence); + } + if (mavenArtifact.getVersion() != null && !mavenArtifact.getVersion().isEmpty()) { + this.getVersionEvidence().addEvidence(source, "version", mavenArtifact.getVersion(), confidence); + } + if (mavenArtifact.getArtifactUrl() != null && !mavenArtifact.getArtifactUrl().isEmpty()) { + boolean found = false; + for (Identifier i : this.getIdentifiers()) { + if ("maven".equals(i.getType()) && i.getValue().equals(mavenArtifact.toString())) { + found = true; + i.setConfidence(Confidence.HIGHEST); + i.setUrl(mavenArtifact.getArtifactUrl()); + break; + } + } + if (!found) { + this.addIdentifier("maven", mavenArtifact.toString(), mavenArtifact.getArtifactUrl(), Confidence.HIGHEST); + } + } + } + /** * Adds an entry to the list of detected Identifiers for the dependency file. * @@ -324,6 +358,7 @@ public class Dependency implements Serializable, Comparable { public void addIdentifier(Identifier identifier) { this.identifiers.add(identifier); } + /** * A set of identifiers that have been suppressed. */ @@ -441,6 +476,7 @@ public class Dependency implements Serializable, Comparable { public EvidenceCollection getVersionEvidence() { return this.versionEvidence; } + /** * The description of the JAR file. */ @@ -463,6 +499,7 @@ public class Dependency implements Serializable, Comparable { public void setDescription(String description) { this.description = description; } + /** * The license that this dependency uses. */ @@ -485,6 +522,7 @@ public class Dependency implements Serializable, Comparable { public void setLicense(String license) { this.license = license; } + /** * A list of vulnerabilities for this dependency. */ @@ -540,6 +578,7 @@ public class Dependency implements Serializable, Comparable { public void addVulnerability(Vulnerability vulnerability) { this.vulnerabilities.add(vulnerability); } + /** * A collection of related dependencies. */ diff --git a/dependency-check-core/src/main/resources/templates/HtmlReport.vsl b/dependency-check-core/src/main/resources/templates/HtmlReport.vsl index 6c6d88120..54d88da56 100644 --- a/dependency-check-core/src/main/resources/templates/HtmlReport.vsl +++ b/dependency-check-core/src/main/resources/templates/HtmlReport.vsl @@ -906,6 +906,6 @@ arising out of or in connection with the use of this tool, the analysis performe ## END SUPPRESSED VULNERABILITIES -


This report contains data retrieved from the National Vulnerability Database.
+


This report contains data retrieved from the National Vulnerability Database.
diff --git a/dependency-check-core/src/main/resources/templates/VulnerabilityReport.vsl b/dependency-check-core/src/main/resources/templates/VulnerabilityReport.vsl index 44ee05e77..9070cc7a8 100644 --- a/dependency-check-core/src/main/resources/templates/VulnerabilityReport.vsl +++ b/dependency-check-core/src/main/resources/templates/VulnerabilityReport.vsl @@ -236,6 +236,6 @@ arising out of or in connection with the use of this tool, the analysis performe -



This report contains data retrieved from the National Vulnerability Database.

+



This report contains data retrieved from the National Vulnerability Database.

diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIntegrationTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIntegrationTest.java index c986ae487..9d660d43e 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIntegrationTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIntegrationTest.java @@ -17,7 +17,9 @@ */ package org.owasp.dependencycheck; +import java.util.List; import org.junit.After; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Before; import org.junit.Test; @@ -54,8 +56,8 @@ public class EngineIntegrationTest extends BaseTest { Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false); Engine instance = new Engine(); Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); - instance.scan(testClasses); - assertTrue(instance.getDependencies().size() > 0); + List deps = instance.scan(testClasses); + assertFalse(deps.isEmpty()); for (Dependency d : instance.getDependencies()) { assertTrue("non-zip file collected " + d.getFileName(), d.getFileName().toLowerCase().endsWith(".zip")); } @@ -81,8 +83,7 @@ public class EngineIntegrationTest extends BaseTest { cveDB.open(); DatabaseProperties dbProp = cveDB.getDatabaseProperties(); cveDB.close(); - ReportGenerator rg = new ReportGenerator("DependencyCheck", - instance.getDependencies(), instance.getAnalyzers(), dbProp); + ReportGenerator rg = new ReportGenerator("DependencyCheck", instance.getDependencies(), instance.getAnalyzers(), dbProp); rg.generateReports("./target/", "ALL"); instance.cleanup(); } diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/dependency/DependencyTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/dependency/DependencyTest.java index 8062ddb11..a3062ac0a 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/dependency/DependencyTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/dependency/DependencyTest.java @@ -23,10 +23,12 @@ import java.util.Set; import org.junit.After; import org.junit.AfterClass; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.owasp.dependencycheck.data.nexus.MavenArtifact; /** * @@ -152,7 +154,7 @@ public class DependencyTest { public void testGetMd5sum() { File file = new File(this.getClass().getClassLoader().getResource("struts2-core-2.1.2.jar").getPath()); Dependency instance = new Dependency(file); -// assertEquals("89CE9E36AA9A9E03F1450936D2F4F8DD0F961F8B", result.getSha1sum()); + //assertEquals("89CE9E36AA9A9E03F1450936D2F4F8DD0F961F8B", result.getSha1sum()); String expResult = "C30B57142E1CCBC1EFD5CD15F307358F"; String result = instance.getMd5sum(); assertEquals(expResult, result); @@ -294,4 +296,34 @@ public class DependencyTest { EvidenceCollection result = instance.getVersionEvidence(); assertTrue(true); //this is just a getter setter pair. } + + /** + * Test of addAsEvidence method, of class Dependency. + */ + @Test + public void testAddAsEvidence() { + Dependency instance = new Dependency(); + MavenArtifact mavenArtifact = new MavenArtifact("group", "artifact", "version", "url"); + instance.addAsEvidence("pom", mavenArtifact, Confidence.HIGH); + assertTrue(instance.getEvidence().contains(Confidence.HIGH)); + assertFalse(instance.getEvidence().getEvidence("pom", "groupid").isEmpty()); + assertFalse(instance.getEvidence().getEvidence("pom", "artifactid").isEmpty()); + assertFalse(instance.getEvidence().getEvidence("pom", "version").isEmpty()); + assertFalse(instance.getIdentifiers().isEmpty()); + } + + /** + * Test of addAsEvidence method, of class Dependency. + */ + @Test + public void testAddAsEvidenceWithEmptyArtefact() { + Dependency instance = new Dependency(); + MavenArtifact mavenArtifact = new MavenArtifact(null, null, null, null); + instance.addAsEvidence("pom", mavenArtifact, Confidence.HIGH); + assertFalse(instance.getEvidence().contains(Confidence.HIGH)); + assertTrue(instance.getEvidence().getEvidence("pom", "groupid").isEmpty()); + assertTrue(instance.getEvidence().getEvidence("pom", "artifactid").isEmpty()); + assertTrue(instance.getEvidence().getEvidence("pom", "version").isEmpty()); + assertTrue(instance.getIdentifiers().isEmpty()); + } } diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/DependencyCheckMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/DependencyCheckMojo.java index 26b9ef4c5..f6ad5082e 100644 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/DependencyCheckMojo.java +++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/DependencyCheckMojo.java @@ -46,7 +46,9 @@ import org.apache.maven.settings.Proxy; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; +import org.owasp.dependencycheck.data.nexus.MavenArtifact; import org.owasp.dependencycheck.data.nvdcve.DatabaseException; +import org.owasp.dependencycheck.dependency.Confidence; import org.owasp.dependencycheck.dependency.Dependency; import org.owasp.dependencycheck.dependency.Identifier; import org.owasp.dependencycheck.dependency.Vulnerability; @@ -58,9 +60,7 @@ import org.owasp.dependencycheck.utils.Settings; * * @author Jeremy Long */ -@Mojo(name = "check", defaultPhase = LifecyclePhase.COMPILE, threadSafe = true, - requiresDependencyResolution = ResolutionScope.RUNTIME_PLUS_SYSTEM, - requiresOnline = true) +@Mojo(name = "check", defaultPhase = LifecyclePhase.COMPILE, threadSafe = true, requiresDependencyResolution = ResolutionScope.RUNTIME_PLUS_SYSTEM, requiresOnline = true) public class DependencyCheckMojo extends ReportAggregationMojo { // @@ -292,6 +292,7 @@ public class DependencyCheckMojo extends ReportAggregationMojo { @Parameter(property = "externalReport") @Deprecated private String externalReport = null; + // /** * Constructs a new dependency-check-mojo. @@ -326,8 +327,20 @@ public class DependencyCheckMojo extends ReportAggregationMojo { if (excludeFromScan(a)) { continue; } - - localEngine.scan(a.getFile().getAbsolutePath()); + List deps = localEngine.scan(a.getFile().getAbsoluteFile()); + if (deps != null) { + if (deps.size() == 1) { + Dependency d = deps.get(0); + if (d != null) { + MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion()); + d.addAsEvidence("pom", ma, Confidence.HIGHEST); + } + } else { + final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'", + a.getGroupId(), a.getArtifactId(), a.getVersion()); + LOGGER.info(msg); + } + } } localEngine.analyzeDependencies(); @@ -396,8 +409,7 @@ public class DependencyCheckMojo extends ReportAggregationMojo { } if (proxyUrl != null && !proxyUrl.isEmpty()) { - LOGGER.warning("Deprecated configuration detected, proxyUrl will be ignored; use the maven settings " - + "to configure the proxy instead"); + LOGGER.warning("Deprecated configuration detected, proxyUrl will be ignored; use the maven settings " + "to configure the proxy instead"); } final Proxy proxy = getMavenProxy(); if (proxy != null) { @@ -510,8 +522,8 @@ public class DependencyCheckMojo extends ReportAggregationMojo { } return null; } - // + // /** * Executes the dependency-check and generates the report. * @@ -530,8 +542,7 @@ public class DependencyCheckMojo extends ReportAggregationMojo { checkForFailure(engine.getDependencies()); } } catch (DatabaseException ex) { - LOGGER.log(Level.SEVERE, - "Unable to connect to the dependency-check database; analysis has stopped"); + LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped"); LOGGER.log(Level.FINE, "", ex); } } @@ -580,16 +591,15 @@ public class DependencyCheckMojo extends ReportAggregationMojo { engine = initializeEngine(); engine.getDependencies().addAll(deps); } catch (DatabaseException ex) { - final String msg = String.format("An unrecoverable exception with the dependency-check initialization occured while scanning %s", - getProject().getName()); + final String msg = String.format("An unrecoverable exception with the dependency-check initialization occured while scanning %s", getProject() + .getName()); throw new MavenReportException(msg, ex); } } else { try { engine = executeDependencyCheck(); } catch (DatabaseException ex) { - final String msg = String.format("An unrecoverable exception with the dependency-check scan occured while scanning %s", - getProject().getName()); + final String msg = String.format("An unrecoverable exception with the dependency-check scan occured while scanning %s", getProject().getName()); throw new MavenReportException(msg, ex); } } @@ -612,8 +622,7 @@ public class DependencyCheckMojo extends ReportAggregationMojo { try { engine = executeDependencyCheck(project); } catch (DatabaseException ex) { - final String msg = String.format("An unrecoverable exception with the dependency-check scan occured while scanning %s", - project.getName()); + final String msg = String.format("An unrecoverable exception with the dependency-check scan occured while scanning %s", project.getName()); throw new MavenReportException(msg, ex); } } @@ -646,8 +655,7 @@ public class DependencyCheckMojo extends ReportAggregationMojo { * @return the output name */ public String getOutputName() { - if ("HTML".equalsIgnoreCase(this.format) - || "ALL".equalsIgnoreCase(this.format)) { + if ("HTML".equalsIgnoreCase(this.format) || "ALL".equalsIgnoreCase(this.format)) { return "dependency-check-report"; } else if ("XML".equalsIgnoreCase(this.format)) { return "dependency-check-report.xml#"; @@ -685,8 +693,7 @@ public class DependencyCheckMojo extends ReportAggregationMojo { * @return the description */ public String getDescription(Locale locale) { - return "A report providing details on any published " - + "vulnerabilities within project dependencies. This report is a best effort but may contain " + return "A report providing details on any published " + "vulnerabilities within project dependencies. This report is a best effort but may contain " + "false positives and false negatives."; } @@ -740,8 +747,8 @@ public class DependencyCheckMojo extends ReportAggregationMojo { protected boolean canGenerateAggregateReport() { return isAggregate() && isLastProject(); } - // + // // /** * Checks to see if a vulnerability has been identified with a CVSS score that is above the threshold set in the @@ -807,14 +814,13 @@ public class DependencyCheckMojo extends ReportAggregationMojo { } } if (summary.length() > 0) { - final String msg = String.format("%n%n" - + "One or more dependencies were identified with known vulnerabilities:%n%n%s" + final String msg = String.format("%n%n" + "One or more dependencies were identified with known vulnerabilities:%n%n%s" + "%n%nSee the dependency-check report for more details.%n%n", summary.toString()); LOGGER.log(Level.WARNING, msg); } } - // + // // /** * Writes the scan data to disk. This is used to serialize the scan data between the "check" and "aggregate" phase.