Compare commits

...

45 Commits

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

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

View File

@@ -21,7 +21,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.0</version> <version>1.2.1</version>
</parent> </parent>
<artifactId>dependency-check-ant</artifactId> <artifactId>dependency-check-ant</artifactId>

View File

@@ -866,7 +866,7 @@ public class DependencyCheckTask extends Task {
Engine engine = null; Engine engine = null;
try { try {
engine = new Engine(); engine = new Engine(DependencyCheckTask.class.getClassLoader());
for (Resource resource : path) { for (Resource resource : path) {
final FileProvider provider = resource.as(FileProvider.class); final FileProvider provider = resource.as(FileProvider.class);
@@ -912,7 +912,7 @@ public class DependencyCheckTask extends Task {
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); LOGGER.log(Level.FINE, "", ex);
} finally { } finally {
Settings.cleanup(); Settings.cleanup(true);
if (engine != null) { if (engine != null) {
engine.cleanup(); engine.cleanup();
} }

View File

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

View File

@@ -21,7 +21,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.0</version> <version>1.2.1</version>
</parent> </parent>
<artifactId>dependency-check-cli</artifactId> <artifactId>dependency-check-cli</artifactId>

View File

@@ -57,8 +57,13 @@ public class App {
* @param args the command line arguments * @param args the command line arguments
*/ */
public static void main(String[] args) { public static void main(String[] args) {
final App app = new App(); try {
app.run(args); Settings.initialize();
final App app = new App();
app.run(args);
} finally {
Settings.cleanup(true);
}
} }
/** /**
@@ -67,8 +72,8 @@ public class App {
* @param args the command line arguments * @param args the command line arguments
*/ */
public void run(String[] args) { public void run(String[] args) {
final CliParser cli = new CliParser(); final CliParser cli = new CliParser();
try { try {
cli.parse(args); cli.parse(args);
} catch (FileNotFoundException ex) { } catch (FileNotFoundException ex) {
@@ -140,7 +145,6 @@ public class App {
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); LOGGER.log(Level.FINE, "", ex);
} finally { } finally {
Settings.cleanup();
if (scanner != null) { if (scanner != null) {
scanner.cleanup(); scanner.cleanup();
} }
@@ -155,8 +159,6 @@ public class App {
*/ */
private void populateSettings(CliParser cli) { private void populateSettings(CliParser cli) {
Settings.initialize();
final boolean autoUpdate = cli.isAutoUpdate(); final boolean autoUpdate = cli.isAutoUpdate();
final String connectionTimeout = cli.getConnectionTimeout(); final String connectionTimeout = cli.getConnectionTimeout();
final String proxyUrl = cli.getProxyUrl(); final String proxyUrl = cli.getProxyUrl();

View File

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

View File

@@ -21,7 +21,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.0</version> <version>1.2.1</version>
</parent> </parent>
<artifactId>dependency-check-core</artifactId> <artifactId>dependency-check-core</artifactId>
@@ -662,11 +662,11 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
Additionally, these are only added when using "allTests" to Additionally, these are only added when using "allTests" to
make the build slightly faster in most cases. --> make the build slightly faster in most cases. -->
<id>False Positive Tests</id> <id>False Positive Tests</id>
<!--activation> <activation>
<property> <property>
<name>allTests</name> <name>allTests</name>
</property> </property>
</activation--> </activation>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.apache.xmlgraphics</groupId> <groupId>org.apache.xmlgraphics</groupId>
@@ -689,6 +689,34 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<scope>provided</scope> <scope>provided</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency>
<groupId>com.ganyo</groupId>
<artifactId>gcm-server</artifactId>
<version>1.0.2</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.7-b1</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-complete</artifactId>
<version>1.7.4</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby</artifactId>
<version>1.6.3</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
</dependencies> </dependencies>
</profile> </profile>
</profiles> </profiles>

View File

@@ -888,7 +888,7 @@ public class DependencyCheckScanAgent {
"Unable to connect to the dependency-check database; analysis has stopped"); "Unable to connect to the dependency-check database; analysis has stopped");
LOGGER.log(Level.FINE, "", ex); LOGGER.log(Level.FINE, "", ex);
} finally { } finally {
Settings.cleanup(); Settings.cleanup(true);
if (engine != null) { if (engine != null) {
engine.cleanup(); engine.cleanup();
} }

View File

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

View File

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

View File

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

View File

@@ -88,6 +88,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
removeBadMatches(dependency); removeBadMatches(dependency);
removeWrongVersionMatches(dependency); removeWrongVersionMatches(dependency);
removeSpuriousCPE(dependency); removeSpuriousCPE(dependency);
removeDuplicativeEntriesFromJar(dependency, engine);
addFalseNegativeCPEs(dependency); addFalseNegativeCPEs(dependency);
} }
@@ -181,27 +182,6 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
if (coreCPE.matches() && !coreFiles.matches()) { if (coreCPE.matches() && !coreFiles.matches()) {
itr.remove(); 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();
// }
} }
} }
@@ -248,16 +228,27 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
//TODO move this startsWith expression to a configuration file? //TODO move this startsWith expression to a configuration file?
if ("cpe".equals(i.getType())) { if ("cpe".equals(i.getType())) {
if ((i.getValue().matches(".*c\\+\\+.*") if ((i.getValue().matches(".*c\\+\\+.*")
|| i.getValue().startsWith("cpe:/a:jquery:jquery")
|| i.getValue().startsWith("cpe:/a:prototypejs:prototype")
|| i.getValue().startsWith("cpe:/a:yahoo:yui")
|| i.getValue().startsWith("cpe:/a:file:file") || i.getValue().startsWith("cpe:/a:file:file")
|| i.getValue().startsWith("cpe:/a:mozilla:mozilla") || i.getValue().startsWith("cpe:/a:mozilla:mozilla")
|| i.getValue().startsWith("cpe:/a:cvs:cvs") || i.getValue().startsWith("cpe:/a:cvs:cvs")
|| i.getValue().startsWith("cpe:/a:ftp:ftp") || i.getValue().startsWith("cpe:/a:ftp:ftp")
|| i.getValue().startsWith("cpe:/a:ssh:ssh")) || i.getValue().startsWith("cpe:/a:tcp:tcp")
|| i.getValue().startsWith("cpe:/a:ssh:ssh")
|| i.getValue().startsWith("cpe:/a:lookup:lookup"))
&& (dependency.getFileName().toLowerCase().endsWith(".jar") && (dependency.getFileName().toLowerCase().endsWith(".jar")
|| dependency.getFileName().toLowerCase().endsWith("pom.xml"))) { || dependency.getFileName().toLowerCase().endsWith("pom.xml")
|| dependency.getFileName().toLowerCase().endsWith(".dll")
|| dependency.getFileName().toLowerCase().endsWith(".exe")
|| dependency.getFileName().toLowerCase().endsWith(".nuspec")
|| dependency.getFileName().toLowerCase().endsWith(".nupkg"))) {
itr.remove();
} else if ((i.getValue().startsWith("cpe:/a:jquery:jquery")
|| i.getValue().startsWith("cpe:/a:prototypejs:prototype")
|| i.getValue().startsWith("cpe:/a:yahoo:yui"))
&& (dependency.getFileName().toLowerCase().endsWith(".jar")
|| dependency.getFileName().toLowerCase().endsWith("pom.xml")
|| dependency.getFileName().toLowerCase().endsWith(".dll")
|| dependency.getFileName().toLowerCase().endsWith(".exe"))) {
itr.remove(); itr.remove();
} else if (i.getValue().startsWith("cpe:/a:apache:maven") } else if (i.getValue().startsWith("cpe:/a:apache:maven")
&& !dependency.getFileName().toLowerCase().matches("maven-core-[\\d\\.]+\\.jar")) { && !dependency.getFileName().toLowerCase().matches("maven-core-[\\d\\.]+\\.jar")) {
@@ -266,7 +257,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
&& !dependency.getEvidenceUsed().containsUsedString("m-core")) { && !dependency.getEvidenceUsed().containsUsedString("m-core")) {
itr.remove(); itr.remove();
} else if (i.getValue().startsWith("cpe:/a:jboss:jboss") } else if (i.getValue().startsWith("cpe:/a:jboss:jboss")
&& !dependency.getFileName().toLowerCase().matches("jboss-[\\d\\.]+(GA)?\\.jar")) { && !dependency.getFileName().toLowerCase().matches("jboss-?[\\d\\.-]+(GA)?\\.jar")) {
itr.remove(); itr.remove();
} }
} }
@@ -314,6 +305,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
* @param dependency the dependency being analyzed * @param dependency the dependency being analyzed
*/ */
private void addFalseNegativeCPEs(Dependency dependency) { private void addFalseNegativeCPEs(Dependency dependency) {
//TODO move this to the hint analyzer
final Iterator<Identifier> itr = dependency.getIdentifiers().iterator(); final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
while (itr.hasNext()) { while (itr.hasNext()) {
final Identifier i = itr.next(); final Identifier i = itr.next();
@@ -329,20 +321,92 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
try { try {
dependency.addIdentifier("cpe", dependency.addIdentifier("cpe",
newCpe, newCpe,
String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(newCpe, "UTF-8"))); String.format(CPEAnalyzer.NVD_SEARCH_URL, URLEncoder.encode(newCpe, "UTF-8")));
dependency.addIdentifier("cpe", dependency.addIdentifier("cpe",
newCpe2, newCpe2,
String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(newCpe2, "UTF-8"))); String.format(CPEAnalyzer.NVD_SEARCH_URL, URLEncoder.encode(newCpe2, "UTF-8")));
dependency.addIdentifier("cpe", dependency.addIdentifier("cpe",
newCpe3, newCpe3,
String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(newCpe3, "UTF-8"))); String.format(CPEAnalyzer.NVD_SEARCH_URL, URLEncoder.encode(newCpe3, "UTF-8")));
dependency.addIdentifier("cpe", dependency.addIdentifier("cpe",
newCpe4, newCpe4,
String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(newCpe4, "UTF-8"))); String.format(CPEAnalyzer.NVD_SEARCH_URL, URLEncoder.encode(newCpe4, "UTF-8")));
} catch (UnsupportedEncodingException ex) { } catch (UnsupportedEncodingException ex) {
LOGGER.log(Level.FINE, null, ex); LOGGER.log(Level.FINE, null, ex);
} }
} }
} }
} }
/**
* Removes duplicate entries identified that are contained within JAR files. These occasionally crop up due to POM
* entries or other types of files (such as DLLs and EXEs) being contained within the JAR.
*
* @param dependency the dependency that might be a duplicate
* @param engine the engine used to scan all dependencies
*/
private void removeDuplicativeEntriesFromJar(Dependency dependency, Engine engine) {
if (dependency.getFileName().toLowerCase().endsWith("pom.xml")
|| "dll".equals(dependency.getFileExtension())
|| "exe".equals(dependency.getFileExtension())) {
String parentPath = dependency.getFilePath().toLowerCase();
if (parentPath.contains(".jar")) {
parentPath = parentPath.substring(0, parentPath.indexOf(".jar") + 4);
final Dependency parent = findDependency(parentPath, engine.getDependencies());
if (parent != null) {
boolean remove = false;
for (Identifier i : dependency.getIdentifiers()) {
if ("cpe".equals(i.getType())) {
final String trimmedCPE = trimCpeToVendor(i.getValue());
for (Identifier parentId : parent.getIdentifiers()) {
if ("cpe".equals(parentId.getType()) && parentId.getValue().startsWith(trimmedCPE)) {
remove |= true;
}
}
}
if (!remove) { //we can escape early
return;
}
}
if (remove) {
engine.getDependencies().remove(dependency);
}
}
}
}
}
/**
* Retrieves a given dependency, based on a given path, from a list of dependencies.
*
* @param dependencyPath the path of the dependency to return
* @param dependencies the collection of dependencies to search
* @return the dependency object for the given path, otherwise null
*/
private Dependency findDependency(String dependencyPath, List<Dependency> dependencies) {
for (Dependency d : dependencies) {
if (d.getFilePath().equalsIgnoreCase(dependencyPath)) {
return d;
}
}
return null;
}
/**
* Takes a full CPE and returns the CPE trimmed to include only vendor and product.
*
* @param value the CPE value to trim
* @return a CPE value that only includes the vendor and product
*/
private String trimCpeToVendor(String value) {
//cpe:/a:jruby:jruby:1.0.8
final int pos1 = value.indexOf(":", 7); //right of vendor
final int pos2 = value.indexOf(":", pos1 + 1); //right of product
if (pos2 < 0) {
return value;
} else {
return value.substring(0, pos2);
}
}
} }

View File

@@ -138,7 +138,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
"include-resource", "include-resource",
"embed-dependency", "embed-dependency",
"ipojo-components", "ipojo-components",
"ipojo-extension"); "ipojo-extension",
"eclipse-sourcereferences");
/** /**
* item in some manifest, should be considered medium confidence. * item in some manifest, should be considered medium confidence.
*/ */
@@ -690,7 +691,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
&& !dependency.getFileName().toLowerCase().endsWith("-javadoc.jar") && !dependency.getFileName().toLowerCase().endsWith("-javadoc.jar")
&& !dependency.getFileName().toLowerCase().endsWith("-src.jar") && !dependency.getFileName().toLowerCase().endsWith("-src.jar")
&& !dependency.getFileName().toLowerCase().endsWith("-doc.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.", String.format("Jar file '%s' does not contain a manifest.",
dependency.getFileName())); dependency.getFileName()));
} }
@@ -764,6 +765,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
&& !key.endsWith("class-path") && !key.endsWith("class-path")
&& !key.endsWith("-scm") //todo change this to a regex? && !key.endsWith("-scm") //todo change this to a regex?
&& !key.startsWith("scm-") && !key.startsWith("scm-")
&& !value.trim().startsWith("scm:")
&& !isImportPackage(key, value) && !isImportPackage(key, value)
&& !isPackage(key, value)) { && !isPackage(key, value)) {

View File

@@ -46,6 +46,7 @@ import org.owasp.dependencycheck.utils.Pair;
* @author Jeremy Long <jeremy.long@owasp.org> * @author Jeremy Long <jeremy.long@owasp.org>
*/ */
public class CveDB { public class CveDB {
/** /**
* The logger. * The logger.
*/ */
@@ -733,8 +734,10 @@ public class CveDB {
final boolean isStruts = "apache".equals(vendor) && "struts".equals(product); final boolean isStruts = "apache".equals(vendor) && "struts".equals(product);
final DependencyVersion v = parseDependencyVersion(cpeId); final DependencyVersion v = parseDependencyVersion(cpeId);
final boolean prevAffected = previous != null && !previous.isEmpty(); final boolean prevAffected = previous != null && !previous.isEmpty();
if (identifiedVersion == null || "-".equals(identifiedVersion.toString())) { if (v == null || "-".equals(v.toString())) { //all versions
if (v == null || "-".equals(v.toString())) { affected = true;
} else if (identifiedVersion == null || "-".equals(identifiedVersion.toString())) {
if (prevAffected) {
affected = true; affected = true;
} }
} else if (identifiedVersion.equals(v) || (prevAffected && identifiedVersion.compareTo(v) < 0)) { } else if (identifiedVersion.equals(v) || (prevAffected && identifiedVersion.compareTo(v) < 0)) {

View File

@@ -178,7 +178,9 @@ public class StandardUpdate {
if (maxUpdates >= 1) { //ensure the modified file date gets written (we may not have actually updated it) if (maxUpdates >= 1) { //ensure the modified file date gets written (we may not have actually updated it)
properties.save(updateable.get(MODIFIED)); properties.save(updateable.get(MODIFIED));
LOGGER.log(Level.INFO, "Begin database maintenance.");
cveDB.cleanupDatabase(); cveDB.cleanupDatabase();
LOGGER.log(Level.INFO, "End database maintenance.");
} }
} finally { } finally {
closeDataStores(); closeDataStores();

View File

@@ -203,7 +203,7 @@ public class CallableDownloadTask implements Callable<Future<ProcessTask>> {
LOGGER.log(Level.WARNING, msg); LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, "Download Task Failed", ex); LOGGER.log(Level.FINE, "Download Task Failed", ex);
} finally { } finally {
Settings.cleanup(); Settings.cleanup(false);
} }
return null; return null;
} }

View File

@@ -119,7 +119,7 @@ public class ProcessTask implements Callable<ProcessTask> {
} catch (UpdateException ex) { } catch (UpdateException ex) {
this.exception = ex; this.exception = ex;
} finally { } finally {
Settings.cleanup(); Settings.cleanup(false);
} }
return this; return this;
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -247,9 +247,11 @@ public final class Settings {
/** /**
* Cleans up resources to prevent memory leaks. * Cleans up resources to prevent memory leaks.
*
* @param deleteTemporary flag indicating whether any temporary directories generated should be removed
*/ */
public static void cleanup() { public static void cleanup(boolean deleteTemporary) {
if (tempDirectory != null && tempDirectory.exists()) { if (deleteTemporary && tempDirectory != null && tempDirectory.exists()) {
FileUtils.delete(tempDirectory); FileUtils.delete(tempDirectory);
} }
try { try {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -23,7 +23,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.0</version> <version>1.2.1</version>
</parent> </parent>
<artifactId>dependency-check-maven</artifactId> <artifactId>dependency-check-maven</artifactId>

View File

@@ -613,7 +613,8 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR
*/ */
private int writeSiteReportDependencyEvidenceUsed(Dependency d, int collapsibleHeaderCount, Sink sink) { private int writeSiteReportDependencyEvidenceUsed(Dependency d, int collapsibleHeaderCount, Sink sink) {
int cnt = collapsibleHeaderCount; int cnt = collapsibleHeaderCount;
if (d.getEvidenceUsed() != null && d.getEvidenceUsed().size() > 0) { final Set<Evidence> evidence = d.getEvidenceForDisplay();
if (evidence != null && evidence.size() > 0) {
cnt += 1; cnt += 1;
sink.sectionTitle4(); sink.sectionTitle4();
sink.rawText("Evidence Collected <a href=\"javascript:toggleElement(this, 'evidence" + cnt + "')\">[+]</a>"); sink.rawText("Evidence Collected <a href=\"javascript:toggleElement(this, 'evidence" + cnt + "')\">[+]</a>");
@@ -625,7 +626,7 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR
writeTableHeaderCell(sink, "Name"); writeTableHeaderCell(sink, "Name");
writeTableHeaderCell(sink, "Value"); writeTableHeaderCell(sink, "Value");
sink.tableRow_(); sink.tableRow_();
for (Evidence e : d.getEvidenceUsed()) { for (Evidence e : evidence) {
sink.tableRow(); sink.tableRow();
writeTableCell(sink, e.getSource()); writeTableCell(sink, e.getSource());
writeTableCell(sink, e.getName()); writeTableCell(sink, e.getName());
@@ -952,7 +953,7 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR
"Unable to connect to the dependency-check database; analysis has stopped"); "Unable to connect to the dependency-check database; analysis has stopped");
logger.log(Level.FINE, "", ex); logger.log(Level.FINE, "", ex);
} finally { } finally {
Settings.cleanup(); Settings.cleanup(true);
if (engine != null) { if (engine != null) {
engine.cleanup(); engine.cleanup();
} }
@@ -993,7 +994,7 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR
"Unable to connect to the dependency-check database; analysis has stopped"); "Unable to connect to the dependency-check database; analysis has stopped");
logger.log(Level.FINE, "", ex); logger.log(Level.FINE, "", ex);
} finally { } finally {
Settings.cleanup(); Settings.cleanup(true);
if (engine != null) { if (engine != null) {
engine.cleanup(); engine.cleanup();
} }

View File

@@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long
<groupId>org.owasp</groupId> <groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId> <artifactId>dependency-check-parent</artifactId>
<version>1.2.0</version> <version>1.2.1</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<modules> <modules>

File diff suppressed because one or more lines are too long