diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.java index c882c7f10..4ddba2ce8 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.java @@ -88,6 +88,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer { removeBadMatches(dependency); removeWrongVersionMatches(dependency); removeSpuriousCPE(dependency); + removeDuplicativePOMEntries(dependency, engine); addFalseNegativeCPEs(dependency); } @@ -181,27 +182,6 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer { if (coreCPE.matches() && !coreFiles.matches()) { itr.remove(); } - - //replaced with the regex above. - // if (("cpe:/a:sun:java".equals(i.getValue()) - // || "cpe:/a:oracle:java".equals(i.getValue()) - // || "cpe:/a:ibm:java".equals(i.getValue()) - // || "cpe:/a:sun:j2se".equals(i.getValue()) - // || "cpe:/a:oracle:j2se".equals(i.getValue()) - // || i.getValue().startsWith("cpe:/a:sun:java:") - // || i.getValue().startsWith("cpe:/a:sun:j2se:") - // || i.getValue().startsWith("cpe:/a:sun:java:jre") - // || i.getValue().startsWith("cpe:/a:sun:java:jdk") - // || i.getValue().startsWith("cpe:/a:sun:java_se") - // || i.getValue().startsWith("cpe:/a:oracle:java_se") - // || i.getValue().startsWith("cpe:/a:oracle:java:") - // || i.getValue().startsWith("cpe:/a:oracle:j2se:") - // || i.getValue().startsWith("cpe:/a:oracle:jre") - // || i.getValue().startsWith("cpe:/a:oracle:jdk") - // || i.getValue().startsWith("cpe:/a:ibm:java:")) - // && !dependency.getFileName().toLowerCase().endsWith("rt.jar")) { - // itr.remove(); - // } } } @@ -253,7 +233,8 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer { || i.getValue().startsWith("cpe:/a:cvs:cvs") || i.getValue().startsWith("cpe:/a:ftp:ftp") || i.getValue().startsWith("cpe:/a:tcp:tcp") - || i.getValue().startsWith("cpe:/a:ssh:ssh")) + || i.getValue().startsWith("cpe:/a:ssh:ssh") + || i.getValue().startsWith("cpe:/a:lookup:lookup")) && (dependency.getFileName().toLowerCase().endsWith(".jar") || dependency.getFileName().toLowerCase().endsWith("pom.xml") || dependency.getFileName().toLowerCase().endsWith(".dll") @@ -324,6 +305,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer { * @param dependency the dependency being analyzed */ private void addFalseNegativeCPEs(Dependency dependency) { + //TODO move this to the hint analyzer final Iterator itr = dependency.getIdentifiers().iterator(); while (itr.hasNext()) { final Identifier i = itr.next(); @@ -356,4 +338,54 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer { } } + private void removeDuplicativePOMEntries(Dependency dependency, Engine engine) { + if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) { + String parentPath = dependency.getFilePath().toLowerCase(); + if (parentPath.contains(".jar")) { + parentPath = parentPath.substring(0, parentPath.indexOf(".jar") + 4); + Dependency parent = findDependency(parentPath, engine.getDependencies()); + if (parent != null) { + boolean remove = false; + for (Identifier i : dependency.getIdentifiers()) { + if ("cpe".equals(i.getType())) { + String trimmedCPE = trimCpeToVendor(i.getValue()); + for (Identifier parentId : parent.getIdentifiers()) { + if ("cpe".equals(parentId.getType()) && parentId.getValue().startsWith(trimmedCPE)) { + remove |= true; + } + } + } + if (remove == false) { + return; + } + } + if (remove) { + engine.getDependencies().remove(dependency); + } + } + } + + } + } + + private Dependency findDependency(String parentPath, List dependencies) { + for (Dependency d : dependencies) { + if (d.getFilePath().equalsIgnoreCase(parentPath)) { + return d; + } + } + return null; + } + + private String trimCpeToVendor(String value) { + //cpe:/a:jruby:jruby:1.0.8 + int pos1 = value.indexOf(":", 7); //right of vendor + int pos2 = value.indexOf(":", pos1 + 1); //right of product + if (pos2 < 0) { + return value; + } else { + return value.substring(0, pos2 - 1); + } + + } } 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 51df832cc..4cdeec00d 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 @@ -690,7 +690,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { && !dependency.getFileName().toLowerCase().endsWith("-javadoc.jar") && !dependency.getFileName().toLowerCase().endsWith("-src.jar") && !dependency.getFileName().toLowerCase().endsWith("-doc.jar")) { - LOGGER.log(Level.INFO, + LOGGER.log(Level.FINE, String.format("Jar file '%s' does not contain a manifest.", dependency.getFileName())); } diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzerTest.java index 011b963ef..c43e64120 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzerTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzerTest.java @@ -56,6 +56,7 @@ public class FalsePositiveAnalyzerTest { public void testAnalyze() throws Exception { Dependency dependency = new Dependency(); dependency.setFileName("pom.xml"); + dependency.setFilePath("pom.xml"); dependency.addIdentifier("cpe", "cpe:/a:file:file:1.2.1", "http://some.org/url"); Engine engine = null; FalsePositiveAnalyzer instance = new FalsePositiveAnalyzer(); diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzerIntegrationTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzerIntegrationTest.java index 73e23294d..6ae7ace04 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzerIntegrationTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzerIntegrationTest.java @@ -69,14 +69,18 @@ public class VulnerabilitySuppressionAnalyzerIntegrationTest extends AbstractDat engine.scan(file); engine.analyzeDependencies(); Dependency dependency = getDependency(engine, file); - assertTrue(dependency.getVulnerabilities().size() > 0); - assertTrue(dependency.getIdentifiers().size() > 0); + int cveSize = dependency.getVulnerabilities().size(); + int cpeSize = dependency.getIdentifiers().size(); + assertTrue(cveSize > 0); + assertTrue(cpeSize > 0); Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppression.getAbsolutePath()); VulnerabilitySuppressionAnalyzer instance = new VulnerabilitySuppressionAnalyzer(); instance.initialize(); instance.analyze(dependency, engine); - assertTrue(dependency.getVulnerabilities().size() == 0); - assertTrue(dependency.getIdentifiers().isEmpty()); + cveSize = cveSize > 1 ? cveSize - 2 : 0; + cpeSize = cpeSize > 0 ? cpeSize - 1 : 0; + assertTrue(dependency.getVulnerabilities().size() == cveSize); + assertTrue(dependency.getIdentifiers().size() == cpeSize); engine.cleanup(); }