mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-01-15 08:13:43 +01:00
Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5574f1c24f | ||
|
|
9457744571 | ||
|
|
19243c479c | ||
|
|
e868ce8328 | ||
|
|
ffa846c05a | ||
|
|
dde1791476 | ||
|
|
45438a7f06 | ||
|
|
c980e77ea3 | ||
|
|
176d3ddefa | ||
|
|
98d783d448 | ||
|
|
bcd6634d8a | ||
|
|
0b260cef2a | ||
|
|
6a68abbd67 | ||
|
|
9fcf23c802 | ||
|
|
5c2c08e051 | ||
|
|
1f254997e1 | ||
|
|
4f95af0864 | ||
|
|
6ff39be9d2 | ||
|
|
6cf5a47971 | ||
|
|
56da53c700 | ||
|
|
7091e10795 | ||
|
|
34765c5741 | ||
|
|
36c139872a | ||
|
|
1e77cec677 | ||
|
|
e95e3fb2d0 | ||
|
|
39c2234e38 | ||
|
|
f4fff5d9cb | ||
|
|
659785f972 | ||
|
|
85c04f6e3e | ||
|
|
bef117cbe8 | ||
|
|
46dd7cf86e | ||
|
|
9ed5a97267 | ||
|
|
cc2da70db2 | ||
|
|
cedd93e774 | ||
|
|
632e1692eb | ||
|
|
4861592d2a | ||
|
|
22e6d4edf3 | ||
|
|
e9bd7ff72f | ||
|
|
e7228fb489 | ||
|
|
96c03a68f2 | ||
|
|
4f6f248421 | ||
|
|
a8f14c86fd | ||
|
|
36de3d1e25 | ||
|
|
48bc4570e1 | ||
|
|
94b272dbae | ||
|
|
c093edf459 | ||
|
|
0164feffcc | ||
|
|
8cd377b99f | ||
|
|
74282c8ac5 | ||
|
|
d2158e5e44 | ||
|
|
9ea16ad1d1 | ||
|
|
45941adb71 | ||
|
|
c4d662fd2b | ||
|
|
d9ce3cda66 | ||
|
|
6bd7d6b078 | ||
|
|
84c6dd5dfa | ||
|
|
71e7412f15 | ||
|
|
2fa8507d69 | ||
|
|
00d4ee47de | ||
|
|
413c71eb0a | ||
|
|
2b761279e4 | ||
|
|
1e7bbfa7c1 | ||
|
|
dc7245ff6e | ||
|
|
ffaf7b40e9 | ||
|
|
99355d993a | ||
|
|
d25f6e813c | ||
|
|
043f8e0523 | ||
|
|
5fcf2a2623 | ||
|
|
f1422adf75 | ||
|
|
c2b1742582 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -26,4 +26,5 @@ _site/**
|
|||||||
.LCKpom.xml~
|
.LCKpom.xml~
|
||||||
#coverity
|
#coverity
|
||||||
/cov-int/
|
/cov-int/
|
||||||
/dependency-check-core/nbproject/
|
/dependency-check-core/nbproject/
|
||||||
|
cov-scan.bat
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
[](https://travis-ci.org/jeremylong/DependencyCheck) [](https://www.apache.org/licenses/LICENSE-2.0.txt)
|
[](https://travis-ci.org/jeremylong/DependencyCheck) [](https://www.apache.org/licenses/LICENSE-2.0.txt) [](https://scan.coverity.com/projects/dependencycheck)
|
||||||
|
|
||||||
Dependency-Check
|
Dependency-Check
|
||||||
================
|
================
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,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.4.1</version>
|
<version>1.4.3</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>dependency-check-ant</artifactId>
|
<artifactId>dependency-check-ant</artifactId>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp</groupId>
|
<groupId>org.owasp</groupId>
|
||||||
<artifactId>dependency-check-parent</artifactId>
|
<artifactId>dependency-check-parent</artifactId>
|
||||||
<version>1.4.1</version>
|
<version>1.4.3</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>dependency-check-cli</artifactId>
|
<artifactId>dependency-check-cli</artifactId>
|
||||||
|
|||||||
@@ -158,8 +158,13 @@ public class App {
|
|||||||
exitCode = -4;
|
exitCode = -4;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getProjectName(), cli.getScanFiles(),
|
final String[] scanFiles = cli.getScanFiles();
|
||||||
cli.getExcludeList(), cli.getSymLinkDepth());
|
if (scanFiles != null) {
|
||||||
|
runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getProjectName(), scanFiles,
|
||||||
|
cli.getExcludeList(), cli.getSymLinkDepth());
|
||||||
|
} else {
|
||||||
|
LOGGER.error("No scan files configured");
|
||||||
|
}
|
||||||
} catch (InvalidScanPathException ex) {
|
} catch (InvalidScanPathException ex) {
|
||||||
LOGGER.error("An invalid scan path was detected; unable to scan '//*' paths");
|
LOGGER.error("An invalid scan path was detected; unable to scan '//*' paths");
|
||||||
exitCode = -10;
|
exitCode = -10;
|
||||||
@@ -293,7 +298,7 @@ public class App {
|
|||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (exCol != null && exCol.getExceptions().size()>0) {
|
if (exCol != null && exCol.getExceptions().size() > 0) {
|
||||||
throw exCol;
|
throw exCol;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -301,7 +306,7 @@ public class App {
|
|||||||
engine.cleanup();
|
engine.cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -196,6 +196,10 @@ public final class CliParser {
|
|||||||
isValid = false;
|
isValid = false;
|
||||||
final String msg = String.format("Invalid '%s' argument: '%s'%nUnable to scan paths that start with '//'.", argumentName, path);
|
final String msg = String.format("Invalid '%s' argument: '%s'%nUnable to scan paths that start with '//'.", argumentName, path);
|
||||||
throw new FileNotFoundException(msg);
|
throw new FileNotFoundException(msg);
|
||||||
|
} else if ((path.endsWith("/*") && !path.endsWith("**/*")) || (path.endsWith("\\*") && path.endsWith("**\\*"))) {
|
||||||
|
final String msg = String.format("Possibly incorrect path '%s' from argument '%s' because it ends with a slash star; "
|
||||||
|
+ "dependency-check uses ant-style paths", path, argumentName);
|
||||||
|
LOGGER.warn(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -966,7 +970,7 @@ public final class CliParser {
|
|||||||
*/
|
*/
|
||||||
public void printVersionInfo() {
|
public void printVersionInfo() {
|
||||||
final String version = String.format("%s version %s",
|
final String version = String.format("%s version %s",
|
||||||
Settings.getString(Settings.KEYS.APPLICATION_VAME, "dependency-check"),
|
Settings.getString(Settings.KEYS.APPLICATION_NAME, "dependency-check"),
|
||||||
Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
|
Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
|
||||||
System.out.println(version);
|
System.out.println(version);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp</groupId>
|
<groupId>org.owasp</groupId>
|
||||||
<artifactId>dependency-check-parent</artifactId>
|
<artifactId>dependency-check-parent</artifactId>
|
||||||
<version>1.4.1</version>
|
<version>1.4.3</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>dependency-check-core</artifactId>
|
<artifactId>dependency-check-core</artifactId>
|
||||||
|
|||||||
@@ -368,7 +368,7 @@ public class Engine implements FileFilter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.debug("\n----------------------------------------------------\nBEGIN ANALYSIS\n----------------------------------------------------");
|
LOGGER.debug("\n----------------------------------------------------\nBEGIN ANALYSIS\n----------------------------------------------------");
|
||||||
LOGGER.info("Analysis Starting");
|
LOGGER.info("Analysis Started");
|
||||||
final long analysisStart = System.currentTimeMillis();
|
final long analysisStart = System.currentTimeMillis();
|
||||||
|
|
||||||
// analysis phases
|
// analysis phases
|
||||||
|
|||||||
@@ -130,15 +130,26 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
file = new File(suppressionFilePath);
|
file = new File(suppressionFilePath);
|
||||||
|
InputStream suppressionsFromClasspath = null;
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
final InputStream suppressionsFromClasspath = this.getClass().getClassLoader().getResourceAsStream(suppressionFilePath);
|
try {
|
||||||
if (suppressionsFromClasspath != null) {
|
suppressionsFromClasspath = this.getClass().getClassLoader().getResourceAsStream(suppressionFilePath);
|
||||||
deleteTempFile = true;
|
if (suppressionsFromClasspath != null) {
|
||||||
file = FileUtils.getTempFile("suppression", "xml");
|
deleteTempFile = true;
|
||||||
try {
|
file = FileUtils.getTempFile("suppression", "xml");
|
||||||
org.apache.commons.io.FileUtils.copyInputStreamToFile(suppressionsFromClasspath, file);
|
try {
|
||||||
} catch (IOException ex) {
|
org.apache.commons.io.FileUtils.copyInputStreamToFile(suppressionsFromClasspath, file);
|
||||||
throwSuppressionParseException("Unable to locate suppressions file in classpath", ex);
|
} catch (IOException ex) {
|
||||||
|
throwSuppressionParseException("Unable to locate suppressions file in classpath", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (suppressionsFromClasspath != null) {
|
||||||
|
try {
|
||||||
|
suppressionsFromClasspath.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.debug("Failed to close stream", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -357,6 +357,12 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
*/
|
*/
|
||||||
private void extractFiles(File archive, File destination, Engine engine) throws AnalysisException {
|
private void extractFiles(File archive, File destination, Engine engine) throws AnalysisException {
|
||||||
if (archive != null && destination != null) {
|
if (archive != null && destination != null) {
|
||||||
|
String archiveExt = FileUtils.getFileExtension(archive.getName());
|
||||||
|
if (archiveExt == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
archiveExt = archiveExt.toLowerCase();
|
||||||
|
|
||||||
FileInputStream fis;
|
FileInputStream fis;
|
||||||
try {
|
try {
|
||||||
fis = new FileInputStream(archive);
|
fis = new FileInputStream(archive);
|
||||||
@@ -364,7 +370,6 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
LOGGER.debug("", ex);
|
LOGGER.debug("", ex);
|
||||||
throw new AnalysisException("Archive file was not found.", ex);
|
throw new AnalysisException("Archive file was not found.", ex);
|
||||||
}
|
}
|
||||||
final String archiveExt = FileUtils.getFileExtension(archive.getName()).toLowerCase();
|
|
||||||
try {
|
try {
|
||||||
if (ZIPPABLES.contains(archiveExt)) {
|
if (ZIPPABLES.contains(archiveExt)) {
|
||||||
final BufferedInputStream in = new BufferedInputStream(fis);
|
final BufferedInputStream in = new BufferedInputStream(fis);
|
||||||
@@ -414,8 +419,9 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
if ("jar".equals(archiveExt) && in.markSupported()) {
|
if ("jar".equals(archiveExt) && in.markSupported()) {
|
||||||
in.mark(7);
|
in.mark(7);
|
||||||
final byte[] b = new byte[7];
|
final byte[] b = new byte[7];
|
||||||
in.read(b);
|
final int read = in.read(b);
|
||||||
if (b[0] == '#'
|
if (read == 7
|
||||||
|
&& b[0] == '#'
|
||||||
&& b[1] == '!'
|
&& b[1] == '!'
|
||||||
&& b[2] == '/'
|
&& b[2] == '/'
|
||||||
&& b[3] == 'b'
|
&& b[3] == 'b'
|
||||||
@@ -441,6 +447,8 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
in.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import org.owasp.dependencycheck.exception.InitializationException;
|
import org.owasp.dependencycheck.exception.InitializationException;
|
||||||
|
import org.apache.commons.lang3.SystemUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Analyzer for getting company, product, and version information from a .NET
|
* Analyzer for getting company, product, and version information from a .NET
|
||||||
@@ -85,18 +86,19 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
*
|
*
|
||||||
* @return the list of arguments to begin populating the ProcessBuilder
|
* @return the list of arguments to begin populating the ProcessBuilder
|
||||||
*/
|
*/
|
||||||
private List<String> buildArgumentList() {
|
protected List<String> buildArgumentList() {
|
||||||
// Use file.separator as a wild guess as to whether this is Windows
|
// Use file.separator as a wild guess as to whether this is Windows
|
||||||
final List<String> args = new ArrayList<String>();
|
final List<String> args = new ArrayList<String>();
|
||||||
if (!"\\".equals(System.getProperty("file.separator"))) {
|
if (!SystemUtils.IS_OS_WINDOWS) {
|
||||||
if (Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH) != null) {
|
if (Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH) != null) {
|
||||||
args.add(Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH));
|
args.add(Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH));
|
||||||
} else {
|
} else if (isInPath("mono")) {
|
||||||
args.add("mono");
|
args.add("mono");
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args.add(grokAssemblyExe.getPath());
|
args.add(grokAssemblyExe.getPath());
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,6 +118,10 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final List<String> args = buildArgumentList();
|
final List<String> args = buildArgumentList();
|
||||||
|
if (args == null) {
|
||||||
|
LOGGER.warn("Assembly Analyzer was unable to execute");
|
||||||
|
return;
|
||||||
|
}
|
||||||
args.add(dependency.getActualFilePath());
|
args.add(dependency.getActualFilePath());
|
||||||
final ProcessBuilder pb = new ProcessBuilder(args);
|
final ProcessBuilder pb = new ProcessBuilder(args);
|
||||||
Document doc = null;
|
Document doc = null;
|
||||||
@@ -203,8 +209,6 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
IOUtils.copy(is, fos);
|
IOUtils.copy(is, fos);
|
||||||
|
|
||||||
grokAssemblyExe = tempFile;
|
grokAssemblyExe = tempFile;
|
||||||
// Set the temp file to get deleted when we're done
|
|
||||||
grokAssemblyExe.deleteOnExit();
|
|
||||||
LOGGER.debug("Extracted GrokAssembly.exe to {}", grokAssemblyExe.getPath());
|
LOGGER.debug("Extracted GrokAssembly.exe to {}", grokAssemblyExe.getPath());
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
this.setEnabled(false);
|
this.setEnabled(false);
|
||||||
@@ -229,6 +233,22 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
|
|
||||||
// Now, need to see if GrokAssembly actually runs from this location.
|
// Now, need to see if GrokAssembly actually runs from this location.
|
||||||
final List<String> args = buildArgumentList();
|
final List<String> args = buildArgumentList();
|
||||||
|
//TODO this creaes an "unreported" error - if someone doesn't look
|
||||||
|
// at the command output this could easily be missed (especially in an
|
||||||
|
// Ant or Mmaven build.
|
||||||
|
//
|
||||||
|
// We need to create a non-fatal warning error type that will
|
||||||
|
// get added to the report.
|
||||||
|
//TOOD this idea needs to get replicated to the bundle audit analyzer.
|
||||||
|
if (args == null) {
|
||||||
|
setEnabled(false);
|
||||||
|
LOGGER.error("----------------------------------------------------");
|
||||||
|
LOGGER.error(".NET Assembly Analyzer could not be initialized and at least one "
|
||||||
|
+ "'exe' or 'dll' was scanned. The 'mono' executale could not be found on "
|
||||||
|
+ "the path; either disable the Assembly Analyzer or configure the path mono.");
|
||||||
|
LOGGER.error("----------------------------------------------------");
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
final ProcessBuilder pb = new ProcessBuilder(args);
|
final ProcessBuilder pb = new ProcessBuilder(args);
|
||||||
final Process p = pb.start();
|
final Process p = pb.start();
|
||||||
@@ -246,6 +266,7 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
throw new InitializationException("Could not execute .NET AssemblyAnalyzer");
|
throw new InitializationException("Could not execute .NET AssemblyAnalyzer");
|
||||||
}
|
}
|
||||||
} catch (InitializationException e) {
|
} catch (InitializationException e) {
|
||||||
|
setEnabled(false);
|
||||||
throw e;
|
throw e;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer;\n"
|
LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer;\n"
|
||||||
@@ -272,10 +293,12 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
super.close();
|
super.close();
|
||||||
try {
|
try {
|
||||||
if (grokAssemblyExe != null && !grokAssemblyExe.delete()) {
|
if (grokAssemblyExe != null && !grokAssemblyExe.delete()) {
|
||||||
|
LOGGER.debug("Unable to delete temporary GrokAssembly.exe; attempting delete on exit");
|
||||||
grokAssemblyExe.deleteOnExit();
|
grokAssemblyExe.deleteOnExit();
|
||||||
}
|
}
|
||||||
} catch (SecurityException se) {
|
} catch (SecurityException se) {
|
||||||
LOGGER.debug("Can't delete temporary GrokAssembly.exe");
|
LOGGER.debug("Can't delete temporary GrokAssembly.exe");
|
||||||
|
grokAssemblyExe.deleteOnExit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,4 +343,29 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
protected String getAnalyzerEnabledSettingKey() {
|
protected String getAnalyzerEnabledSettingKey() {
|
||||||
return Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED;
|
return Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests to see if a file is in the system path. <b>Note</b> - the current
|
||||||
|
* implementation only works on non-windows platforms. For purposes of the
|
||||||
|
* AssemblyAnalyzer this is okay as this is only needed on Mac/*nix.
|
||||||
|
*
|
||||||
|
* @param file the executable to look for
|
||||||
|
* @return <code>true</code> if the file exists; otherwise
|
||||||
|
* <code>false</code>
|
||||||
|
*/
|
||||||
|
private boolean isInPath(String file) {
|
||||||
|
final ProcessBuilder pb = new ProcessBuilder("which", file);
|
||||||
|
try {
|
||||||
|
final Process proc = pb.start();
|
||||||
|
final int retCode = proc.waitFor();
|
||||||
|
if (retCode == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.debug("Path seach failed for " + file);
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
LOGGER.debug("Path seach failed for " + file);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -196,6 +196,9 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
* @param engine the dependency-check engine
|
* @param engine the dependency-check engine
|
||||||
* @param contents the version information
|
* @param contents the version information
|
||||||
*/
|
*/
|
||||||
|
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
|
||||||
|
value = "DM_DEFAULT_ENCODING",
|
||||||
|
justification = "Default encoding is only used if UTF-8 is not available")
|
||||||
private void analyzeSetVersionCommand(Dependency dependency, Engine engine, String contents) {
|
private void analyzeSetVersionCommand(Dependency dependency, Engine engine, String contents) {
|
||||||
Dependency currentDep = dependency;
|
Dependency currentDep = dependency;
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||||
import org.apache.lucene.document.Document;
|
import org.apache.lucene.document.Document;
|
||||||
import org.apache.lucene.index.CorruptIndexException;
|
import org.apache.lucene.index.CorruptIndexException;
|
||||||
import org.apache.lucene.queryparser.classic.ParseException;
|
import org.apache.lucene.queryparser.classic.ParseException;
|
||||||
@@ -550,7 +551,7 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>();
|
final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>();
|
||||||
|
|
||||||
//TODO the following algorithm incorrectly identifies things as a lower version
|
//TODO the following algorithm incorrectly identifies things as a lower version
|
||||||
// if there lower confidence evidence when the current (highest) version number
|
// if there lower confidence evidence when the current (highest) version number
|
||||||
// is newer then anything in the NVD.
|
// is newer then anything in the NVD.
|
||||||
for (Confidence conf : Confidence.values()) {
|
for (Confidence conf : Confidence.values()) {
|
||||||
for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) {
|
for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) {
|
||||||
@@ -801,6 +802,12 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(IdentifierMatch o) {
|
public int compareTo(IdentifierMatch o) {
|
||||||
|
return new CompareToBuilder()
|
||||||
|
.append(confidence, o.confidence)
|
||||||
|
.append(evidenceConfidence, o.evidenceConfidence)
|
||||||
|
.append(identifier, o.identifier)
|
||||||
|
.toComparison();
|
||||||
|
/*
|
||||||
int conf = this.confidence.compareTo(o.confidence);
|
int conf = this.confidence.compareTo(o.confidence);
|
||||||
if (conf == 0) {
|
if (conf == 0) {
|
||||||
conf = this.evidenceConfidence.compareTo(o.evidenceConfidence);
|
conf = this.evidenceConfidence.compareTo(o.evidenceConfidence);
|
||||||
@@ -809,6 +816,7 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return conf;
|
return conf;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -229,7 +229,8 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
LOGGER.warn("Unable to download pom.xml for {} from Central; "
|
LOGGER.warn("Unable to download pom.xml for {} from Central; "
|
||||||
+ "this could result in undetected CPE/CVEs.", dependency.getFileName());
|
+ "this could result in undetected CPE/CVEs.", dependency.getFileName());
|
||||||
} finally {
|
} finally {
|
||||||
if (pomFile != null && !FileUtils.deleteQuietly(pomFile)) {
|
if (pomFile != null && pomFile.exists() && !FileUtils.deleteQuietly(pomFile)) {
|
||||||
|
LOGGER.debug("Failed to delete temporary pom file {}", pomFile.toString());
|
||||||
pomFile.deleteOnExit();
|
pomFile.deleteOnExit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,205 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-core.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 IBM Corporation. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.analyzer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileFilter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.owasp.dependencycheck.Engine;
|
||||||
|
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||||
|
import org.owasp.dependencycheck.dependency.Confidence;
|
||||||
|
import org.owasp.dependencycheck.dependency.Dependency;
|
||||||
|
import org.owasp.dependencycheck.dependency.EvidenceCollection;
|
||||||
|
import org.owasp.dependencycheck.utils.FileFilterBuilder;
|
||||||
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This analyzer is used to analyze SWIFT and Objective-C packages by collecting
|
||||||
|
* information from .podspec files. CocoaPods dependency manager see
|
||||||
|
* https://cocoapods.org/.
|
||||||
|
*
|
||||||
|
* @author Bianca Jiang (https://twitter.com/biancajiang)
|
||||||
|
*/
|
||||||
|
@Experimental
|
||||||
|
public class CocoaPodsAnalyzer extends AbstractFileTypeAnalyzer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logger.
|
||||||
|
*/
|
||||||
|
// private static final Logger LOGGER = LoggerFactory.getLogger(CocoaPodsAnalyzer.class);
|
||||||
|
/**
|
||||||
|
* The name of the analyzer.
|
||||||
|
*/
|
||||||
|
private static final String ANALYZER_NAME = "CocoaPods Package Analyzer";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The phase that this analyzer is intended to run in.
|
||||||
|
*/
|
||||||
|
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The file name to scan.
|
||||||
|
*/
|
||||||
|
public static final String PODSPEC = "podspec";
|
||||||
|
/**
|
||||||
|
* Filter that detects files named "*.podspec".
|
||||||
|
*/
|
||||||
|
private static final FileFilter PODSPEC_FILTER = FileFilterBuilder.newInstance().addExtensions(PODSPEC).build();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The capture group #1 is the block variable. e.g. "Pod::Spec.new do
|
||||||
|
* |spec|"
|
||||||
|
*/
|
||||||
|
private static final Pattern PODSPEC_BLOCK_PATTERN = Pattern.compile("Pod::Spec\\.new\\s+?do\\s+?\\|(.+?)\\|");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the FileFilter
|
||||||
|
*
|
||||||
|
* @return the FileFilter
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected FileFilter getFileFilter() {
|
||||||
|
return PODSPEC_FILTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initializeFileTypeAnalyzer() {
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the analyzer.
|
||||||
|
*
|
||||||
|
* @return the name of the analyzer.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return ANALYZER_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the phase that the analyzer is intended to run in.
|
||||||
|
*
|
||||||
|
* @return the phase that the analyzer is intended to run in.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AnalysisPhase getAnalysisPhase() {
|
||||||
|
return ANALYSIS_PHASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the key used in the properties file to reference the analyzer's
|
||||||
|
* enabled property.
|
||||||
|
*
|
||||||
|
* @return the analyzer's enabled property setting key
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String getAnalyzerEnabledSettingKey() {
|
||||||
|
return Settings.KEYS.ANALYZER_COCOAPODS_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void analyzeFileType(Dependency dependency, Engine engine)
|
||||||
|
throws AnalysisException {
|
||||||
|
|
||||||
|
String contents;
|
||||||
|
try {
|
||||||
|
contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new AnalysisException(
|
||||||
|
"Problem occurred while reading dependency file.", e);
|
||||||
|
}
|
||||||
|
final Matcher matcher = PODSPEC_BLOCK_PATTERN.matcher(contents);
|
||||||
|
if (matcher.find()) {
|
||||||
|
contents = contents.substring(matcher.end());
|
||||||
|
final String blockVariable = matcher.group(1);
|
||||||
|
|
||||||
|
final EvidenceCollection vendor = dependency.getVendorEvidence();
|
||||||
|
final EvidenceCollection product = dependency.getProductEvidence();
|
||||||
|
final EvidenceCollection version = dependency.getVersionEvidence();
|
||||||
|
|
||||||
|
final String name = addStringEvidence(product, contents, blockVariable, "name", "name", Confidence.HIGHEST);
|
||||||
|
if (!name.isEmpty()) {
|
||||||
|
vendor.addEvidence(PODSPEC, "name_project", name, Confidence.HIGHEST);
|
||||||
|
}
|
||||||
|
addStringEvidence(product, contents, blockVariable, "summary", "summary", Confidence.HIGHEST);
|
||||||
|
|
||||||
|
addStringEvidence(vendor, contents, blockVariable, "author", "authors?", Confidence.HIGHEST);
|
||||||
|
addStringEvidence(vendor, contents, blockVariable, "homepage", "homepage", Confidence.HIGHEST);
|
||||||
|
addStringEvidence(vendor, contents, blockVariable, "license", "licen[cs]es?", Confidence.HIGHEST);
|
||||||
|
|
||||||
|
addStringEvidence(version, contents, blockVariable, "version", "version", Confidence.HIGHEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
setPackagePath(dependency);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts evidence from the contents and adds it to the given evidence
|
||||||
|
* collection.
|
||||||
|
*
|
||||||
|
* @param evidences the evidence collection to update
|
||||||
|
* @param contents the text to extract evidence from
|
||||||
|
* @param blockVariable the block variable within the content to search for
|
||||||
|
* @param field the name of the field being searched for
|
||||||
|
* @param fieldPattern the field pattern within the contents to search for
|
||||||
|
* @param confidence the confidence level of the evidence if found
|
||||||
|
* @return the string that was added as evidence
|
||||||
|
*/
|
||||||
|
private String addStringEvidence(EvidenceCollection evidences, String contents,
|
||||||
|
String blockVariable, String field, String fieldPattern, Confidence confidence) {
|
||||||
|
String value = "";
|
||||||
|
|
||||||
|
//capture array value between [ ]
|
||||||
|
final Matcher arrayMatcher = Pattern.compile(
|
||||||
|
String.format("\\s*?%s\\.%s\\s*?=\\s*?\\{\\s*?(.*?)\\s*?\\}", blockVariable, fieldPattern),
|
||||||
|
Pattern.CASE_INSENSITIVE).matcher(contents);
|
||||||
|
if (arrayMatcher.find()) {
|
||||||
|
value = arrayMatcher.group(1);
|
||||||
|
} else { //capture single value between quotes
|
||||||
|
final Matcher matcher = Pattern.compile(
|
||||||
|
String.format("\\s*?%s\\.%s\\s*?=\\s*?(['\"])(.*?)\\1", blockVariable, fieldPattern),
|
||||||
|
Pattern.CASE_INSENSITIVE).matcher(contents);
|
||||||
|
if (matcher.find()) {
|
||||||
|
value = matcher.group(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (value.length() > 0) {
|
||||||
|
evidences.addEvidence(PODSPEC, field, value, confidence);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the package path on the given dependency.
|
||||||
|
*
|
||||||
|
* @param dep the dependency to update
|
||||||
|
*/
|
||||||
|
private void setPackagePath(Dependency dep) {
|
||||||
|
final File file = new File(dep.getFilePath());
|
||||||
|
final String parent = file.getParent();
|
||||||
|
if (parent != null) {
|
||||||
|
dep.setPackagePath(parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -117,6 +117,7 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|
|||||||
final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex());
|
final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex());
|
||||||
while (subIterator.hasNext()) {
|
while (subIterator.hasNext()) {
|
||||||
final Dependency nextDependency = subIterator.next();
|
final Dependency nextDependency = subIterator.next();
|
||||||
|
Dependency main = null;
|
||||||
if (hashesMatch(dependency, nextDependency) && !containedInWar(dependency.getFilePath())
|
if (hashesMatch(dependency, nextDependency) && !containedInWar(dependency.getFilePath())
|
||||||
&& !containedInWar(nextDependency.getFilePath())) {
|
&& !containedInWar(nextDependency.getFilePath())) {
|
||||||
if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) {
|
if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) {
|
||||||
@@ -143,8 +144,14 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|
|||||||
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
||||||
break; //since we merged into the next dependency - skip forward to the next in mainIterator
|
break; //since we merged into the next dependency - skip forward to the next in mainIterator
|
||||||
}
|
}
|
||||||
} else if (isSameRubyGem(dependency, nextDependency)) {
|
} else if ((main = getMainGemspecDependency(dependency, nextDependency)) != null) {
|
||||||
final Dependency main = getMainGemspecDependency(dependency, nextDependency);
|
if (main == dependency) {
|
||||||
|
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
||||||
|
} else {
|
||||||
|
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
||||||
|
break; //since we merged into the next dependency - skip forward to the next in mainIterator
|
||||||
|
}
|
||||||
|
} else if ((main = getMainSwiftDependency(dependency, nextDependency)) != null) {
|
||||||
if (main == dependency) {
|
if (main == dependency) {
|
||||||
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
||||||
} else {
|
} else {
|
||||||
@@ -302,10 +309,13 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|
|||||||
String right = rFile.getParent();
|
String right = rFile.getParent();
|
||||||
if (left == null) {
|
if (left == null) {
|
||||||
return right == null;
|
return right == null;
|
||||||
|
} else if (right == null) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
if (left.equalsIgnoreCase(right)) {
|
if (left.equalsIgnoreCase(right)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left.matches(".*[/\\\\]repository[/\\\\].*") && right.matches(".*[/\\\\]repository[/\\\\].*")) {
|
if (left.matches(".*[/\\\\]repository[/\\\\].*") && right.matches(".*[/\\\\]repository[/\\\\].*")) {
|
||||||
left = getBaseRepoPath(left);
|
left = getBaseRepoPath(left);
|
||||||
right = getBaseRepoPath(right);
|
right = getBaseRepoPath(right);
|
||||||
@@ -376,6 +386,49 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bundling same swift dependencies with the same packagePath but identified
|
||||||
|
* by different analyzers.
|
||||||
|
*
|
||||||
|
* @param dependency1 dependency to test
|
||||||
|
* @param dependency2 dependency to test
|
||||||
|
* @return <code>true</code> if the dependencies appear to be the same;
|
||||||
|
* otherwise <code>false</code>
|
||||||
|
*/
|
||||||
|
private boolean isSameSwiftPackage(Dependency dependency1, Dependency dependency2) {
|
||||||
|
if (dependency1 == null || dependency2 == null
|
||||||
|
|| (!dependency1.getFileName().endsWith(".podspec")
|
||||||
|
&& !dependency1.getFileName().equals("Package.swift"))
|
||||||
|
|| (!dependency2.getFileName().endsWith(".podspec")
|
||||||
|
&& !dependency2.getFileName().equals("Package.swift"))
|
||||||
|
|| dependency1.getPackagePath() == null
|
||||||
|
|| dependency2.getPackagePath() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines which of the swift dependencies should be considered the
|
||||||
|
* primary.
|
||||||
|
*
|
||||||
|
* @param dependency1 the first swift dependency to compare
|
||||||
|
* @param dependency2 the second swift dependency to compare
|
||||||
|
* @return the primary swift dependency
|
||||||
|
*/
|
||||||
|
private Dependency getMainSwiftDependency(Dependency dependency1, Dependency dependency2) {
|
||||||
|
if (isSameSwiftPackage(dependency1, dependency2)) {
|
||||||
|
if (dependency1.getFileName().endsWith(".podspec")) {
|
||||||
|
return dependency1;
|
||||||
|
}
|
||||||
|
return dependency2;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is likely a very broken attempt at determining if the 'left'
|
* This is likely a very broken attempt at determining if the 'left'
|
||||||
* dependency is the 'core' library in comparison to the 'right' library.
|
* dependency is the 'core' library in comparison to the 'right' library.
|
||||||
|
|||||||
@@ -70,11 +70,12 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer {
|
|||||||
/**
|
/**
|
||||||
* Python init files
|
* Python init files
|
||||||
*/
|
*/
|
||||||
|
//CSOFF: WhitespaceAfter
|
||||||
private static final NameFileFilter IGNORED_FILES = new NameFileFilter(new String[]{
|
private static final NameFileFilter IGNORED_FILES = new NameFileFilter(new String[]{
|
||||||
"__init__.py",
|
"__init__.py",
|
||||||
"__init__.pyc",
|
"__init__.pyc",
|
||||||
"__init__.pyo",
|
"__init__.pyo",});
|
||||||
});
|
//CSON: WhitespaceAfter
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collects information about the file name.
|
* Collects information about the file name.
|
||||||
@@ -93,26 +94,27 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer {
|
|||||||
|
|
||||||
//add version evidence
|
//add version evidence
|
||||||
final DependencyVersion version = DependencyVersionUtil.parseVersion(fileName);
|
final DependencyVersion version = DependencyVersionUtil.parseVersion(fileName);
|
||||||
|
final String packageName = DependencyVersionUtil.parsePreVersion(fileName);
|
||||||
if (version != null) {
|
if (version != null) {
|
||||||
// If the version number is just a number like 2 or 23, reduce the confidence
|
// If the version number is just a number like 2 or 23, reduce the confidence
|
||||||
// a shade. This should hopefully correct for cases like log4j.jar or
|
// a shade. This should hopefully correct for cases like log4j.jar or
|
||||||
// struts2-core.jar
|
// struts2-core.jar
|
||||||
if (version.getVersionParts() == null || version.getVersionParts().size() < 2) {
|
if (version.getVersionParts() == null || version.getVersionParts().size() < 2) {
|
||||||
dependency.getVersionEvidence().addEvidence("file", "name",
|
dependency.getVersionEvidence().addEvidence("file", "version",
|
||||||
version.toString(), Confidence.MEDIUM);
|
version.toString(), Confidence.MEDIUM);
|
||||||
} else {
|
} else {
|
||||||
dependency.getVersionEvidence().addEvidence("file", "version",
|
dependency.getVersionEvidence().addEvidence("file", "version",
|
||||||
version.toString(), Confidence.HIGHEST);
|
version.toString(), Confidence.HIGHEST);
|
||||||
}
|
}
|
||||||
dependency.getVersionEvidence().addEvidence("file", "name",
|
dependency.getVersionEvidence().addEvidence("file", "name",
|
||||||
fileName, Confidence.MEDIUM);
|
packageName, Confidence.MEDIUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IGNORED_FILES.accept(f)) {
|
if (!IGNORED_FILES.accept(f)) {
|
||||||
dependency.getProductEvidence().addEvidence("file", "name",
|
dependency.getProductEvidence().addEvidence("file", "name",
|
||||||
fileName, Confidence.HIGH);
|
packageName, Confidence.HIGH);
|
||||||
dependency.getVendorEvidence().addEvidence("file", "name",
|
dependency.getVendorEvidence().addEvidence("file", "name",
|
||||||
fileName, Confidence.HIGH);
|
packageName, Confidence.HIGH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,6 +154,9 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer {
|
|||||||
for (Evidence e : hint.getAddProduct()) {
|
for (Evidence e : hint.getAddProduct()) {
|
||||||
dependency.getProductEvidence().addEvidence(e);
|
dependency.getProductEvidence().addEvidence(e);
|
||||||
}
|
}
|
||||||
|
for (Evidence e : hint.getAddVersion()) {
|
||||||
|
dependency.getVersionEvidence().addEvidence(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,7 +295,7 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer {
|
|||||||
LOGGER.error("Unable to parse the base hint data file");
|
LOGGER.error("Unable to parse the base hint data file");
|
||||||
LOGGER.debug("Unable to parse the base hint data file", ex);
|
LOGGER.debug("Unable to parse the base hint data file", ex);
|
||||||
}
|
}
|
||||||
final String filePath = Settings.getString(Settings.KEYS.SUPPRESSION_FILE);
|
final String filePath = Settings.getString(Settings.KEYS.HINTS_FILE);
|
||||||
if (filePath == null) {
|
if (filePath == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -311,14 +314,21 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer {
|
|||||||
} else {
|
} else {
|
||||||
file = new File(filePath);
|
file = new File(filePath);
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
final InputStream fromClasspath = this.getClass().getClassLoader().getResourceAsStream(filePath);
|
InputStream fromClasspath = null;
|
||||||
if (fromClasspath != null) {
|
try {
|
||||||
deleteTempFile = true;
|
fromClasspath = this.getClass().getClassLoader().getResourceAsStream(filePath);
|
||||||
file = FileUtils.getTempFile("hint", "xml");
|
if (fromClasspath != null) {
|
||||||
try {
|
deleteTempFile = true;
|
||||||
org.apache.commons.io.FileUtils.copyInputStreamToFile(fromClasspath, file);
|
file = FileUtils.getTempFile("hint", "xml");
|
||||||
} catch (IOException ex) {
|
try {
|
||||||
throw new HintParseException("Unable to locate suppressions file in classpath", ex);
|
org.apache.commons.io.FileUtils.copyInputStreamToFile(fromClasspath, file);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new HintParseException("Unable to locate suppressions file in classpath", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (fromClasspath != null) {
|
||||||
|
fromClasspath.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -325,8 +325,10 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
} else {
|
} else {
|
||||||
pom = PomUtils.readPom(externalPom);
|
pom = PomUtils.readPom(externalPom);
|
||||||
}
|
}
|
||||||
pom.processProperties(pomProperties);
|
if (pom != null) {
|
||||||
foundSomething |= setPomEvidence(dependency, pom, classes);
|
pom.processProperties(pomProperties);
|
||||||
|
foundSomething |= setPomEvidence(dependency, pom, classes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (AnalysisException ex) {
|
} catch (AnalysisException ex) {
|
||||||
LOGGER.warn("An error occurred while analyzing '{}'.", dependency.getActualFilePath());
|
LOGGER.warn("An error occurred while analyzing '{}'.", dependency.getActualFilePath());
|
||||||
@@ -409,6 +411,9 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
final File file = new File(tmpDir, "pom.xml");
|
final File file = new File(tmpDir, "pom.xml");
|
||||||
try {
|
try {
|
||||||
final ZipEntry entry = jar.getEntry(path);
|
final ZipEntry entry = jar.getEntry(path);
|
||||||
|
if (entry == null) {
|
||||||
|
throw new AnalysisException(String.format("Pom (%s)does not exist in %s", path, jar.getName()));
|
||||||
|
}
|
||||||
input = jar.getInputStream(entry);
|
input = jar.getInputStream(entry);
|
||||||
fos = new FileOutputStream(file);
|
fos = new FileOutputStream(file);
|
||||||
IOUtils.copy(input, fos);
|
IOUtils.copy(input, fos);
|
||||||
@@ -487,7 +492,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final String originalGroupID = groupid;
|
final String originalGroupID = groupid;
|
||||||
if (groupid.startsWith("org.") || groupid.startsWith("com.")) {
|
if (groupid != null && (groupid.startsWith("org.") || groupid.startsWith("com."))) {
|
||||||
groupid = groupid.substring(4);
|
groupid = groupid.substring(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -496,7 +501,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final String originalArtifactID = artifactid;
|
final String originalArtifactID = artifactid;
|
||||||
if (artifactid.startsWith("org.") || artifactid.startsWith("com.")) {
|
if (artifactid != null && (artifactid.startsWith("org.") || artifactid.startsWith("com."))) {
|
||||||
artifactid = artifactid.substring(4);
|
artifactid = artifactid.substring(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -685,7 +690,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
foundSomething = true;
|
foundSomething = true;
|
||||||
versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
|
versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
|
||||||
} else if ("specification-version".equalsIgnoreCase(key)) {
|
} else if ("specification-version".equalsIgnoreCase(key)) {
|
||||||
specificationVersion = key;
|
specificationVersion = value;
|
||||||
} else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
|
} else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
|
||||||
foundSomething = true;
|
foundSomething = true;
|
||||||
vendorEvidence.addEvidence(source, key, value, Confidence.HIGH);
|
vendorEvidence.addEvidence(source, key, value, Confidence.HIGH);
|
||||||
@@ -704,17 +709,12 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
addMatchingValues(classInformation, value, productEvidence);
|
addMatchingValues(classInformation, value, productEvidence);
|
||||||
// //the following caused false positives.
|
// //the following caused false positives.
|
||||||
// } else if (key.equalsIgnoreCase(BUNDLE_VENDOR)) {
|
// } else if (key.equalsIgnoreCase(BUNDLE_VENDOR)) {
|
||||||
// foundSomething = true;
|
|
||||||
// vendorEvidence.addEvidence(source, key, value, Confidence.HIGH);
|
|
||||||
// addMatchingValues(classInformation, value, vendorEvidence);
|
|
||||||
} else if (key.equalsIgnoreCase(BUNDLE_VERSION)) {
|
} else if (key.equalsIgnoreCase(BUNDLE_VERSION)) {
|
||||||
foundSomething = true;
|
foundSomething = true;
|
||||||
versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
|
versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
|
||||||
} else if (key.equalsIgnoreCase(Attributes.Name.MAIN_CLASS.toString())) {
|
} else if (key.equalsIgnoreCase(Attributes.Name.MAIN_CLASS.toString())) {
|
||||||
continue;
|
continue;
|
||||||
//skipping main class as if this has important information to add
|
//skipping main class as if this has important information to add it will be added during class name analysis...
|
||||||
// it will be added during class name analysis... if other fields
|
|
||||||
// have the information from the class name then they will get added...
|
|
||||||
} else {
|
} else {
|
||||||
key = key.toLowerCase();
|
key = key.toLowerCase();
|
||||||
if (!IGNORE_KEYS.contains(key)
|
if (!IGNORE_KEYS.contains(key)
|
||||||
|
|||||||
@@ -245,7 +245,8 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
LOGGER.warn("Unable to download pom.xml for {} from Nexus repository; "
|
LOGGER.warn("Unable to download pom.xml for {} from Nexus repository; "
|
||||||
+ "this could result in undetected CPE/CVEs.", dependency.getFileName());
|
+ "this could result in undetected CPE/CVEs.", dependency.getFileName());
|
||||||
} finally {
|
} finally {
|
||||||
if (pomFile != null && !FileUtils.deleteQuietly(pomFile)) {
|
if (pomFile != null && pomFile.exists() && !FileUtils.deleteQuietly(pomFile)) {
|
||||||
|
LOGGER.debug("Failed to delete temporary pom file {}", pomFile.toString());
|
||||||
pomFile.deleteOnExit();
|
pomFile.deleteOnExit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ import java.io.FileInputStream;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FilenameFilter;
|
import java.io.FilenameFilter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import org.apache.commons.io.filefilter.NameFileFilter;
|
import org.apache.commons.io.filefilter.NameFileFilter;
|
||||||
import org.apache.commons.io.filefilter.SuffixFileFilter;
|
import org.apache.commons.io.filefilter.SuffixFileFilter;
|
||||||
import org.apache.commons.io.input.AutoCloseInputStream;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.owasp.dependencycheck.Engine;
|
import org.owasp.dependencycheck.Engine;
|
||||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||||
@@ -228,10 +228,13 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
throw new AnalysisException(ex);
|
throw new AnalysisException(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
collectWheelMetadata(
|
File matchingFile = getMatchingFile(temp, folderFilter);
|
||||||
dependency,
|
if (matchingFile != null) {
|
||||||
getMatchingFile(getMatchingFile(temp, folderFilter),
|
matchingFile = getMatchingFile(matchingFile, metadataFilter);
|
||||||
metadataFilter));
|
if (matchingFile != null) {
|
||||||
|
collectWheelMetadata(dependency, matchingFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -354,13 +357,22 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
if (null == manifest) {
|
if (null == manifest) {
|
||||||
LOGGER.debug("Manifest file not found.");
|
LOGGER.debug("Manifest file not found.");
|
||||||
} else {
|
} else {
|
||||||
|
InputStream in = null;
|
||||||
try {
|
try {
|
||||||
result.load(new AutoCloseInputStream(new BufferedInputStream(
|
in = new BufferedInputStream(new FileInputStream(manifest));
|
||||||
new FileInputStream(manifest))));
|
result.load(in);
|
||||||
} catch (MessagingException e) {
|
} catch (MessagingException e) {
|
||||||
LOGGER.warn(e.getMessage(), e);
|
LOGGER.warn(e.getMessage(), e);
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
LOGGER.warn(e.getMessage(), e);
|
LOGGER.warn(e.getMessage(), e);
|
||||||
|
} finally {
|
||||||
|
if (in != null) {
|
||||||
|
try {
|
||||||
|
in.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.debug("failed to close input stream", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -23,25 +23,26 @@ import java.io.FileFilter;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
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.data.nvdcve.CveDB;
|
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||||
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||||
import org.owasp.dependencycheck.dependency.Confidence;
|
import org.owasp.dependencycheck.dependency.Confidence;
|
||||||
import org.owasp.dependencycheck.dependency.Dependency;
|
import org.owasp.dependencycheck.dependency.Dependency;
|
||||||
import org.owasp.dependencycheck.dependency.Reference;
|
import org.owasp.dependencycheck.dependency.Reference;
|
||||||
import org.owasp.dependencycheck.dependency.Vulnerability;
|
import org.owasp.dependencycheck.dependency.Vulnerability;
|
||||||
|
import org.owasp.dependencycheck.exception.InitializationException;
|
||||||
import org.owasp.dependencycheck.utils.FileFilterBuilder;
|
import org.owasp.dependencycheck.utils.FileFilterBuilder;
|
||||||
import org.owasp.dependencycheck.utils.Settings;
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
|
||||||
import org.owasp.dependencycheck.exception.InitializationException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to analyze Ruby Bundler Gemspec.lock files utilizing the 3rd party
|
* Used to analyze Ruby Bundler Gemspec.lock files utilizing the 3rd party
|
||||||
@@ -279,11 +280,16 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
}
|
}
|
||||||
final File parentFile = dependency.getActualFile().getParentFile();
|
final File parentFile = dependency.getActualFile().getParentFile();
|
||||||
final Process process = launchBundleAudit(parentFile);
|
final Process process = launchBundleAudit(parentFile);
|
||||||
|
final int exitValue;
|
||||||
try {
|
try {
|
||||||
process.waitFor();
|
exitValue = process.waitFor();
|
||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
throw new AnalysisException("bundle-audit process interrupted", ie);
|
throw new AnalysisException("bundle-audit process interrupted", ie);
|
||||||
}
|
}
|
||||||
|
if (exitValue != 0) {
|
||||||
|
final String msg = String.format("Unexpected exit code from bundle-audit process; exit code: %s", exitValue);
|
||||||
|
throw new AnalysisException(msg);
|
||||||
|
}
|
||||||
BufferedReader rdr = null;
|
BufferedReader rdr = null;
|
||||||
BufferedReader errReader = null;
|
BufferedReader errReader = null;
|
||||||
try {
|
try {
|
||||||
@@ -482,7 +488,9 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
*/
|
*/
|
||||||
private Dependency createDependencyForGem(Engine engine, String parentName, String fileName, String filePath, String gem) throws IOException {
|
private Dependency createDependencyForGem(Engine engine, String parentName, String fileName, String filePath, String gem) throws IOException {
|
||||||
final File gemFile = new File(Settings.getTempDirectory(), gem + "_Gemfile.lock");
|
final File gemFile = new File(Settings.getTempDirectory(), gem + "_Gemfile.lock");
|
||||||
gemFile.createNewFile();
|
if (!gemFile.createNewFile()) {
|
||||||
|
throw new IOException("Unable to create temporary gem file");
|
||||||
|
}
|
||||||
final String displayFileName = String.format("%s%c%s:%s", parentName, File.separatorChar, fileName, gem);
|
final String displayFileName = String.format("%s%c%s:%s", parentName, File.separatorChar, fileName, gem);
|
||||||
|
|
||||||
FileUtils.write(gemFile, displayFileName, Charset.defaultCharset()); // unique contents to avoid dependency bundling
|
FileUtils.write(gemFile, displayFileName, Charset.defaultCharset()); // unique contents to avoid dependency bundling
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2016 Bianca Jiang. All Rights Reserved.
|
* Copyright (c) 2016 IBM Corporation. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
package org.owasp.dependencycheck.analyzer;
|
package org.owasp.dependencycheck.analyzer;
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ import org.owasp.dependencycheck.dependency.Dependency;
|
|||||||
* {@link RubyGemspecAnalyzer}, so it will enabled/disabled with
|
* {@link RubyGemspecAnalyzer}, so it will enabled/disabled with
|
||||||
* {@link RubyGemspecAnalyzer}.
|
* {@link RubyGemspecAnalyzer}.
|
||||||
*
|
*
|
||||||
* @author Bianca Jiang (biancajiang@gmail.com)
|
* @author Bianca Jiang (https://twitter.com/biancajiang)
|
||||||
*/
|
*/
|
||||||
@Experimental
|
@Experimental
|
||||||
public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer {
|
public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer {
|
||||||
|
|||||||
@@ -217,6 +217,9 @@ public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
return name.contains(VERSION_FILE_NAME);
|
return name.contains(VERSION_FILE_NAME);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (matchingFiles == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (File f : matchingFiles) {
|
for (File f : matchingFiles) {
|
||||||
try {
|
try {
|
||||||
final List<String> lines = FileUtils.readLines(f, Charset.defaultCharset());
|
final List<String> lines = FileUtils.readLines(f, Charset.defaultCharset());
|
||||||
|
|||||||
@@ -0,0 +1,192 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-core.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 IBM Corporation. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.analyzer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileFilter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.owasp.dependencycheck.Engine;
|
||||||
|
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||||
|
import org.owasp.dependencycheck.dependency.Confidence;
|
||||||
|
import org.owasp.dependencycheck.dependency.Dependency;
|
||||||
|
import org.owasp.dependencycheck.dependency.EvidenceCollection;
|
||||||
|
import org.owasp.dependencycheck.utils.FileFilterBuilder;
|
||||||
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This analyzer is used to analyze the SWIFT Package Manager
|
||||||
|
* (https://swift.org/package-manager/). It collects information about a package
|
||||||
|
* from Package.swift files.
|
||||||
|
*
|
||||||
|
* @author Bianca Jiang (https://twitter.com/biancajiang)
|
||||||
|
*/
|
||||||
|
@Experimental
|
||||||
|
public class SwiftPackageManagerAnalyzer extends AbstractFileTypeAnalyzer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the analyzer.
|
||||||
|
*/
|
||||||
|
private static final String ANALYZER_NAME = "SWIFT Package Manager Analyzer";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The phase that this analyzer is intended to run in.
|
||||||
|
*/
|
||||||
|
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The file name to scan.
|
||||||
|
*/
|
||||||
|
public static final String SPM_FILE_NAME = "Package.swift";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter that detects files named "package.json".
|
||||||
|
*/
|
||||||
|
private static final FileFilter SPM_FILE_FILTER = FileFilterBuilder.newInstance().addFilenames(SPM_FILE_NAME).build();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The capture group #1 is the block variable. e.g. "import
|
||||||
|
* PackageDescription let package = Package( name: "Gloss" )"
|
||||||
|
*/
|
||||||
|
private static final Pattern SPM_BLOCK_PATTERN = Pattern.compile("let[^=]+=\\s*Package\\s*\\(\\s*([^)]*)\\s*\\)", Pattern.DOTALL);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the FileFilter
|
||||||
|
*
|
||||||
|
* @return the FileFilter
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected FileFilter getFileFilter() {
|
||||||
|
return SPM_FILE_FILTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initializeFileTypeAnalyzer() {
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the analyzer.
|
||||||
|
*
|
||||||
|
* @return the name of the analyzer.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return ANALYZER_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the phase that the analyzer is intended to run in.
|
||||||
|
*
|
||||||
|
* @return the phase that the analyzer is intended to run in.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AnalysisPhase getAnalysisPhase() {
|
||||||
|
return ANALYSIS_PHASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the key used in the properties file to reference the analyzer's
|
||||||
|
* enabled property.
|
||||||
|
*
|
||||||
|
* @return the analyzer's enabled property setting key
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String getAnalyzerEnabledSettingKey() {
|
||||||
|
return Settings.KEYS.ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void analyzeFileType(Dependency dependency, Engine engine)
|
||||||
|
throws AnalysisException {
|
||||||
|
|
||||||
|
String contents;
|
||||||
|
try {
|
||||||
|
contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new AnalysisException(
|
||||||
|
"Problem occurred while reading dependency file.", e);
|
||||||
|
}
|
||||||
|
final Matcher matcher = SPM_BLOCK_PATTERN.matcher(contents);
|
||||||
|
if (matcher.find()) {
|
||||||
|
final String packageDescription = matcher.group(1);
|
||||||
|
if (packageDescription.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final EvidenceCollection product = dependency.getProductEvidence();
|
||||||
|
final EvidenceCollection vendor = dependency.getVendorEvidence();
|
||||||
|
|
||||||
|
//SPM is currently under development for SWIFT 3. Its current metadata includes package name and dependencies.
|
||||||
|
//Future interesting metadata: version, license, homepage, author, summary, etc.
|
||||||
|
final String name = addStringEvidence(product, packageDescription, "name", "name", Confidence.HIGHEST);
|
||||||
|
if (name != null && !name.isEmpty()) {
|
||||||
|
vendor.addEvidence(SPM_FILE_NAME, "name_project", name, Confidence.HIGHEST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setPackagePath(dependency);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts evidence from the package description and adds it to the given
|
||||||
|
* evidence collection.
|
||||||
|
*
|
||||||
|
* @param evidences the evidence collection to update
|
||||||
|
* @param packageDescription the text to extract evidence from
|
||||||
|
* @param field the name of the field being searched for
|
||||||
|
* @param fieldPattern the field pattern within the contents to search for
|
||||||
|
* @param confidence the confidence level of the evidence if found
|
||||||
|
* @return the string that was added as evidence
|
||||||
|
*/
|
||||||
|
private String addStringEvidence(EvidenceCollection evidences,
|
||||||
|
String packageDescription, String field, String fieldPattern, Confidence confidence) {
|
||||||
|
String value = "";
|
||||||
|
|
||||||
|
final Matcher matcher = Pattern.compile(
|
||||||
|
String.format("%s *:\\s*\"([^\"]*)", fieldPattern), Pattern.DOTALL).matcher(packageDescription);
|
||||||
|
if (matcher.find()) {
|
||||||
|
value = matcher.group(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value != null) {
|
||||||
|
value = value.trim();
|
||||||
|
if (value.length() > 0) {
|
||||||
|
evidences.addEvidence(SPM_FILE_NAME, field, value, confidence);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the package path on the given dependency.
|
||||||
|
*
|
||||||
|
* @param dep the dependency to update
|
||||||
|
*/
|
||||||
|
private void setPackagePath(Dependency dep) {
|
||||||
|
final File file = new File(dep.getFilePath());
|
||||||
|
final String parent = file.getParent();
|
||||||
|
if (parent != null) {
|
||||||
|
dep.setPackagePath(parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -61,8 +61,8 @@ public class CentralSearch {
|
|||||||
/**
|
/**
|
||||||
* Creates a NexusSearch for the given repository URL.
|
* Creates a NexusSearch for the given repository URL.
|
||||||
*
|
*
|
||||||
* @param rootURL the URL of the repository on which searches should execute. Only parameters are added to this (so it should
|
* @param rootURL the URL of the repository on which searches should
|
||||||
* end in /select)
|
* execute. Only parameters are added to this (so it should end in /select)
|
||||||
*/
|
*/
|
||||||
public CentralSearch(URL rootURL) {
|
public CentralSearch(URL rootURL) {
|
||||||
this.rootURL = rootURL;
|
this.rootURL = rootURL;
|
||||||
@@ -76,18 +76,20 @@ public class CentralSearch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches the configured Central URL for the given sha1 hash. If the artifact is found, a <code>MavenArtifact</code> is
|
* Searches the configured Central URL for the given sha1 hash. If the
|
||||||
* populated with the GAV.
|
* artifact is found, a <code>MavenArtifact</code> is populated with the
|
||||||
|
* GAV.
|
||||||
*
|
*
|
||||||
* @param sha1 the SHA-1 hash string for which to search
|
* @param sha1 the SHA-1 hash string for which to search
|
||||||
* @return the populated Maven GAV.
|
* @return the populated Maven GAV.
|
||||||
* @throws IOException if it's unable to connect to the specified repository or if the specified artifact is not found.
|
* @throws IOException if it's unable to connect to the specified repository
|
||||||
|
* or if the specified artifact is not found.
|
||||||
*/
|
*/
|
||||||
public List<MavenArtifact> searchSha1(String sha1) throws IOException {
|
public List<MavenArtifact> searchSha1(String sha1) throws IOException {
|
||||||
if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) {
|
if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) {
|
||||||
throw new IllegalArgumentException("Invalid SHA1 format");
|
throw new IllegalArgumentException("Invalid SHA1 format");
|
||||||
}
|
}
|
||||||
|
List<MavenArtifact> result = null;
|
||||||
final URL url = new URL(rootURL + String.format("?q=1:\"%s\"&wt=xml", sha1));
|
final URL url = new URL(rootURL + String.format("?q=1:\"%s\"&wt=xml", sha1));
|
||||||
|
|
||||||
LOGGER.debug("Searching Central url {}", url);
|
LOGGER.debug("Searching Central url {}", url);
|
||||||
@@ -116,7 +118,7 @@ public class CentralSearch {
|
|||||||
if ("0".equals(numFound)) {
|
if ("0".equals(numFound)) {
|
||||||
missing = true;
|
missing = true;
|
||||||
} else {
|
} else {
|
||||||
final List<MavenArtifact> result = new ArrayList<MavenArtifact>();
|
result = new ArrayList<MavenArtifact>();
|
||||||
final NodeList docs = (NodeList) xpath.evaluate("/response/result/doc", doc, XPathConstants.NODESET);
|
final NodeList docs = (NodeList) xpath.evaluate("/response/result/doc", doc, XPathConstants.NODESET);
|
||||||
for (int i = 0; i < docs.getLength(); i++) {
|
for (int i = 0; i < docs.getLength(); i++) {
|
||||||
final String g = xpath.evaluate("./str[@name='g']", docs.item(i));
|
final String g = xpath.evaluate("./str[@name='g']", docs.item(i));
|
||||||
@@ -144,16 +146,12 @@ public class CentralSearch {
|
|||||||
useHTTPS = true;
|
useHTTPS = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.trace("Version: {}", v);
|
LOGGER.trace("Version: {}", v);
|
||||||
result.add(new MavenArtifact(g, a, v, jarAvailable, pomAvailable, useHTTPS));
|
result.add(new MavenArtifact(g, a, v, jarAvailable, pomAvailable, useHTTPS));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
// Anything else is jacked up XML stuff that we really can't recover
|
// Anything else is jacked up XML stuff that we really can't recover from well
|
||||||
// from well
|
|
||||||
throw new IOException(e.getMessage(), e);
|
throw new IOException(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,10 +160,9 @@ public class CentralSearch {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOGGER.debug("Could not connect to Central received response code: {} {}",
|
LOGGER.debug("Could not connect to Central received response code: {} {}",
|
||||||
conn.getResponseCode(), conn.getResponseMessage());
|
conn.getResponseCode(), conn.getResponseMessage());
|
||||||
throw new IOException("Could not connect to Central");
|
throw new IOException("Could not connect to Central");
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,10 +209,13 @@ public final class CpeMemoryIndex {
|
|||||||
|
|
||||||
final Set<Pair<String, String>> data = cve.getVendorProductList();
|
final Set<Pair<String, String>> data = cve.getVendorProductList();
|
||||||
for (Pair<String, String> pair : data) {
|
for (Pair<String, String> pair : data) {
|
||||||
v.setStringValue(pair.getLeft());
|
//todo figure out why there are null products
|
||||||
p.setStringValue(pair.getRight());
|
if (pair.getLeft() != null && pair.getRight() != null) {
|
||||||
indexWriter.addDocument(doc);
|
v.setStringValue(pair.getLeft());
|
||||||
resetFieldAnalyzer();
|
p.setStringValue(pair.getRight());
|
||||||
|
indexWriter.addDocument(doc);
|
||||||
|
resetFieldAnalyzer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (DatabaseException ex) {
|
} catch (DatabaseException ex) {
|
||||||
LOGGER.debug("", ex);
|
LOGGER.debug("", ex);
|
||||||
|
|||||||
@@ -36,8 +36,10 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the configured database driver and returns the database connection. If the embedded H2 database is used obtaining a
|
* Loads the configured database driver and returns the database connection. If
|
||||||
* connection will ensure the database file exists and that the appropriate table structure has been created.
|
* the embedded H2 database is used obtaining a connection will ensure the
|
||||||
|
* database file exists and that the appropriate table structure has been
|
||||||
|
* created.
|
||||||
*
|
*
|
||||||
* @author Jeremy Long
|
* @author Jeremy Long
|
||||||
*/
|
*/
|
||||||
@@ -87,12 +89,13 @@ public final class ConnectionFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the connection factory. Ensuring that the appropriate drivers are loaded and that a connection can be made
|
* Initializes the connection factory. Ensuring that the appropriate drivers
|
||||||
* successfully.
|
* are loaded and that a connection can be made successfully.
|
||||||
*
|
*
|
||||||
* @throws DatabaseException thrown if we are unable to connect to the database
|
* @throws DatabaseException thrown if we are unable to connect to the
|
||||||
|
* database
|
||||||
*/
|
*/
|
||||||
public static synchronized void initialize() throws DatabaseException {
|
public static void initialize() throws DatabaseException {
|
||||||
//this only needs to be called once.
|
//this only needs to be called once.
|
||||||
if (connectionString != null) {
|
if (connectionString != null) {
|
||||||
return;
|
return;
|
||||||
@@ -188,11 +191,12 @@ public final class ConnectionFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cleans up resources and unloads any registered database drivers. This needs to be called to ensure the driver is
|
* Cleans up resources and unloads any registered database drivers. This
|
||||||
* unregistered prior to the finalize method being called as during shutdown the class loader used to load the driver may be
|
* needs to be called to ensure the driver is unregistered prior to the
|
||||||
* unloaded prior to the driver being de-registered.
|
* finalize method being called as during shutdown the class loader used to
|
||||||
|
* load the driver may be unloaded prior to the driver being de-registered.
|
||||||
*/
|
*/
|
||||||
public static synchronized void cleanup() {
|
public static void cleanup() {
|
||||||
if (driver != null) {
|
if (driver != null) {
|
||||||
try {
|
try {
|
||||||
DriverManager.deregisterDriver(driver);
|
DriverManager.deregisterDriver(driver);
|
||||||
@@ -210,10 +214,12 @@ public final class ConnectionFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new database connection object per the database configuration.
|
* Constructs a new database connection object per the database
|
||||||
|
* configuration.
|
||||||
*
|
*
|
||||||
* @return a database connection object
|
* @return a database connection object
|
||||||
* @throws DatabaseException thrown if there is an exception loading the database connection
|
* @throws DatabaseException thrown if there is an exception loading the
|
||||||
|
* database connection
|
||||||
*/
|
*/
|
||||||
public static Connection getConnection() throws DatabaseException {
|
public static Connection getConnection() throws DatabaseException {
|
||||||
initialize();
|
initialize();
|
||||||
@@ -228,10 +234,12 @@ public final class ConnectionFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the H2 database file exists. If it does not exist then the data structure will need to be created.
|
* Determines if the H2 database file exists. If it does not exist then the
|
||||||
|
* data structure will need to be created.
|
||||||
*
|
*
|
||||||
* @return true if the H2 database file does not exist; otherwise false
|
* @return true if the H2 database file does not exist; otherwise false
|
||||||
* @throws IOException thrown if the data directory does not exist and cannot be created
|
* @throws IOException thrown if the data directory does not exist and
|
||||||
|
* cannot be created
|
||||||
*/
|
*/
|
||||||
private static boolean h2DataFileExists() throws IOException {
|
private static boolean h2DataFileExists() throws IOException {
|
||||||
final File dir = Settings.getDataDirectory();
|
final File dir = Settings.getDataDirectory();
|
||||||
@@ -241,7 +249,8 @@ public final class ConnectionFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the database structure (tables and indexes) to store the CVE data.
|
* Creates the database structure (tables and indexes) to store the CVE
|
||||||
|
* data.
|
||||||
*
|
*
|
||||||
* @param conn the database connection
|
* @param conn the database connection
|
||||||
* @throws DatabaseException thrown if there is a Database Exception
|
* @throws DatabaseException thrown if there is a Database Exception
|
||||||
@@ -271,14 +280,17 @@ public final class ConnectionFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the database schema by loading the upgrade script for the version specified. The intended use is that if the
|
* Updates the database schema by loading the upgrade script for the version
|
||||||
* current schema version is 2.9 then we would call updateSchema(conn, "2.9"). This would load the upgrade_2.9.sql file and
|
* specified. The intended use is that if the current schema version is 2.9
|
||||||
* execute it against the database. The upgrade script must update the 'version' in the properties table.
|
* then we would call updateSchema(conn, "2.9"). This would load the
|
||||||
|
* upgrade_2.9.sql file and execute it against the database. The upgrade
|
||||||
|
* script must update the 'version' in the properties table.
|
||||||
*
|
*
|
||||||
* @param conn the database connection object
|
* @param conn the database connection object
|
||||||
* @param appExpectedVersion the schema version that the application expects
|
* @param appExpectedVersion the schema version that the application expects
|
||||||
* @param currentDbVersion the current schema version of the database
|
* @param currentDbVersion the current schema version of the database
|
||||||
* @throws DatabaseException thrown if there is an exception upgrading the database schema
|
* @throws DatabaseException thrown if there is an exception upgrading the
|
||||||
|
* database schema
|
||||||
*/
|
*/
|
||||||
private static void updateSchema(Connection conn, DependencyVersion appExpectedVersion, DependencyVersion currentDbVersion)
|
private static void updateSchema(Connection conn, DependencyVersion appExpectedVersion, DependencyVersion currentDbVersion)
|
||||||
throws DatabaseException {
|
throws DatabaseException {
|
||||||
@@ -340,15 +352,18 @@ public final class ConnectionFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counter to ensure that calls to ensureSchemaVersion does not end up in an endless loop.
|
* Counter to ensure that calls to ensureSchemaVersion does not end up in an
|
||||||
|
* endless loop.
|
||||||
*/
|
*/
|
||||||
private static int callDepth = 0;
|
private static int callDepth = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses the provided connection to check the specified schema version within the database.
|
* Uses the provided connection to check the specified schema version within
|
||||||
|
* the database.
|
||||||
*
|
*
|
||||||
* @param conn the database connection object
|
* @param conn the database connection object
|
||||||
* @throws DatabaseException thrown if the schema version is not compatible with this version of dependency-check
|
* @throws DatabaseException thrown if the schema version is not compatible
|
||||||
|
* with this version of dependency-check
|
||||||
*/
|
*/
|
||||||
private static void ensureSchemaVersion(Connection conn) throws DatabaseException {
|
private static void ensureSchemaVersion(Connection conn) throws DatabaseException {
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
@@ -359,7 +374,13 @@ public final class ConnectionFactory {
|
|||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
if (rs.next()) {
|
if (rs.next()) {
|
||||||
final DependencyVersion appDbVersion = DependencyVersionUtil.parseVersion(DB_SCHEMA_VERSION);
|
final DependencyVersion appDbVersion = DependencyVersionUtil.parseVersion(DB_SCHEMA_VERSION);
|
||||||
|
if (appDbVersion == null) {
|
||||||
|
throw new DatabaseException("Invalid application database schema");
|
||||||
|
}
|
||||||
final DependencyVersion db = DependencyVersionUtil.parseVersion(rs.getString(1));
|
final DependencyVersion db = DependencyVersionUtil.parseVersion(rs.getString(1));
|
||||||
|
if (db == null) {
|
||||||
|
throw new DatabaseException("Invalid database schema");
|
||||||
|
}
|
||||||
if (appDbVersion.compareTo(db) > 0) {
|
if (appDbVersion.compareTo(db) > 0) {
|
||||||
LOGGER.debug("Current Schema: {}", DB_SCHEMA_VERSION);
|
LOGGER.debug("Current Schema: {}", DB_SCHEMA_VERSION);
|
||||||
LOGGER.debug("DB Schema: {}", rs.getString(1));
|
LOGGER.debug("DB Schema: {}", rs.getString(1));
|
||||||
|
|||||||
@@ -87,10 +87,12 @@ public class CveDB {
|
|||||||
open();
|
open();
|
||||||
try {
|
try {
|
||||||
final String databaseProductName = conn.getMetaData().getDatabaseProductName();
|
final String databaseProductName = conn.getMetaData().getDatabaseProductName();
|
||||||
batchSupported = conn.getMetaData().supportsBatchUpdates();
|
|
||||||
LOGGER.debug("Database dialect: {}", databaseProductName);
|
LOGGER.debug("Database dialect: {}", databaseProductName);
|
||||||
final Locale dbDialect = new Locale(databaseProductName);
|
final Locale dbDialect = new Locale(databaseProductName);
|
||||||
statementBundle = ResourceBundle.getBundle("data/dbStatements", dbDialect);
|
statementBundle = ResourceBundle.getBundle("data/dbStatements", dbDialect);
|
||||||
|
if ("mysql".equalsIgnoreCase(databaseProductName)) {
|
||||||
|
batchSupported = false;
|
||||||
|
}
|
||||||
} catch (SQLException se) {
|
} catch (SQLException se) {
|
||||||
LOGGER.warn("Problem loading database specific dialect!", se);
|
LOGGER.warn("Problem loading database specific dialect!", se);
|
||||||
statementBundle = ResourceBundle.getBundle("data/dbStatements");
|
statementBundle = ResourceBundle.getBundle("data/dbStatements");
|
||||||
@@ -658,7 +660,7 @@ public class CveDB {
|
|||||||
+ "If the problem persist try deleting the files in '{}' and running {} again. If the problem continues, please "
|
+ "If the problem persist try deleting the files in '{}' and running {} again. If the problem continues, please "
|
||||||
+ "create a log file (see documentation at http://jeremylong.github.io/DependencyCheck/) and open a ticket at "
|
+ "create a log file (see documentation at http://jeremylong.github.io/DependencyCheck/) and open a ticket at "
|
||||||
+ "https://github.com/jeremylong/DependencyCheck/issues and include the log file.\n\n",
|
+ "https://github.com/jeremylong/DependencyCheck/issues and include the log file.\n\n",
|
||||||
dd, dd, Settings.getString(Settings.KEYS.APPLICATION_VAME));
|
dd, dd, Settings.getString(Settings.KEYS.APPLICATION_NAME));
|
||||||
LOGGER.debug("", ex);
|
LOGGER.debug("", ex);
|
||||||
} finally {
|
} finally {
|
||||||
DBUtils.closeResultSet(rs);
|
DBUtils.closeResultSet(rs);
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ public class CpeUpdater extends BaseUpdater implements CachedWebDataSource {
|
|||||||
final String originalPath = file.getPath();
|
final String originalPath = file.getPath();
|
||||||
final File gzip = new File(originalPath + ".gz");
|
final File gzip = new File(originalPath + ".gz");
|
||||||
if (gzip.isFile() && !gzip.delete()) {
|
if (gzip.isFile() && !gzip.delete()) {
|
||||||
|
LOGGER.debug("Failed to delete intial temporary file {}", gzip.toString());
|
||||||
gzip.deleteOnExit();
|
gzip.deleteOnExit();
|
||||||
}
|
}
|
||||||
if (!file.renameTo(gzip)) {
|
if (!file.renameTo(gzip)) {
|
||||||
@@ -192,8 +193,9 @@ public class CpeUpdater extends BaseUpdater implements CachedWebDataSource {
|
|||||||
LOGGER.trace("ignore", ex);
|
LOGGER.trace("ignore", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (gzip.isFile()) {
|
if (gzip.isFile() && !FileUtils.deleteQuietly(gzip)) {
|
||||||
FileUtils.deleteQuietly(gzip);
|
LOGGER.debug("Failed to delete temporary file {}", gzip.toString());
|
||||||
|
gzip.deleteOnExit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -220,11 +220,11 @@ public class EngineVersionCheck implements CachedWebDataSource {
|
|||||||
return releaseVersion.trim();
|
return releaseVersion.trim();
|
||||||
}
|
}
|
||||||
} catch (MalformedURLException ex) {
|
} catch (MalformedURLException ex) {
|
||||||
LOGGER.debug("Unable to retrieve current release version of dependency-check", ex);
|
LOGGER.debug("Unable to retrieve current release version of dependency-check - malformed url?");
|
||||||
} catch (URLConnectionFailureException ex) {
|
} catch (URLConnectionFailureException ex) {
|
||||||
LOGGER.debug("Unable to retrieve current release version of dependency-check", ex);
|
LOGGER.debug("Unable to retrieve current release version of dependency-check - connection failed");
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
LOGGER.debug("Unable to retrieve current release version of dependency-check", ex);
|
LOGGER.debug("Unable to retrieve current release version of dependency-check - i/o exception");
|
||||||
} finally {
|
} finally {
|
||||||
if (conn != null) {
|
if (conn != null) {
|
||||||
conn.disconnect();
|
conn.disconnect();
|
||||||
|
|||||||
@@ -77,10 +77,10 @@ public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource {
|
|||||||
}
|
}
|
||||||
if (autoUpdate && checkUpdate()) {
|
if (autoUpdate && checkUpdate()) {
|
||||||
final UpdateableNvdCve updateable = getUpdatesNeeded();
|
final UpdateableNvdCve updateable = getUpdatesNeeded();
|
||||||
getProperties().save(DatabaseProperties.LAST_CHECKED, Long.toString(System.currentTimeMillis()));
|
|
||||||
if (updateable.isUpdateNeeded()) {
|
if (updateable.isUpdateNeeded()) {
|
||||||
performUpdate(updateable);
|
performUpdate(updateable);
|
||||||
}
|
}
|
||||||
|
getProperties().save(DatabaseProperties.LAST_CHECKED, Long.toString(System.currentTimeMillis()));
|
||||||
}
|
}
|
||||||
} catch (MalformedURLException ex) {
|
} catch (MalformedURLException ex) {
|
||||||
throw new UpdateException("NVD CVE properties files contain an invalid URL, unable to update the data to use the most current data.", ex);
|
throw new UpdateException("NVD CVE properties files contain an invalid URL, unable to update the data to use the most current data.", ex);
|
||||||
@@ -156,93 +156,86 @@ public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource {
|
|||||||
* @throws UpdateException is thrown if there is an error updating the
|
* @throws UpdateException is thrown if there is an error updating the
|
||||||
* database
|
* database
|
||||||
*/
|
*/
|
||||||
public void performUpdate(UpdateableNvdCve updateable) throws UpdateException {
|
private void performUpdate(UpdateableNvdCve updateable) throws UpdateException {
|
||||||
int maxUpdates = 0;
|
int maxUpdates = 0;
|
||||||
try {
|
for (NvdCveInfo cve : updateable) {
|
||||||
for (NvdCveInfo cve : updateable) {
|
if (cve.getNeedsUpdate()) {
|
||||||
if (cve.getNeedsUpdate()) {
|
maxUpdates += 1;
|
||||||
maxUpdates += 1;
|
}
|
||||||
|
}
|
||||||
|
if (maxUpdates <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (maxUpdates > 3) {
|
||||||
|
LOGGER.info("NVD CVE requires several updates; this could take a couple of minutes.");
|
||||||
|
}
|
||||||
|
|
||||||
|
final int poolSize = (MAX_THREAD_POOL_SIZE < maxUpdates) ? MAX_THREAD_POOL_SIZE : maxUpdates;
|
||||||
|
|
||||||
|
final ExecutorService downloadExecutors = Executors.newFixedThreadPool(poolSize);
|
||||||
|
final ExecutorService processExecutor = Executors.newSingleThreadExecutor();
|
||||||
|
final Set<Future<Future<ProcessTask>>> downloadFutures = new HashSet<Future<Future<ProcessTask>>>(maxUpdates);
|
||||||
|
for (NvdCveInfo cve : updateable) {
|
||||||
|
if (cve.getNeedsUpdate()) {
|
||||||
|
final DownloadTask call = new DownloadTask(cve, processExecutor, getCveDB(), Settings.getInstance());
|
||||||
|
downloadFutures.add(downloadExecutors.submit(call));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
downloadExecutors.shutdown();
|
||||||
|
|
||||||
|
//next, move the future future processTasks to just future processTasks
|
||||||
|
final Set<Future<ProcessTask>> processFutures = new HashSet<Future<ProcessTask>>(maxUpdates);
|
||||||
|
for (Future<Future<ProcessTask>> future : downloadFutures) {
|
||||||
|
Future<ProcessTask> task = null;
|
||||||
|
try {
|
||||||
|
task = future.get();
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
downloadExecutors.shutdownNow();
|
||||||
|
processExecutor.shutdownNow();
|
||||||
|
|
||||||
|
LOGGER.debug("Thread was interrupted during download", ex);
|
||||||
|
throw new UpdateException("The download was interrupted", ex);
|
||||||
|
} catch (ExecutionException ex) {
|
||||||
|
downloadExecutors.shutdownNow();
|
||||||
|
processExecutor.shutdownNow();
|
||||||
|
|
||||||
|
LOGGER.debug("Thread was interrupted during download execution", ex);
|
||||||
|
throw new UpdateException("The execution of the download was interrupted", ex);
|
||||||
|
}
|
||||||
|
if (task == null) {
|
||||||
|
downloadExecutors.shutdownNow();
|
||||||
|
processExecutor.shutdownNow();
|
||||||
|
LOGGER.debug("Thread was interrupted during download");
|
||||||
|
throw new UpdateException("The download was interrupted; unable to complete the update");
|
||||||
|
} else {
|
||||||
|
processFutures.add(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Future<ProcessTask> future : processFutures) {
|
||||||
|
try {
|
||||||
|
final ProcessTask task = future.get();
|
||||||
|
if (task.getException() != null) {
|
||||||
|
throw task.getException();
|
||||||
}
|
}
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
processExecutor.shutdownNow();
|
||||||
|
LOGGER.debug("Thread was interrupted during processing", ex);
|
||||||
|
throw new UpdateException(ex);
|
||||||
|
} catch (ExecutionException ex) {
|
||||||
|
processExecutor.shutdownNow();
|
||||||
|
LOGGER.debug("Execution Exception during process", ex);
|
||||||
|
throw new UpdateException(ex);
|
||||||
|
} finally {
|
||||||
|
processExecutor.shutdown();
|
||||||
}
|
}
|
||||||
if (maxUpdates <= 0) {
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (maxUpdates > 3) {
|
|
||||||
LOGGER.info("NVD CVE requires several updates; this could take a couple of minutes.");
|
|
||||||
}
|
|
||||||
if (maxUpdates > 0) {
|
|
||||||
openDataStores();
|
|
||||||
}
|
|
||||||
|
|
||||||
final int poolSize = (MAX_THREAD_POOL_SIZE < maxUpdates) ? MAX_THREAD_POOL_SIZE : maxUpdates;
|
if (maxUpdates >= 1) { //ensure the modified file date gets written (we may not have actually updated it)
|
||||||
|
getProperties().save(updateable.get(MODIFIED));
|
||||||
final ExecutorService downloadExecutors = Executors.newFixedThreadPool(poolSize);
|
LOGGER.info("Begin database maintenance.");
|
||||||
final ExecutorService processExecutor = Executors.newSingleThreadExecutor();
|
getCveDB().cleanupDatabase();
|
||||||
final Set<Future<Future<ProcessTask>>> downloadFutures = new HashSet<Future<Future<ProcessTask>>>(maxUpdates);
|
LOGGER.info("End database maintenance.");
|
||||||
for (NvdCveInfo cve : updateable) {
|
|
||||||
if (cve.getNeedsUpdate()) {
|
|
||||||
final DownloadTask call = new DownloadTask(cve, processExecutor, getCveDB(), Settings.getInstance());
|
|
||||||
downloadFutures.add(downloadExecutors.submit(call));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
downloadExecutors.shutdown();
|
|
||||||
|
|
||||||
//next, move the future future processTasks to just future processTasks
|
|
||||||
final Set<Future<ProcessTask>> processFutures = new HashSet<Future<ProcessTask>>(maxUpdates);
|
|
||||||
for (Future<Future<ProcessTask>> future : downloadFutures) {
|
|
||||||
Future<ProcessTask> task = null;
|
|
||||||
try {
|
|
||||||
task = future.get();
|
|
||||||
} catch (InterruptedException ex) {
|
|
||||||
downloadExecutors.shutdownNow();
|
|
||||||
processExecutor.shutdownNow();
|
|
||||||
|
|
||||||
LOGGER.debug("Thread was interrupted during download", ex);
|
|
||||||
throw new UpdateException("The download was interrupted", ex);
|
|
||||||
} catch (ExecutionException ex) {
|
|
||||||
downloadExecutors.shutdownNow();
|
|
||||||
processExecutor.shutdownNow();
|
|
||||||
|
|
||||||
LOGGER.debug("Thread was interrupted during download execution", ex);
|
|
||||||
throw new UpdateException("The execution of the download was interrupted", ex);
|
|
||||||
}
|
|
||||||
if (task == null) {
|
|
||||||
downloadExecutors.shutdownNow();
|
|
||||||
processExecutor.shutdownNow();
|
|
||||||
LOGGER.debug("Thread was interrupted during download");
|
|
||||||
throw new UpdateException("The download was interrupted; unable to complete the update");
|
|
||||||
} else {
|
|
||||||
processFutures.add(task);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Future<ProcessTask> future : processFutures) {
|
|
||||||
try {
|
|
||||||
final ProcessTask task = future.get();
|
|
||||||
if (task.getException() != null) {
|
|
||||||
throw task.getException();
|
|
||||||
}
|
|
||||||
} catch (InterruptedException ex) {
|
|
||||||
processExecutor.shutdownNow();
|
|
||||||
LOGGER.debug("Thread was interrupted during processing", ex);
|
|
||||||
throw new UpdateException(ex);
|
|
||||||
} catch (ExecutionException ex) {
|
|
||||||
processExecutor.shutdownNow();
|
|
||||||
LOGGER.debug("Execution Exception during process", ex);
|
|
||||||
throw new UpdateException(ex);
|
|
||||||
} finally {
|
|
||||||
processExecutor.shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maxUpdates >= 1) { //ensure the modified file date gets written (we may not have actually updated it)
|
|
||||||
getProperties().save(updateable.get(MODIFIED));
|
|
||||||
LOGGER.info("Begin database maintenance.");
|
|
||||||
getCveDB().cleanupDatabase();
|
|
||||||
LOGGER.info("End database maintenance.");
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
closeDataStores();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,8 +55,9 @@ public class DownloadTask implements Callable<Future<ProcessTask>> {
|
|||||||
* @param nvdCveInfo the NVD CVE info
|
* @param nvdCveInfo the NVD CVE info
|
||||||
* @param processor the processor service to submit the downloaded files to
|
* @param processor the processor service to submit the downloaded files to
|
||||||
* @param cveDB the CVE DB to use to store the vulnerability data
|
* @param cveDB the CVE DB to use to store the vulnerability data
|
||||||
* @param settings a reference to the global settings object; this is necessary so that when the thread is started the
|
* @param settings a reference to the global settings object; this is
|
||||||
* dependencies have a correct reference to the global settings.
|
* necessary so that when the thread is started the dependencies have a
|
||||||
|
* correct reference to the global settings.
|
||||||
* @throws UpdateException thrown if temporary files could not be created
|
* @throws UpdateException thrown if temporary files could not be created
|
||||||
*/
|
*/
|
||||||
public DownloadTask(NvdCveInfo nvdCveInfo, ExecutorService processor, CveDB cveDB, Settings settings) throws UpdateException {
|
public DownloadTask(NvdCveInfo nvdCveInfo, ExecutorService processor, CveDB cveDB, Settings settings) throws UpdateException {
|
||||||
@@ -205,25 +206,13 @@ public class DownloadTask implements Callable<Future<ProcessTask>> {
|
|||||||
* Attempts to delete the files that were downloaded.
|
* Attempts to delete the files that were downloaded.
|
||||||
*/
|
*/
|
||||||
public void cleanup() {
|
public void cleanup() {
|
||||||
boolean deleted = false;
|
if (first != null && first.exists() && first.delete()) {
|
||||||
try {
|
LOGGER.debug("Failed to delete first temporary file {}", second.toString());
|
||||||
if (first != null && first.exists()) {
|
first.deleteOnExit();
|
||||||
deleted = first.delete();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (first != null && (first.exists() || !deleted)) {
|
|
||||||
first.deleteOnExit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
try {
|
if (second != null && second.exists() && !second.delete()) {
|
||||||
deleted = false;
|
LOGGER.debug("Failed to delete second temporary file {}", second.toString());
|
||||||
if (second != null && second.exists()) {
|
second.deleteOnExit();
|
||||||
deleted = second.delete();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (second != null && (second.exists() || !deleted)) {
|
|
||||||
second.deleteOnExit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +257,8 @@ public class DownloadTask implements Callable<Future<ProcessTask>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the file contained in a gzip archive. The extracted file is placed in the exact same path as the file specified.
|
* Extracts the file contained in a gzip archive. The extracted file is
|
||||||
|
* placed in the exact same path as the file specified.
|
||||||
*
|
*
|
||||||
* @param file the archive file
|
* @param file the archive file
|
||||||
* @throws FileNotFoundException thrown if the file does not exist
|
* @throws FileNotFoundException thrown if the file does not exist
|
||||||
@@ -278,6 +268,7 @@ public class DownloadTask implements Callable<Future<ProcessTask>> {
|
|||||||
final String originalPath = file.getPath();
|
final String originalPath = file.getPath();
|
||||||
final File gzip = new File(originalPath + ".gz");
|
final File gzip = new File(originalPath + ".gz");
|
||||||
if (gzip.isFile() && !gzip.delete()) {
|
if (gzip.isFile() && !gzip.delete()) {
|
||||||
|
LOGGER.debug("Failed to delete initial temporary file when extracting 'gz' {}", gzip.toString());
|
||||||
gzip.deleteOnExit();
|
gzip.deleteOnExit();
|
||||||
}
|
}
|
||||||
if (!file.renameTo(gzip)) {
|
if (!file.renameTo(gzip)) {
|
||||||
@@ -312,8 +303,9 @@ public class DownloadTask implements Callable<Future<ProcessTask>> {
|
|||||||
LOGGER.trace("ignore", ex);
|
LOGGER.trace("ignore", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (gzip.isFile()) {
|
if (gzip.isFile() && !FileUtils.deleteQuietly(gzip)) {
|
||||||
FileUtils.deleteQuietly(gzip);
|
LOGGER.debug("Failed to delete temporary file when extracting 'gz' {}", gzip.toString());
|
||||||
|
gzip.deleteOnExit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package org.owasp.dependencycheck.dependency;
|
package org.owasp.dependencycheck.dependency;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An external reference for a vulnerability. This contains a name, URL, and a
|
* An external reference for a vulnerability. This contains a name, URL, and a
|
||||||
@@ -141,18 +142,10 @@ public class Reference implements Serializable, Comparable<Reference> {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(Reference o) {
|
public int compareTo(Reference o) {
|
||||||
if (source.equals(o.source)) {
|
return new CompareToBuilder()
|
||||||
if (name.equals(o.name)) {
|
.append(source, o.source)
|
||||||
if (url.equals(o.url)) {
|
.append(name, o.name)
|
||||||
return 0; //they are equal
|
.append(url, o.url)
|
||||||
} else {
|
.toComparison();
|
||||||
return url.compareTo(o.url);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return name.compareTo(o.name);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return source.compareTo(o.source);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import java.io.Serializable;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the information about a vulnerability.
|
* Contains the information about a vulnerability.
|
||||||
@@ -161,7 +162,8 @@ public class Vulnerability implements Serializable, Comparable<Vulnerability> {
|
|||||||
* Adds an entry for vulnerable software.
|
* Adds an entry for vulnerable software.
|
||||||
*
|
*
|
||||||
* @param cpe string representation of a cpe
|
* @param cpe string representation of a cpe
|
||||||
* @param previousVersion the previous version (previousVersion - cpe would be considered vulnerable)
|
* @param previousVersion the previous version (previousVersion - cpe would
|
||||||
|
* be considered vulnerable)
|
||||||
* @return if the add succeeded
|
* @return if the add succeeded
|
||||||
*/
|
*/
|
||||||
public boolean addVulnerableSoftware(String cpe, String previousVersion) {
|
public boolean addVulnerableSoftware(String cpe, String previousVersion) {
|
||||||
@@ -390,28 +392,32 @@ public class Vulnerability implements Serializable, Comparable<Vulnerability> {
|
|||||||
sb.append(this.name);
|
sb.append(this.name);
|
||||||
sb.append("\nReferences:\n");
|
sb.append("\nReferences:\n");
|
||||||
for (Reference reference : this.references) {
|
for (Reference reference : this.references) {
|
||||||
sb.append("=> ");
|
sb.append("=> ");
|
||||||
sb.append(reference);
|
sb.append(reference);
|
||||||
sb.append("\n");
|
sb.append("\n");
|
||||||
}
|
}
|
||||||
sb.append("\nSoftware:\n");
|
sb.append("\nSoftware:\n");
|
||||||
for (VulnerableSoftware software : this.vulnerableSoftware) {
|
for (VulnerableSoftware software : this.vulnerableSoftware) {
|
||||||
sb.append("=> ");
|
sb.append("=> ");
|
||||||
sb.append(software);
|
sb.append(software);
|
||||||
sb.append("\n");
|
sb.append("\n");
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares two vulnerabilities.
|
* Compares two vulnerabilities.
|
||||||
*
|
*
|
||||||
* @param v a vulnerability to be compared
|
* @param v a vulnerability to be compared
|
||||||
* @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than
|
* @return a negative integer, zero, or a positive integer as this object is
|
||||||
* the specified vulnerability
|
* less than, equal to, or greater than the specified vulnerability
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(Vulnerability v) {
|
public int compareTo(Vulnerability v) {
|
||||||
return v.getName().compareTo(this.getName());
|
return new CompareToBuilder()
|
||||||
|
.append(this.name, v.name)
|
||||||
|
.toComparison();
|
||||||
|
//return v.getName().compareTo(this.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -427,8 +433,8 @@ public class Vulnerability implements Serializable, Comparable<Vulnerability> {
|
|||||||
* Sets the CPE that caused this vulnerability to be flagged.
|
* Sets the CPE that caused this vulnerability to be flagged.
|
||||||
*
|
*
|
||||||
* @param cpeId a CPE identifier
|
* @param cpeId a CPE identifier
|
||||||
* @param previous a flag indicating whether or not all previous versions were affected (any non-null value is
|
* @param previous a flag indicating whether or not all previous versions
|
||||||
* considered true)
|
* were affected (any non-null value is considered true)
|
||||||
*/
|
*/
|
||||||
public void setMatchedCPE(String cpeId, String previous) {
|
public void setMatchedCPE(String cpeId, String previous) {
|
||||||
matchedCPE = cpeId;
|
matchedCPE = cpeId;
|
||||||
|
|||||||
@@ -90,7 +90,8 @@ public class ExceptionCollection extends Exception {
|
|||||||
this.exceptions.add(exceptions);
|
this.exceptions.add(exceptions);
|
||||||
this.fatal = fatal;
|
this.fatal = fatal;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
|
/**
|
||||||
* Instantiates a new exception collection.
|
* Instantiates a new exception collection.
|
||||||
*
|
*
|
||||||
* @param msg the exception message
|
* @param msg the exception message
|
||||||
@@ -195,7 +196,7 @@ public class ExceptionCollection extends Exception {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void printStackTrace(PrintStream s) {
|
public void printStackTrace(PrintStream s) {
|
||||||
s.println("Multiple Exceptions Occured");
|
s.println("Multiple Exceptions Occurred");
|
||||||
super.printStackTrace(s);
|
super.printStackTrace(s);
|
||||||
for (Throwable t : this.exceptions) {
|
for (Throwable t : this.exceptions) {
|
||||||
s.println("Next Exception:");
|
s.println("Next Exception:");
|
||||||
@@ -204,11 +205,23 @@ public class ExceptionCollection extends Exception {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints the stack trace to standard error.
|
* Returns the error message, including the message from all contained
|
||||||
|
* exceptions.
|
||||||
|
*
|
||||||
|
* @return the error message
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void printStackTrace() {
|
public String getMessage() {
|
||||||
this.printStackTrace(System.err);
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
final String msg = super.getMessage();
|
||||||
|
if (msg == null || msg.isEmpty()) {
|
||||||
|
sb.append("One or more exceptions occured during analysis:");
|
||||||
|
} else {
|
||||||
|
sb.append(msg);
|
||||||
|
}
|
||||||
|
for (Throwable t : this.exceptions) {
|
||||||
|
sb.append("\n\t").append(t.getMessage());
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ import java.util.regex.Pattern;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* A utility class to extract version numbers from file names (or other strings containing version numbers.</p>
|
* A utility class to extract version numbers from file names (or other strings
|
||||||
|
* containing version numbers.</p>
|
||||||
*
|
*
|
||||||
* @author Jeremy Long
|
* @author Jeremy Long
|
||||||
*/
|
*/
|
||||||
@@ -35,11 +36,19 @@ public final class DependencyVersionUtil {
|
|||||||
*/
|
*/
|
||||||
private static final Pattern RX_VERSION = Pattern.compile("\\d+(\\.\\d{1,6})+(\\.?([_-](release|beta|alpha|\\d+)|[a-zA-Z_-]{1,3}\\d{0,8}))?");
|
private static final Pattern RX_VERSION = Pattern.compile("\\d+(\\.\\d{1,6})+(\\.?([_-](release|beta|alpha|\\d+)|[a-zA-Z_-]{1,3}\\d{0,8}))?");
|
||||||
/**
|
/**
|
||||||
* Regular expression to extract a single version number without periods. This is a last ditch effort just to check in case we
|
* Regular expression to extract a single version number without periods.
|
||||||
* are missing a version number using the previous regex.
|
* This is a last ditch effort just to check in case we are missing a
|
||||||
|
* version number using the previous regex.
|
||||||
*/
|
*/
|
||||||
private static final Pattern RX_SINGLE_VERSION = Pattern.compile("\\d+(\\.?([_-](release|beta|alpha)|[a-zA-Z_-]{1,3}\\d{1,8}))?");
|
private static final Pattern RX_SINGLE_VERSION = Pattern.compile("\\d+(\\.?([_-](release|beta|alpha)|[a-zA-Z_-]{1,3}\\d{1,8}))?");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regular expression to extract the part before the version numbers if
|
||||||
|
* there are any based on RX_VERSION. In most cases, this part represents a
|
||||||
|
* more accurate name.
|
||||||
|
*/
|
||||||
|
private static final Pattern RX_PRE_VERSION = Pattern.compile("^(.+)[_-](\\d+\\.\\d{1,6})+");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private constructor for utility class.
|
* Private constructor for utility class.
|
||||||
*/
|
*/
|
||||||
@@ -48,7 +57,8 @@ public final class DependencyVersionUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* A utility class to extract version numbers from file names (or other strings containing version numbers.</p>
|
* A utility class to extract version numbers from file names (or other
|
||||||
|
* strings containing version numbers.</p>
|
||||||
* <pre>
|
* <pre>
|
||||||
* Example:
|
* Example:
|
||||||
* Give the file name: library-name-1.4.1r2-release.jar
|
* Give the file name: library-name-1.4.1r2-release.jar
|
||||||
@@ -95,4 +105,30 @@ public final class DependencyVersionUtil {
|
|||||||
}
|
}
|
||||||
return new DependencyVersion(version);
|
return new DependencyVersion(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* A utility class to extract the part before version numbers from file
|
||||||
|
* names (or other strings containing version numbers. In most cases, this
|
||||||
|
* part represents a more accurate name than the full file name.</p>
|
||||||
|
* <pre>
|
||||||
|
* Example:
|
||||||
|
* Give the file name: library-name-1.4.1r2-release.jar
|
||||||
|
* This function would return: library-name</pre>
|
||||||
|
*
|
||||||
|
* @param text the text being analyzed
|
||||||
|
* @return the part before the version numbers if any, otherwise return the
|
||||||
|
* text itself.
|
||||||
|
*/
|
||||||
|
public static String parsePreVersion(String text) {
|
||||||
|
if (parseVersion(text) == null) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Matcher matcher = RX_PRE_VERSION.matcher(text);
|
||||||
|
if (matcher.find()) {
|
||||||
|
return matcher.group(1);
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,9 +62,17 @@ public class HintHandler extends DefaultHandler {
|
|||||||
*/
|
*/
|
||||||
private static final String DUPLICATE = "duplicate";
|
private static final String DUPLICATE = "duplicate";
|
||||||
/**
|
/**
|
||||||
* Attribute name.
|
* Attribute value.
|
||||||
*/
|
*/
|
||||||
private static final String VENDOR = "vendor";
|
private static final String VENDOR = "vendor";
|
||||||
|
/**
|
||||||
|
* Attribute value.
|
||||||
|
*/
|
||||||
|
private static final String PRODUCT = "product";
|
||||||
|
/**
|
||||||
|
* Attribute value.
|
||||||
|
*/
|
||||||
|
private static final String VERSION = "version";
|
||||||
/**
|
/**
|
||||||
* Attribute name.
|
* Attribute name.
|
||||||
*/
|
*/
|
||||||
@@ -168,16 +176,25 @@ public class HintHandler extends DefaultHandler {
|
|||||||
attr.getValue(VALUE),
|
attr.getValue(VALUE),
|
||||||
Confidence.valueOf(attr.getValue(CONFIDENCE)));
|
Confidence.valueOf(attr.getValue(CONFIDENCE)));
|
||||||
}
|
}
|
||||||
} else if (inAddNode) {
|
} else if (PRODUCT.equals(hintType)) {
|
||||||
rule.addAddProduct(attr.getValue(SOURCE),
|
if (inAddNode) {
|
||||||
attr.getValue(NAME),
|
rule.addAddProduct(attr.getValue(SOURCE),
|
||||||
attr.getValue(VALUE),
|
attr.getValue(NAME),
|
||||||
Confidence.valueOf(attr.getValue(CONFIDENCE)));
|
attr.getValue(VALUE),
|
||||||
} else {
|
Confidence.valueOf(attr.getValue(CONFIDENCE)));
|
||||||
rule.addGivenProduct(attr.getValue(SOURCE),
|
} else {
|
||||||
attr.getValue(NAME),
|
rule.addGivenProduct(attr.getValue(SOURCE),
|
||||||
attr.getValue(VALUE),
|
attr.getValue(NAME),
|
||||||
Confidence.valueOf(attr.getValue(CONFIDENCE)));
|
attr.getValue(VALUE),
|
||||||
|
Confidence.valueOf(attr.getValue(CONFIDENCE)));
|
||||||
|
}
|
||||||
|
} else if (VERSION.equals(hintType)) {
|
||||||
|
if (inAddNode) {
|
||||||
|
rule.addAddVersion(attr.getValue(SOURCE),
|
||||||
|
attr.getValue(NAME),
|
||||||
|
attr.getValue(VALUE),
|
||||||
|
Confidence.valueOf(attr.getValue(CONFIDENCE)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (FILE_NAME.equals(qName)) {
|
} else if (FILE_NAME.equals(qName)) {
|
||||||
final PropertyType pt = new PropertyType();
|
final PropertyType pt = new PropertyType();
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public class HintParser {
|
|||||||
/**
|
/**
|
||||||
* The schema for the hint XML files.
|
* The schema for the hint XML files.
|
||||||
*/
|
*/
|
||||||
private static final String HINT_SCHEMA = "schema/dependency-hint.1.0.xsd";
|
private static final String HINT_SCHEMA = "schema/dependency-hint.1.1.xsd";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the given XML file and returns a list of the hints contained.
|
* Parses the given XML file and returns a list of the hints contained.
|
||||||
@@ -104,8 +104,9 @@ public class HintParser {
|
|||||||
* @throws SAXException thrown if the XML cannot be parsed
|
* @throws SAXException thrown if the XML cannot be parsed
|
||||||
*/
|
*/
|
||||||
public Hints parseHints(InputStream inputStream) throws HintParseException, SAXException {
|
public Hints parseHints(InputStream inputStream) throws HintParseException, SAXException {
|
||||||
|
InputStream schemaStream = null;
|
||||||
try {
|
try {
|
||||||
final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(HINT_SCHEMA);
|
schemaStream = this.getClass().getClassLoader().getResourceAsStream(HINT_SCHEMA);
|
||||||
final HintHandler handler = new HintHandler();
|
final HintHandler handler = new HintHandler();
|
||||||
final SAXParserFactory factory = SAXParserFactory.newInstance();
|
final SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||||
factory.setNamespaceAware(true);
|
factory.setNamespaceAware(true);
|
||||||
@@ -141,6 +142,14 @@ public class HintParser {
|
|||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
LOGGER.debug("", ex);
|
LOGGER.debug("", ex);
|
||||||
throw new HintParseException(ex);
|
throw new HintParseException(ex);
|
||||||
|
} finally {
|
||||||
|
if (schemaStream != null) {
|
||||||
|
try {
|
||||||
|
schemaStream.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.debug("Error closing hint file stream", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,6 +85,15 @@ public class HintRule {
|
|||||||
*/
|
*/
|
||||||
private final List<Evidence> givenVendor = new ArrayList<Evidence>();
|
private final List<Evidence> givenVendor = new ArrayList<Evidence>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of product evidence to add.
|
||||||
|
*/
|
||||||
|
private final List<Evidence> addProduct = new ArrayList<Evidence>();
|
||||||
|
/**
|
||||||
|
* The list of version evidence to add.
|
||||||
|
*/
|
||||||
|
private final List<Evidence> addVersion = new ArrayList<Evidence>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a given vendors to the list of evidence to matched.
|
* Adds a given vendors to the list of evidence to matched.
|
||||||
*
|
*
|
||||||
@@ -106,11 +115,6 @@ public class HintRule {
|
|||||||
return givenVendor;
|
return givenVendor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The list of product evidence to add.
|
|
||||||
*/
|
|
||||||
private final List<Evidence> addProduct = new ArrayList<Evidence>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a given product to the list of evidence to add when matched.
|
* Adds a given product to the list of evidence to add when matched.
|
||||||
*
|
*
|
||||||
@@ -132,6 +136,27 @@ public class HintRule {
|
|||||||
return addProduct;
|
return addProduct;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a given version to the list of evidence to add when matched.
|
||||||
|
*
|
||||||
|
* @param source the source of the evidence
|
||||||
|
* @param name the name of the evidence
|
||||||
|
* @param value the value of the evidence
|
||||||
|
* @param confidence the confidence of the evidence
|
||||||
|
*/
|
||||||
|
public void addAddVersion(String source, String name, String value, Confidence confidence) {
|
||||||
|
addVersion.add(new Evidence(source, name, value, confidence));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of addVersion.
|
||||||
|
*
|
||||||
|
* @return the value of addVersion
|
||||||
|
*/
|
||||||
|
public List<Evidence> getAddVersion() {
|
||||||
|
return addVersion;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of vendor hints to add.
|
* The list of vendor hints to add.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -48,13 +48,17 @@ public final class PomUtils {
|
|||||||
*
|
*
|
||||||
* @param file the pom.xml file
|
* @param file the pom.xml file
|
||||||
* @return returns a
|
* @return returns a
|
||||||
* @throws AnalysisException is thrown if there is an exception extracting or parsing the POM {@link Model} object
|
* @throws AnalysisException is thrown if there is an exception extracting
|
||||||
|
* or parsing the POM {@link Model} object
|
||||||
*/
|
*/
|
||||||
public static Model readPom(File file) throws AnalysisException {
|
public static Model readPom(File file) throws AnalysisException {
|
||||||
Model model = null;
|
|
||||||
try {
|
try {
|
||||||
final PomParser parser = new PomParser();
|
final PomParser parser = new PomParser();
|
||||||
model = parser.parse(file);
|
final Model model = parser.parse(file);
|
||||||
|
if (model == null) {
|
||||||
|
throw new AnalysisException(String.format("Unable to parse pom '%s'", file.getPath()));
|
||||||
|
}
|
||||||
|
return model;
|
||||||
} catch (PomParseException ex) {
|
} catch (PomParseException ex) {
|
||||||
LOGGER.warn("Unable to parse pom '{}'", file.getPath());
|
LOGGER.warn("Unable to parse pom '{}'", file.getPath());
|
||||||
LOGGER.debug("", ex);
|
LOGGER.debug("", ex);
|
||||||
@@ -68,7 +72,6 @@ public final class PomUtils {
|
|||||||
LOGGER.debug("", ex);
|
LOGGER.debug("", ex);
|
||||||
throw new AnalysisException(ex);
|
throw new AnalysisException(ex);
|
||||||
}
|
}
|
||||||
return model;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,7 +80,8 @@ public final class PomUtils {
|
|||||||
* @param path the path to the pom.xml file within the jar file
|
* @param path the path to the pom.xml file within the jar file
|
||||||
* @param jar the jar file to extract the pom from
|
* @param jar the jar file to extract the pom from
|
||||||
* @return returns a
|
* @return returns a
|
||||||
* @throws AnalysisException is thrown if there is an exception extracting or parsing the POM {@link Model} object
|
* @throws AnalysisException is thrown if there is an exception extracting
|
||||||
|
* or parsing the POM {@link Model} object
|
||||||
*/
|
*/
|
||||||
public static Model readPom(String path, JarFile jar) throws AnalysisException {
|
public static Model readPom(String path, JarFile jar) throws AnalysisException {
|
||||||
final ZipEntry entry = jar.getEntry(path);
|
final ZipEntry entry = jar.getEntry(path);
|
||||||
@@ -86,7 +90,9 @@ public final class PomUtils {
|
|||||||
try {
|
try {
|
||||||
final PomParser parser = new PomParser();
|
final PomParser parser = new PomParser();
|
||||||
model = parser.parse(jar.getInputStream(entry));
|
model = parser.parse(jar.getInputStream(entry));
|
||||||
LOGGER.debug("Read POM {}", path);
|
if (model == null) {
|
||||||
|
throw new AnalysisException(String.format("Unable to parse pom '%s/%s'", jar.getName(), path));
|
||||||
|
}
|
||||||
} catch (SecurityException ex) {
|
} catch (SecurityException ex) {
|
||||||
LOGGER.warn("Unable to parse pom '{}' in jar '{}'; invalid signature", path, jar.getName());
|
LOGGER.warn("Unable to parse pom '{}' in jar '{}'; invalid signature", path, jar.getName());
|
||||||
LOGGER.debug("", ex);
|
LOGGER.debug("", ex);
|
||||||
@@ -105,11 +111,13 @@ public final class PomUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads in the pom file and adds elements as evidence to the given dependency.
|
* Reads in the pom file and adds elements as evidence to the given
|
||||||
|
* dependency.
|
||||||
*
|
*
|
||||||
* @param dependency the dependency being analyzed
|
* @param dependency the dependency being analyzed
|
||||||
* @param pomFile the pom file to read
|
* @param pomFile the pom file to read
|
||||||
* @throws AnalysisException is thrown if there is an exception parsing the pom
|
* @throws AnalysisException is thrown if there is an exception parsing the
|
||||||
|
* pom
|
||||||
*/
|
*/
|
||||||
public static void analyzePOM(Dependency dependency, File pomFile) throws AnalysisException {
|
public static void analyzePOM(Dependency dependency, File pomFile) throws AnalysisException {
|
||||||
final Model pom = PomUtils.readPom(pomFile);
|
final Model pom = PomUtils.readPom(pomFile);
|
||||||
|
|||||||
@@ -17,8 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.owasp.dependencycheck.xml.suppression;
|
package org.owasp.dependencycheck.xml.suppression;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.xml.sax.ErrorHandler;
|
import org.xml.sax.ErrorHandler;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
import org.xml.sax.SAXParseException;
|
import org.xml.sax.SAXParseException;
|
||||||
@@ -33,7 +31,7 @@ public class SuppressionErrorHandler implements ErrorHandler {
|
|||||||
/**
|
/**
|
||||||
* The logger.
|
* The logger.
|
||||||
*/
|
*/
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(SuppressionErrorHandler.class);
|
//private static final Logger LOGGER = LoggerFactory.getLogger(SuppressionErrorHandler.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a prettier exception message.
|
* Builds a prettier exception message.
|
||||||
@@ -70,7 +68,7 @@ public class SuppressionErrorHandler implements ErrorHandler {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void warning(SAXParseException ex) throws SAXException {
|
public void warning(SAXParseException ex) throws SAXException {
|
||||||
LOGGER.debug("", ex);
|
//LOGGER.debug("", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -121,8 +121,9 @@ public class SuppressionParser {
|
|||||||
* @throws SAXException thrown if the XML cannot be parsed
|
* @throws SAXException thrown if the XML cannot be parsed
|
||||||
*/
|
*/
|
||||||
public List<SuppressionRule> parseSuppressionRules(InputStream inputStream) throws SuppressionParseException, SAXException {
|
public List<SuppressionRule> parseSuppressionRules(InputStream inputStream) throws SuppressionParseException, SAXException {
|
||||||
|
InputStream schemaStream = null;
|
||||||
try {
|
try {
|
||||||
final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(SUPPRESSION_SCHEMA);
|
schemaStream = this.getClass().getClassLoader().getResourceAsStream(SUPPRESSION_SCHEMA);
|
||||||
final SuppressionHandler handler = new SuppressionHandler();
|
final SuppressionHandler handler = new SuppressionHandler();
|
||||||
final SAXParserFactory factory = SAXParserFactory.newInstance();
|
final SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||||
factory.setNamespaceAware(true);
|
factory.setNamespaceAware(true);
|
||||||
@@ -157,6 +158,14 @@ public class SuppressionParser {
|
|||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
LOGGER.debug("", ex);
|
LOGGER.debug("", ex);
|
||||||
throw new SuppressionParseException(ex);
|
throw new SuppressionParseException(ex);
|
||||||
|
} finally {
|
||||||
|
if (schemaStream != null) {
|
||||||
|
try {
|
||||||
|
schemaStream.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.debug("Error closing suppression file stream", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,8 +178,9 @@ public class SuppressionParser {
|
|||||||
* @throws SuppressionParseException if the XML cannot be parsed
|
* @throws SuppressionParseException if the XML cannot be parsed
|
||||||
*/
|
*/
|
||||||
private List<SuppressionRule> parseOldSuppressionRules(InputStream inputStream) throws SuppressionParseException {
|
private List<SuppressionRule> parseOldSuppressionRules(InputStream inputStream) throws SuppressionParseException {
|
||||||
|
InputStream schemaStream = null;
|
||||||
try {
|
try {
|
||||||
final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(OLD_SUPPRESSION_SCHEMA);
|
schemaStream = this.getClass().getClassLoader().getResourceAsStream(OLD_SUPPRESSION_SCHEMA);
|
||||||
final SuppressionHandler handler = new SuppressionHandler();
|
final SuppressionHandler handler = new SuppressionHandler();
|
||||||
final SAXParserFactory factory = SAXParserFactory.newInstance();
|
final SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||||
factory.setNamespaceAware(true);
|
factory.setNamespaceAware(true);
|
||||||
@@ -200,6 +210,14 @@ public class SuppressionParser {
|
|||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
LOGGER.debug("", ex);
|
LOGGER.debug("", ex);
|
||||||
throw new SuppressionParseException(ex);
|
throw new SuppressionParseException(ex);
|
||||||
|
} finally {
|
||||||
|
if (schemaStream != null) {
|
||||||
|
try {
|
||||||
|
schemaStream.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.debug("Error closing old suppression file stream", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -22,3 +22,5 @@ org.owasp.dependencycheck.analyzer.RubyGemspecAnalyzer
|
|||||||
org.owasp.dependencycheck.analyzer.RubyBundlerAnalyzer
|
org.owasp.dependencycheck.analyzer.RubyBundlerAnalyzer
|
||||||
org.owasp.dependencycheck.analyzer.RubyBundleAuditAnalyzer
|
org.owasp.dependencycheck.analyzer.RubyBundleAuditAnalyzer
|
||||||
org.owasp.dependencycheck.analyzer.ComposerLockAnalyzer
|
org.owasp.dependencycheck.analyzer.ComposerLockAnalyzer
|
||||||
|
org.owasp.dependencycheck.analyzer.CocoaPodsAnalyzer
|
||||||
|
org.owasp.dependencycheck.analyzer.SwiftPackageManagerAnalyzer
|
||||||
|
|||||||
@@ -1,75 +1,120 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<hints xmlns="https://jeremylong.github.io/DependencyCheck/dependency-hint.1.0.xsd">
|
<hints xmlns="https://jeremylong.github.io/DependencyCheck/dependency-hint.1.1.xsd">
|
||||||
<hint>
|
<hint>
|
||||||
<given>
|
<given>
|
||||||
<evidence type="product" source="Manifest" name="Implementation-Title" value="Spring Framework" confidence="HIGH"/>
|
<evidence type="product" source="Manifest" name="Implementation-Title" value="Spring Framework" confidence="HIGH"/>
|
||||||
<evidence type="product" source="Manifest" name="Implementation-Title" value="org.springframework.core" confidence="HIGH"/>
|
<evidence type="product" source="Manifest" name="Implementation-Title" value="org.springframework.core" confidence="HIGH"/>
|
||||||
<evidence type="product" source="Manifest" name="Implementation-Title" value="spring-core" confidence="HIGH"/>
|
<evidence type="product" source="Manifest" name="Implementation-Title" value="spring-core" confidence="HIGH"/>
|
||||||
</given>
|
</given>
|
||||||
<add>
|
<add>
|
||||||
<evidence type="product" source="hint analyzer" name="product" value="springsource_spring_framework" confidence="HIGH"/>
|
<evidence type="product" source="hint analyzer" name="product" value="springsource_spring_framework" confidence="HIGH"/>
|
||||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="SpringSource" confidence="HIGH"/>
|
<evidence type="vendor" source="hint analyzer" name="vendor" value="SpringSource" confidence="HIGH"/>
|
||||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="vmware" confidence="HIGH"/>
|
<evidence type="vendor" source="hint analyzer" name="vendor" value="vmware" confidence="HIGH"/>
|
||||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="pivotal" confidence="HIGH"/>
|
<evidence type="vendor" source="hint analyzer" name="vendor" value="pivotal" confidence="HIGH"/>
|
||||||
</add>
|
</add>
|
||||||
</hint>
|
</hint>
|
||||||
<hint>
|
<hint>
|
||||||
<given>
|
<given>
|
||||||
<evidence type="product" source="jar" name="package name" value="springframework" confidence="LOW"/>
|
<evidence type="product" source="jar" name="package name" value="springframework" confidence="LOW"/>
|
||||||
<fileName contains="spring"/>
|
<fileName contains="spring"/>
|
||||||
</given>
|
</given>
|
||||||
<add>
|
<add>
|
||||||
<evidence type="product" source="hint analyzer" name="product" value="springsource_spring_framework" confidence="HIGH"/>
|
<evidence type="product" source="hint analyzer" name="product" value="springsource_spring_framework" confidence="HIGH"/>
|
||||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="SpringSource" confidence="HIGH"/>
|
<evidence type="vendor" source="hint analyzer" name="vendor" value="SpringSource" confidence="HIGH"/>
|
||||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="vmware" confidence="HIGH"/>
|
<evidence type="vendor" source="hint analyzer" name="vendor" value="vmware" confidence="HIGH"/>
|
||||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="pivotal" confidence="HIGH"/>
|
<evidence type="vendor" source="hint analyzer" name="vendor" value="pivotal" confidence="HIGH"/>
|
||||||
</add>
|
</add>
|
||||||
</hint>
|
</hint>
|
||||||
<hint>
|
<hint>
|
||||||
<given>
|
<given>
|
||||||
<evidence type="product" source="jar" name="package name" value="springframework" confidence="LOW"/>
|
<evidence type="product" source="jar" name="package name" value="springframework" confidence="LOW"/>
|
||||||
</given>
|
</given>
|
||||||
<add>
|
<add>
|
||||||
<evidence type="product" source="hint analyzer" name="product" value="springsource_spring_framework" confidence="HIGH"/>
|
<evidence type="product" source="hint analyzer" name="product" value="springsource_spring_framework" confidence="HIGH"/>
|
||||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="vmware" confidence="HIGH"/>
|
<evidence type="vendor" source="hint analyzer" name="vendor" value="vmware" confidence="HIGH"/>
|
||||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="pivotal" confidence="HIGH"/>
|
<evidence type="vendor" source="hint analyzer" name="vendor" value="pivotal" confidence="HIGH"/>
|
||||||
</add>
|
</add>
|
||||||
</hint>
|
</hint>
|
||||||
<hint>
|
<hint>
|
||||||
<given>
|
<given>
|
||||||
<evidence type="product" source="Manifest" name="Bundle-Name" value="Spring Security Core" confidence="MEDIUM"/>
|
<evidence type="product" source="Manifest" name="Bundle-Name" value="Spring Security Core" confidence="MEDIUM"/>
|
||||||
<evidence type="product" source="pom" name="artifactid" value="spring-security-core" confidence="HIGH"/>
|
<evidence type="product" source="pom" name="artifactid" value="spring-security-core" confidence="HIGH"/>
|
||||||
</given>
|
</given>
|
||||||
<add>
|
<add>
|
||||||
<evidence type="product" source="hint analyzer" name="product" value="springsource_spring_framework" confidence="HIGH"/>
|
<evidence type="product" source="hint analyzer" name="product" value="springsource_spring_framework" confidence="HIGH"/>
|
||||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="SpringSource" confidence="HIGH"/>
|
<evidence type="vendor" source="hint analyzer" name="vendor" value="SpringSource" confidence="HIGH"/>
|
||||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="vmware" confidence="HIGH"/>
|
<evidence type="vendor" source="hint analyzer" name="vendor" value="vmware" confidence="HIGH"/>
|
||||||
</add>
|
</add>
|
||||||
</hint>
|
</hint>
|
||||||
<hint>
|
<hint>
|
||||||
<given>
|
<given>
|
||||||
<evidence type="vendor" source="composer.lock" name="vendor" value="symfony" confidence="HIGHEST"/>
|
<evidence type="vendor" source="composer.lock" name="vendor" value="symfony" confidence="HIGHEST"/>
|
||||||
</given>
|
</given>
|
||||||
<add>
|
<add>
|
||||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="sensiolabs" confidence="HIGHEST"/>
|
<evidence type="vendor" source="hint analyzer" name="vendor" value="sensiolabs" confidence="HIGHEST"/>
|
||||||
</add>
|
</add>
|
||||||
</hint>
|
</hint>
|
||||||
<hint>
|
<hint>
|
||||||
<given>
|
<given>
|
||||||
<evidence type="vendor" source="composer.lock" name="vendor" value="zendframework" confidence="HIGHEST"/>
|
<evidence type="vendor" source="composer.lock" name="vendor" value="zendframework" confidence="HIGHEST"/>
|
||||||
</given>
|
</given>
|
||||||
<add>
|
<add>
|
||||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="zend" confidence="HIGHEST"/>
|
<evidence type="vendor" source="hint analyzer" name="vendor" value="zend" confidence="HIGHEST"/>
|
||||||
</add>
|
</add>
|
||||||
</hint>
|
</hint>
|
||||||
<hint>
|
<hint>
|
||||||
<given>
|
<given>
|
||||||
<evidence type="product" source="composer.lock" name="product" value="zendframework" confidence="HIGHEST"/>
|
<evidence type="product" source="composer.lock" name="product" value="zendframework" confidence="HIGHEST"/>
|
||||||
</given>
|
</given>
|
||||||
<add>
|
<add>
|
||||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="zend_framework" confidence="HIGHEST"/>
|
<evidence type="vendor" source="hint analyzer" name="vendor" value="zend_framework" confidence="HIGHEST"/>
|
||||||
</add>
|
</add>
|
||||||
</hint>
|
</hint>
|
||||||
<vendorDuplicatingHint value="sun" duplicate="oracle"/>
|
|
||||||
<vendorDuplicatingHint value="oracle" duplicate="sun"/>
|
<!-- begin hack for temporary patch of issue #534-->
|
||||||
|
<hint>
|
||||||
|
<given>
|
||||||
|
<fileName regex="true" contains=".*hibernate-validator-5\.0\..*"/>
|
||||||
|
</given>
|
||||||
|
<add>
|
||||||
|
<evidence type="version" source="hint" name="version" value="5.0" confidence="HIGHEST"/>
|
||||||
|
</add>
|
||||||
|
</hint>
|
||||||
|
<hint>
|
||||||
|
<given>
|
||||||
|
<fileName regex="true" contains=".*hibernate-validator-5\.1\.[01].*"/>
|
||||||
|
</given>
|
||||||
|
<add>
|
||||||
|
<evidence type="version" source="hint" name="version" value="5.1" confidence="HIGHEST"/>
|
||||||
|
</add>
|
||||||
|
</hint>
|
||||||
|
<hint>
|
||||||
|
<given>
|
||||||
|
<fileName regex="true" contains=".*hibernate-validator-4\.1\..*"/>
|
||||||
|
</given>
|
||||||
|
<add>
|
||||||
|
<evidence type="version" source="hint" name="version" value="4.1.0" confidence="HIGHEST"/>
|
||||||
|
</add>
|
||||||
|
</hint>
|
||||||
|
<hint>
|
||||||
|
<given>
|
||||||
|
<fileName regex="true" contains=".*hibernate-validator-4\.2\.0.*"/>
|
||||||
|
</given>
|
||||||
|
<add>
|
||||||
|
<evidence type="version" source="hint" name="version" value="4.2.0" confidence="HIGHEST"/>
|
||||||
|
</add>
|
||||||
|
</hint>
|
||||||
|
<hint>
|
||||||
|
<given>
|
||||||
|
<fileName regex="true" contains=".*hibernate-validator-4\.3\.[01]\..*"/>
|
||||||
|
</given>
|
||||||
|
<add>
|
||||||
|
<evidence type="version" source="hint" name="version" value="4.3.0" confidence="HIGHEST"/>
|
||||||
|
</add>
|
||||||
|
</hint>
|
||||||
|
<!-- end hack for temporary patch of issue #534-->
|
||||||
|
|
||||||
|
|
||||||
|
<vendorDuplicatingHint value="sun" duplicate="oracle"/>
|
||||||
|
<vendorDuplicatingHint value="oracle" duplicate="sun"/>
|
||||||
</hints>
|
</hints>
|
||||||
@@ -410,7 +410,7 @@
|
|||||||
<notes><![CDATA[
|
<notes><![CDATA[
|
||||||
Aether false positive.
|
Aether false positive.
|
||||||
]]></notes>
|
]]></notes>
|
||||||
<gav regex="true">org.eclipse.aether:aether.*</gav>
|
<gav regex="true">org\.eclipse\.aether:aether.*</gav>
|
||||||
<cpe>cpe:/a:eclipse:eclipse_ide</cpe>
|
<cpe>cpe:/a:eclipse:eclipse_ide</cpe>
|
||||||
</suppress>
|
</suppress>
|
||||||
<suppress base="true">
|
<suppress base="true">
|
||||||
@@ -420,4 +420,11 @@
|
|||||||
<filePath regex="true">.*\.(jar|ear|war|pom)</filePath>
|
<filePath regex="true">.*\.(jar|ear|war|pom)</filePath>
|
||||||
<cpe>cpe:/a:services_project:services</cpe>
|
<cpe>cpe:/a:services_project:services</cpe>
|
||||||
</suppress>
|
</suppress>
|
||||||
|
<suppress base="true">
|
||||||
|
<notes><![CDATA[
|
||||||
|
jenkins-client false positives
|
||||||
|
]]></notes>
|
||||||
|
<gav regex="true">com\.offbytwo\.jenkins:jenkins-client:.*</gav>
|
||||||
|
<cpe>cpe:/a:jenkins:jenkins</cpe>
|
||||||
|
</suppress>
|
||||||
</suppressions>
|
</suppressions>
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ analyzer.nuspec.enabled=true
|
|||||||
analyzer.openssl.enabled=true
|
analyzer.openssl.enabled=true
|
||||||
analyzer.central.enabled=true
|
analyzer.central.enabled=true
|
||||||
analyzer.nexus.enabled=false
|
analyzer.nexus.enabled=false
|
||||||
|
analyzer.cocoapods.enabled=true
|
||||||
|
analyzer.swift.package.manager.enabled=true
|
||||||
#whether the nexus analyzer uses the proxy
|
#whether the nexus analyzer uses the proxy
|
||||||
analyzer.nexus.proxy=true
|
analyzer.nexus.proxy=true
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xs:schema id="hints"
|
||||||
|
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||||
|
elementFormDefault="qualified"
|
||||||
|
targetNamespace="https://jeremylong.github.io/DependencyCheck/dependency-hint.1.1.xsd"
|
||||||
|
xmlns:dc="https://jeremylong.github.io/DependencyCheck/dependency-hint.1.1.xsd">
|
||||||
|
|
||||||
|
<xs:simpleType name="givenType">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="vendor"/>
|
||||||
|
<xs:enumeration value="product"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
<xs:simpleType name="addType">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="vendor"/>
|
||||||
|
<xs:enumeration value="product"/>
|
||||||
|
<xs:enumeration value="version"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
<xs:simpleType name="confidence">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="HIGHEST"/>
|
||||||
|
<xs:enumeration value="HIGH"/>
|
||||||
|
<xs:enumeration value="MEDIUM"/>
|
||||||
|
<xs:enumeration value="LOW"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
<xs:complexType name="givenEvidence">
|
||||||
|
<xs:attribute name="type" use="required" type="dc:givenType"/>
|
||||||
|
<xs:attribute name="source" use="required" type="xs:string"/>
|
||||||
|
<xs:attribute name="name" use="required" type="xs:string"/>
|
||||||
|
<xs:attribute name="value" use="required" type="xs:string"/>
|
||||||
|
<xs:attribute name="confidence" use="required" type="dc:confidence"/>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:complexType name="addEvidence">
|
||||||
|
<xs:attribute name="type" use="required" type="dc:addType"/>
|
||||||
|
<xs:attribute name="source" use="required" type="xs:string"/>
|
||||||
|
<xs:attribute name="name" use="required" type="xs:string"/>
|
||||||
|
<xs:attribute name="value" use="required" type="xs:string"/>
|
||||||
|
<xs:attribute name="confidence" use="required" type="dc:confidence"/>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:complexType name="fileName">
|
||||||
|
<xs:attribute name="contains" use="required" type="xs:string"/>
|
||||||
|
<xs:attribute name="regex" use="optional" type="xs:boolean" default="false"/>
|
||||||
|
<xs:attribute name="caseSensitive" use="optional" type="xs:boolean" default="false"/>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:complexType name="given">
|
||||||
|
<xs:choice minOccurs="1" maxOccurs="unbounded">
|
||||||
|
<xs:element name="evidence" type="dc:givenEvidence"/>
|
||||||
|
<xs:element name="fileName" type="dc:fileName"/>
|
||||||
|
</xs:choice>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:complexType name="add">
|
||||||
|
<xs:sequence minOccurs="1" maxOccurs="unbounded">
|
||||||
|
<xs:element name="evidence" type="dc:addEvidence"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:complexType name="hint">
|
||||||
|
<xs:sequence minOccurs="1" maxOccurs="1">
|
||||||
|
<xs:element name="given" type="dc:given"/>
|
||||||
|
<xs:element name="add" type="dc:add"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:complexType name="duplicatingHint">
|
||||||
|
<xs:attribute name="value" use="required" type="xs:string"/>
|
||||||
|
<xs:attribute name="duplicate" use="required" type="xs:string"/>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:element name="hints">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence minOccurs="0" maxOccurs="unbounded">
|
||||||
|
<xs:sequence minOccurs="0" maxOccurs="unbounded">
|
||||||
|
<xs:element name="hint" type="dc:hint"/>
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:sequence minOccurs="0" maxOccurs="unbounded">
|
||||||
|
<xs:element name="vendorDuplicatingHint" type="dc:duplicatingHint"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:schema>
|
||||||
@@ -24,6 +24,7 @@ import static org.junit.Assert.assertTrue;
|
|||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
import org.junit.Assume;
|
import org.junit.Assume;
|
||||||
import static org.junit.Assume.assumeFalse;
|
import static org.junit.Assume.assumeFalse;
|
||||||
|
import static org.junit.Assume.assumeNotNull;
|
||||||
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;
|
||||||
@@ -61,6 +62,7 @@ public class AssemblyAnalyzerTest extends BaseTest {
|
|||||||
analyzer = new AssemblyAnalyzer();
|
analyzer = new AssemblyAnalyzer();
|
||||||
analyzer.accept(new File("test.dll")); // trick into "thinking it is active"
|
analyzer.accept(new File("test.dll")); // trick into "thinking it is active"
|
||||||
analyzer.initialize();
|
analyzer.initialize();
|
||||||
|
Assume.assumeTrue("Mono is not installed, skipping tests.", analyzer.buildArgumentList() == null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (e.getMessage().contains("Could not execute .NET AssemblyAnalyzer")) {
|
if (e.getMessage().contains("Could not execute .NET AssemblyAnalyzer")) {
|
||||||
LOGGER.warn("Exception setting up AssemblyAnalyzer. Tests will be incomplete");
|
LOGGER.warn("Exception setting up AssemblyAnalyzer. Tests will be incomplete");
|
||||||
@@ -81,7 +83,7 @@ public class AssemblyAnalyzerTest extends BaseTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAnalysis() throws Exception {
|
public void testAnalysis() throws Exception {
|
||||||
//File f = new File(AssemblyAnalyzerTest.class.getClassLoader().getResource("GrokAssembly.exe").getPath());
|
assumeNotNull(analyzer.buildArgumentList());
|
||||||
File f = BaseTest.getResourceAsFile(this, "GrokAssembly.exe");
|
File f = BaseTest.getResourceAsFile(this, "GrokAssembly.exe");
|
||||||
Dependency d = new Dependency(f);
|
Dependency d = new Dependency(f);
|
||||||
analyzer.analyze(d, null);
|
analyzer.analyze(d, null);
|
||||||
@@ -104,7 +106,7 @@ public class AssemblyAnalyzerTest extends BaseTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLog4Net() throws Exception {
|
public void testLog4Net() throws Exception {
|
||||||
//File f = new File(AssemblyAnalyzerTest.class.getClassLoader().getResource("log4net.dll").getPath());
|
assumeNotNull(analyzer.buildArgumentList());
|
||||||
File f = BaseTest.getResourceAsFile(this, "log4net.dll");
|
File f = BaseTest.getResourceAsFile(this, "log4net.dll");
|
||||||
|
|
||||||
Dependency d = new Dependency(f);
|
Dependency d = new Dependency(f);
|
||||||
@@ -116,9 +118,10 @@ public class AssemblyAnalyzerTest extends BaseTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNonexistent() {
|
public void testNonexistent() {
|
||||||
|
assumeNotNull(analyzer.buildArgumentList());
|
||||||
|
|
||||||
// Tweak the log level so the warning doesn't show in the console
|
// Tweak the log level so the warning doesn't show in the console
|
||||||
String oldProp = System.getProperty(LOG_KEY, "info");
|
String oldProp = System.getProperty(LOG_KEY, "info");
|
||||||
//File f = new File(AssemblyAnalyzerTest.class.getClassLoader().getResource("log4net.dll").getPath());
|
|
||||||
File f = BaseTest.getResourceAsFile(this, "log4net.dll");
|
File f = BaseTest.getResourceAsFile(this, "log4net.dll");
|
||||||
File test = new File(f.getParent(), "nonexistent.dll");
|
File test = new File(f.getParent(), "nonexistent.dll");
|
||||||
Dependency d = new Dependency(test);
|
Dependency d = new Dependency(test);
|
||||||
|
|||||||
@@ -189,6 +189,7 @@ public class CPEAnalyzerIntegrationTest extends BaseDBTestCase {
|
|||||||
instance.determineCPE(spring);
|
instance.determineCPE(spring);
|
||||||
instance.determineCPE(spring3);
|
instance.determineCPE(spring3);
|
||||||
instance.close();
|
instance.close();
|
||||||
|
|
||||||
|
|
||||||
String expResult = "cpe:/a:apache:struts:2.1.2";
|
String expResult = "cpe:/a:apache:struts:2.1.2";
|
||||||
Identifier expIdentifier = new Identifier("cpe", expResult, expResult);
|
Identifier expIdentifier = new Identifier("cpe", expResult, expResult);
|
||||||
|
|||||||
@@ -117,7 +117,6 @@ public class RubyBundleAuditAnalyzerTest extends BaseDBTestCase {
|
|||||||
final Engine engine = new Engine();
|
final Engine engine = new Engine();
|
||||||
analyzer.analyze(result, engine);
|
analyzer.analyze(result, engine);
|
||||||
int size = engine.getDependencies().size();
|
int size = engine.getDependencies().size();
|
||||||
|
|
||||||
assertTrue(size >= 1);
|
assertTrue(size >= 1);
|
||||||
|
|
||||||
Dependency dependency = engine.getDependencies().get(0);
|
Dependency dependency = engine.getDependencies().get(0);
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
package org.owasp.dependencycheck.analyzer;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.owasp.dependencycheck.BaseTest;
|
||||||
|
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||||
|
import org.owasp.dependencycheck.dependency.Dependency;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for CocoaPodsAnalyzer.
|
||||||
|
*
|
||||||
|
* @author Bianca Jiang
|
||||||
|
*/
|
||||||
|
public class SwiftAnalyzersTest extends BaseTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The analyzer to test.
|
||||||
|
*/
|
||||||
|
CocoaPodsAnalyzer podsAnalyzer;
|
||||||
|
SwiftPackageManagerAnalyzer spmAnalyzer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correctly setup the analyzer for testing.
|
||||||
|
*
|
||||||
|
* @throws Exception thrown if there is a problem
|
||||||
|
*/
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
podsAnalyzer = new CocoaPodsAnalyzer();
|
||||||
|
podsAnalyzer.setFilesMatched(true);
|
||||||
|
podsAnalyzer.initialize();
|
||||||
|
|
||||||
|
spmAnalyzer = new SwiftPackageManagerAnalyzer();
|
||||||
|
spmAnalyzer.setFilesMatched(true);
|
||||||
|
spmAnalyzer.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleanup the analyzer's temp files, etc.
|
||||||
|
*
|
||||||
|
* @throws Exception thrown if there is a problem
|
||||||
|
*/
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
podsAnalyzer.close();
|
||||||
|
podsAnalyzer = null;
|
||||||
|
|
||||||
|
spmAnalyzer.close();
|
||||||
|
spmAnalyzer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of getName method, of class CocoaPodsAnalyzer.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testPodsGetName() {
|
||||||
|
assertThat(podsAnalyzer.getName(), is("CocoaPods Package Analyzer"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of getName method, of class SwiftPackageManagerAnalyzer.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSPMGetName() {
|
||||||
|
assertThat(spmAnalyzer.getName(), is("SWIFT Package Manager Analyzer"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of supportsFiles method, of class CocoaPodsAnalyzer.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testPodsSupportsFiles() {
|
||||||
|
assertThat(podsAnalyzer.accept(new File("test.podspec")), is(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of supportsFiles method, of class SwiftPackageManagerAnalyzer.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSPMSupportsFiles() {
|
||||||
|
assertThat(spmAnalyzer.accept(new File("Package.swift")), is(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of analyze method, of class CocoaPodsAnalyzer.
|
||||||
|
*
|
||||||
|
* @throws AnalysisException is thrown when an exception occurs.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCocoaPodsAnalyzer() throws AnalysisException {
|
||||||
|
final Dependency result = new Dependency(BaseTest.getResourceAsFile(this,
|
||||||
|
"swift/cocoapods/EasyPeasy.podspec"));
|
||||||
|
podsAnalyzer.analyze(result, null);
|
||||||
|
final String vendorString = result.getVendorEvidence().toString();
|
||||||
|
|
||||||
|
assertThat(vendorString, containsString("Carlos Vidal"));
|
||||||
|
assertThat(vendorString, containsString("https://github.com/nakiostudio/EasyPeasy"));
|
||||||
|
assertThat(vendorString, containsString("MIT"));
|
||||||
|
assertThat(result.getProductEvidence().toString(), containsString("EasyPeasy"));
|
||||||
|
assertThat(result.getVersionEvidence().toString(), containsString("0.2.3"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of analyze method, of class SwiftPackageManagerAnalyzer.
|
||||||
|
*
|
||||||
|
* @throws AnalysisException is thrown when an exception occurs.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSPMAnalyzer() throws AnalysisException {
|
||||||
|
final Dependency result = new Dependency(BaseTest.getResourceAsFile(this,
|
||||||
|
"swift/Gloss/Package.swift"));
|
||||||
|
spmAnalyzer.analyze(result, null);
|
||||||
|
|
||||||
|
assertThat(result.getProductEvidence().toString(), containsString("Gloss"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,12 +40,11 @@ public class NvdCveUpdaterIntegrationTest extends BaseTest {
|
|||||||
// /**
|
// /**
|
||||||
// * 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();
|
NvdCveUpdater instance = getUpdater();
|
||||||
// instance.update();
|
instance.update();
|
||||||
// //TODO make this an actual test
|
}
|
||||||
// }
|
|
||||||
/**
|
/**
|
||||||
* Test of updatesNeeded method, of class StandardUpdate.
|
* Test of updatesNeeded method, of class StandardUpdate.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of dependency-check-core.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package org.owasp.dependencycheck.data.update.nvd;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.owasp.dependencycheck.BaseTest;
|
|
||||||
import org.owasp.dependencycheck.data.update.NvdCveUpdater;
|
|
||||||
import org.owasp.dependencycheck.utils.Settings;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Jeremy Long
|
|
||||||
*/
|
|
||||||
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());
|
|
||||||
File f = BaseTest.getResourceAsFile(this, "nvdcve-2.0-2014.xml");
|
|
||||||
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
|
|
||||||
public void testUpdate() throws Exception {
|
|
||||||
NvdCveUpdater instance = new NvdCveUpdater();
|
|
||||||
instance.update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -52,7 +52,7 @@ public class HintHandlerTest extends BaseTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testHandler() throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException, SAXException, FileNotFoundException, UnsupportedEncodingException, IOException {
|
public void testHandler() throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException, SAXException, FileNotFoundException, UnsupportedEncodingException, IOException {
|
||||||
File file = BaseTest.getResourceAsFile(this, "hints.xml");
|
File file = BaseTest.getResourceAsFile(this, "hints.xml");
|
||||||
File schema = BaseTest.getResourceAsFile(this, "schema/dependency-hint.1.0.xsd");
|
File schema = BaseTest.getResourceAsFile(this, "schema/dependency-hint.1.1.xsd");
|
||||||
HintHandler handler = new HintHandler();
|
HintHandler handler = new HintHandler();
|
||||||
|
|
||||||
SAXParserFactory factory = SAXParserFactory.newInstance();
|
SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<hints xmlns="https://jeremylong.github.io/DependencyCheck/dependency-hint.1.0.xsd">
|
<hints xmlns="https://jeremylong.github.io/DependencyCheck/dependency-hint.1.1.xsd">
|
||||||
<hint>
|
<hint>
|
||||||
<given>
|
<given>
|
||||||
<evidence type="product" source="product source" name="given product name" value="value" confidence="HIGH"/>
|
<evidence type="product" source="product source" name="given product name" value="value" confidence="HIGH"/>
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
Pod::Spec.new do |s|
|
||||||
|
s.name = "Gloss"
|
||||||
|
s.version = "0.7.2"
|
||||||
|
s.summary = "A shiny JSON parsing library in Swift"
|
||||||
|
s.description = "A shiny JSON parsing library in Swift. Features include mapping JSON to objects, mapping objects to JSON, handling of nested objects and custom transformations."
|
||||||
|
s.homepage = "https://github.com/hkellaway/Gloss"
|
||||||
|
s.license = { :type => "MIT", :file => "LICENSE" }
|
||||||
|
s.author = { "Harlan Kellaway" => "hello@harlankellaway.com" }
|
||||||
|
s.social_media_url = "http://twitter.com/HarlanKellaway"
|
||||||
|
s.source = { :git => "https://github.com/hkellaway/Gloss.git", :tag => s.version.to_s }
|
||||||
|
|
||||||
|
s.platforms = { :ios => "8.0", :osx => "10.9", :tvos => "9.0", :watchos => "2.0" }
|
||||||
|
s.requires_arc = true
|
||||||
|
|
||||||
|
s.source_files = 'Sources/*.{swift}'
|
||||||
|
|
||||||
|
end
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// Package.swift
|
||||||
|
// Gloss
|
||||||
|
//
|
||||||
|
// Copyright (c) 2015 Harlan Kellaway
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
import PackageDescription
|
||||||
|
|
||||||
|
let package = Package(
|
||||||
|
name: "Gloss"
|
||||||
|
)
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
Pod::Spec.new do |s|
|
||||||
|
s.name = "EasyPeasy"
|
||||||
|
s.version = "0.2.3"
|
||||||
|
s.summary = "EasyPeasy is a Swift framework that eases the creation of
|
||||||
|
Autolayout constraints programmatically"
|
||||||
|
s.description = <<-DESC
|
||||||
|
EasyPeasy is a Swift framework that lets you create Autolayout constraints
|
||||||
|
programmatically without headaches and never ending boilerplate code. Besides the
|
||||||
|
basics, **EasyPeasy** resolves most of the constraint conflicts for you and lets
|
||||||
|
you attach to a constraint conditional closures that are evaluated before applying
|
||||||
|
a constraint, this lets you apply (or not) a constraint depending on platform, size
|
||||||
|
classes, orientation... or the state of your controller, easy peasy!
|
||||||
|
DESC
|
||||||
|
s.homepage = "https://github.com/nakiostudio/EasyPeasy"
|
||||||
|
s.license = 'MIT'
|
||||||
|
s.author = { "Carlos Vidal" => "nakioparkour@gmail.com" }
|
||||||
|
s.source = { :git => "https://github.com/nakiostudio/EasyPeasy.git", :tag => s.version.to_s }
|
||||||
|
s.social_media_url = 'https://twitter.com/carlostify'
|
||||||
|
|
||||||
|
s.platform = :ios, '8.0'
|
||||||
|
s.requires_arc = true
|
||||||
|
|
||||||
|
s.source_files = 'EasyPeasy/**/*'
|
||||||
|
s.frameworks = 'UIKit'
|
||||||
|
end
|
||||||
@@ -20,7 +20,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.4.1</version>
|
<version>1.4.3</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>dependency-check-maven</artifactId>
|
<artifactId>dependency-check-maven</artifactId>
|
||||||
@@ -208,6 +208,10 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
|||||||
<groupId>org.sonatype.plexus</groupId>
|
<groupId>org.sonatype.plexus</groupId>
|
||||||
<artifactId>plexus-sec-dispatcher</artifactId>
|
<artifactId>plexus-sec-dispatcher</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven.shared</groupId>
|
||||||
|
<artifactId>maven-dependency-tree</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jmockit</groupId>
|
<groupId>org.jmockit</groupId>
|
||||||
<artifactId>jmockit</artifactId>
|
<artifactId>jmockit</artifactId>
|
||||||
|
|||||||
@@ -19,10 +19,8 @@ package org.owasp.dependencycheck.maven;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.apache.maven.plugin.MojoExecutionException;
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
@@ -32,10 +30,7 @@ import org.apache.maven.plugins.annotations.Mojo;
|
|||||||
import org.apache.maven.plugins.annotations.Parameter;
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||||
import org.apache.maven.project.MavenProject;
|
import org.apache.maven.project.MavenProject;
|
||||||
import org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer;
|
|
||||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
|
||||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||||
import org.owasp.dependencycheck.dependency.Dependency;
|
|
||||||
import org.owasp.dependencycheck.exception.ExceptionCollection;
|
import org.owasp.dependencycheck.exception.ExceptionCollection;
|
||||||
import org.owasp.dependencycheck.exception.ReportException;
|
import org.owasp.dependencycheck.exception.ReportException;
|
||||||
import org.owasp.dependencycheck.utils.Settings;
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
@@ -49,18 +44,13 @@ import org.owasp.dependencycheck.utils.Settings;
|
|||||||
@Mojo(
|
@Mojo(
|
||||||
name = "aggregate",
|
name = "aggregate",
|
||||||
defaultPhase = LifecyclePhase.VERIFY,
|
defaultPhase = LifecyclePhase.VERIFY,
|
||||||
/*aggregator = true,*/
|
aggregator = true,
|
||||||
threadSafe = false,
|
threadSafe = false,
|
||||||
requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,
|
requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,
|
||||||
requiresOnline = true
|
requiresOnline = true
|
||||||
)
|
)
|
||||||
public class AggregateMojo extends BaseDependencyCheckMojo {
|
public class AggregateMojo extends BaseDependencyCheckMojo {
|
||||||
|
|
||||||
/**
|
|
||||||
* The key to store aggregate exception in the root Maven execution context.
|
|
||||||
*/
|
|
||||||
private static final String AGGREGATE_EXCEPTIONS = "AggregateExceptions";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes the aggregate dependency-check goal. This runs dependency-check
|
* Executes the aggregate dependency-check goal. This runs dependency-check
|
||||||
* and generates the subsequent reports.
|
* and generates the subsequent reports.
|
||||||
@@ -72,108 +62,78 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void runCheck() throws MojoExecutionException, MojoFailureException {
|
public void runCheck() throws MojoExecutionException, MojoFailureException {
|
||||||
final MavenEngine engine = generateDataFile();
|
final MavenEngine engine = loadEngine();
|
||||||
if (engine == null) {
|
if (engine == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getProject() == getLastProject()) {
|
ExceptionCollection exCol = scanArtifacts(getProject(), engine);
|
||||||
//ensure that the .ser file was created for each.
|
|
||||||
for (MavenProject current : getReactorProjects()) {
|
|
||||||
final File dataFile = getDataFile(current);
|
|
||||||
if (dataFile == null && !skipProject(current)) { //dc was never run on this project. write the ser to the target.
|
|
||||||
getLog().error(String.format("Module '%s' did not execute dependency-check; an attempt will be made to perform "
|
|
||||||
+ "the check but dependencies may be missed resulting in false negatives.", current.getName()));
|
|
||||||
generateDataFile(engine, current);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (MavenProject current : getReactorProjects()) {
|
|
||||||
List<Dependency> dependencies = readDataFile(current);
|
|
||||||
if (dependencies == null) {
|
|
||||||
dependencies = new ArrayList<Dependency>();
|
|
||||||
}
|
|
||||||
final Set<MavenProject> childProjects = getDescendants(current);
|
|
||||||
for (MavenProject reportOn : childProjects) {
|
|
||||||
final List<Dependency> childDeps = readDataFile(reportOn);
|
|
||||||
if (childDeps != null && !childDeps.isEmpty()) {
|
|
||||||
if (getLog().isDebugEnabled()) {
|
|
||||||
getLog().debug(String.format("Adding %d dependencies from %s", childDeps.size(), reportOn.getName()));
|
|
||||||
}
|
|
||||||
dependencies.addAll(childDeps);
|
|
||||||
} else if (getLog().isDebugEnabled()) {
|
|
||||||
getLog().debug(String.format("No dependencies read for %s", reportOn.getName()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
engine.getDependencies().clear();
|
|
||||||
engine.getDependencies().addAll(dependencies);
|
|
||||||
final DependencyBundlingAnalyzer bundler = new DependencyBundlingAnalyzer();
|
|
||||||
try {
|
|
||||||
if (getLog().isDebugEnabled()) {
|
|
||||||
getLog().debug(String.format("Dependency count pre-bundler: %s", engine.getDependencies().size()));
|
|
||||||
}
|
|
||||||
bundler.analyze(null, engine);
|
|
||||||
if (getLog().isDebugEnabled()) {
|
|
||||||
getLog().debug(String.format("Dependency count post-bundler: %s", engine.getDependencies().size()));
|
|
||||||
}
|
|
||||||
} catch (AnalysisException ex) {
|
|
||||||
getLog().warn("An error occurred grouping the dependencies; duplicate entries may exist in the report", ex);
|
|
||||||
getLog().debug("Bundling Exception", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
File outputDir = getCorrectOutputDirectory(current);
|
for (MavenProject childProject : getDescendants(this.getProject())) {
|
||||||
if (outputDir == null) {
|
final ExceptionCollection ex = scanArtifacts(childProject, engine);
|
||||||
//in some regards we shouldn't be writting this, but we are anyway.
|
if (ex != null) {
|
||||||
//we shouldn't write this because nothing is configured to generate this report.
|
if (exCol == null) {
|
||||||
outputDir = new File(current.getBuild().getDirectory());
|
exCol = ex;
|
||||||
}
|
}
|
||||||
try {
|
exCol.getExceptions().addAll(ex.getExceptions());
|
||||||
writeReports(engine, current, outputDir);
|
if (ex.isFatal()) {
|
||||||
} catch (ReportException ex) {
|
exCol.setFatal(true);
|
||||||
ExceptionCollection exCol = (ExceptionCollection) engine.getExecutionRoot().getContextValue(AGGREGATE_EXCEPTIONS);
|
|
||||||
if (exCol == null) {
|
|
||||||
exCol = new ExceptionCollection("Error writing aggregate report", ex);
|
|
||||||
} else {
|
|
||||||
exCol.addException(ex);
|
|
||||||
}
|
|
||||||
if (this.isFailOnError()) {
|
|
||||||
throw new MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol);
|
|
||||||
} else {
|
|
||||||
getLog().debug("One or more exceptions occured during dependency-check analysis", exCol);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
engine.analyzeDependencies();
|
||||||
|
} catch (ExceptionCollection ex) {
|
||||||
|
if (exCol == null) {
|
||||||
|
exCol = ex;
|
||||||
|
} else if (ex.isFatal()) {
|
||||||
|
exCol.setFatal(true);
|
||||||
|
exCol.getExceptions().addAll(ex.getExceptions());
|
||||||
|
}
|
||||||
|
if (exCol.isFatal()) {
|
||||||
|
final String msg = String.format("Fatal exception(s) analyzing %s", getProject().getName());
|
||||||
|
if (this.isFailOnError()) {
|
||||||
|
throw new MojoExecutionException(msg, exCol);
|
||||||
|
}
|
||||||
|
getLog().error(msg);
|
||||||
|
if (getLog().isDebugEnabled()) {
|
||||||
|
getLog().debug(exCol);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
final String msg = String.format("Exception(s) analyzing %s", getProject().getName());
|
||||||
|
if (getLog().isDebugEnabled()) {
|
||||||
|
getLog().debug(msg, exCol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
File outputDir = getCorrectOutputDirectory(this.getProject());
|
||||||
|
if (outputDir == null) {
|
||||||
|
//in some regards we shouldn't be writting this, but we are anyway.
|
||||||
|
//we shouldn't write this because nothing is configured to generate this report.
|
||||||
|
outputDir = new File(this.getProject().getBuild().getDirectory());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
writeReports(engine, this.getProject(), outputDir);
|
||||||
|
} catch (ReportException ex) {
|
||||||
|
if (exCol == null) {
|
||||||
|
exCol = new ExceptionCollection("Error writing aggregate report", ex);
|
||||||
|
} else {
|
||||||
|
exCol.addException(ex);
|
||||||
|
}
|
||||||
|
if (this.isFailOnError()) {
|
||||||
|
throw new MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol);
|
||||||
|
} else {
|
||||||
|
getLog().debug("One or more exceptions occured during dependency-check analysis", exCol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
showSummary(this.getProject(), engine.getDependencies());
|
||||||
|
checkForFailure(engine.getDependencies());
|
||||||
engine.cleanup();
|
engine.cleanup();
|
||||||
Settings.cleanup();
|
Settings.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the last project in the reactor - taking into account skipped
|
|
||||||
* projects.
|
|
||||||
*
|
|
||||||
* @return the last project in the reactor
|
|
||||||
*/
|
|
||||||
private MavenProject getLastProject() {
|
|
||||||
for (int x = getReactorProjects().size() - 1; x >= 0; x--) {
|
|
||||||
final MavenProject p = getReactorProjects().get(x);
|
|
||||||
if (!skipProject(p)) {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if the project is being skipped in the Maven site report.
|
|
||||||
*
|
|
||||||
* @param project a project in the reactor
|
|
||||||
* @return true if the project is skipped; otherwise false
|
|
||||||
*/
|
|
||||||
private boolean skipProject(MavenProject project) {
|
|
||||||
final String skip = (String) project.getProperties().get("maven.site.skip");
|
|
||||||
return "true".equalsIgnoreCase(skip) && isGeneratingSite();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a set containing all the descendant projects of the given
|
* Returns a set containing all the descendant projects of the given
|
||||||
* project.
|
* project.
|
||||||
@@ -264,16 +224,15 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the engine, runs a scan, and writes the serialized
|
* Initializes the engine.
|
||||||
* dependencies to disk.
|
|
||||||
*
|
*
|
||||||
* @return the MavenEngine used to execute dependency-check
|
* @return the MavenEngine used to execute dependency-check
|
||||||
* @throws MojoExecutionException thrown if there is an exception running
|
* @throws MojoExecutionException thrown if there is an exception running
|
||||||
* the mojo
|
* the Mojo
|
||||||
* @throws MojoFailureException thrown if dependency-check is configured to
|
* @throws MojoFailureException thrown if dependency-check is configured to
|
||||||
* fail the build if severe CVEs are identified.
|
* fail the build if severe CVEs are identified.
|
||||||
*/
|
*/
|
||||||
protected MavenEngine generateDataFile() throws MojoExecutionException, MojoFailureException {
|
protected MavenEngine loadEngine() throws MojoExecutionException, MojoFailureException {
|
||||||
MavenEngine engine = null;
|
MavenEngine engine = null;
|
||||||
try {
|
try {
|
||||||
engine = initializeEngine();
|
engine = initializeEngine();
|
||||||
@@ -286,59 +245,7 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
|
|||||||
throw new MojoExecutionException(msg, ex);
|
throw new MojoExecutionException(msg, ex);
|
||||||
}
|
}
|
||||||
getLog().error(msg, ex);
|
getLog().error(msg, ex);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
return generateDataFile(engine, getProject());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs dependency-check's MavenEngine and writes the serialized
|
|
||||||
* dependencies to disk.
|
|
||||||
*
|
|
||||||
* @param engine the MavenEngine to use when scanning.
|
|
||||||
* @param project the project to scan and generate the data file for
|
|
||||||
* @return the MavenEngine used to execute dependency-check
|
|
||||||
* @throws MojoExecutionException thrown if there is an exception running
|
|
||||||
* the mojo
|
|
||||||
* @throws MojoFailureException thrown if dependency-check is configured to
|
|
||||||
* fail the build if severe CVEs are identified.
|
|
||||||
*/
|
|
||||||
protected MavenEngine generateDataFile(MavenEngine engine, MavenProject project) throws MojoExecutionException, MojoFailureException {
|
|
||||||
if (getLog().isDebugEnabled()) {
|
|
||||||
getLog().debug(String.format("Begin Scanning: %s", project.getName()));
|
|
||||||
}
|
|
||||||
engine.getDependencies().clear();
|
|
||||||
engine.resetFileTypeAnalyzers();
|
|
||||||
scanArtifacts(project, engine);
|
|
||||||
try {
|
|
||||||
engine.analyzeDependencies();
|
|
||||||
} catch (ExceptionCollection ex) {
|
|
||||||
ExceptionCollection col = (ExceptionCollection) engine.getExecutionRoot().getContextValue(AGGREGATE_EXCEPTIONS);
|
|
||||||
if (col == null) {
|
|
||||||
col = ex;
|
|
||||||
} else if (ex.isFatal()) {
|
|
||||||
col.setFatal(true);
|
|
||||||
col.getExceptions().addAll(ex.getExceptions());
|
|
||||||
}
|
|
||||||
if (col.isFatal()) {
|
|
||||||
final String msg = String.format("Fatal exception(s) analyzing %s", project.getName());
|
|
||||||
if (this.isFailOnError()) {
|
|
||||||
throw new MojoExecutionException(msg, ex);
|
|
||||||
}
|
|
||||||
getLog().error(msg, col);
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
final String msg = String.format("Exception(s) analyzing %s", project.getName());
|
|
||||||
if (getLog().isDebugEnabled()) {
|
|
||||||
getLog().debug(msg, ex);
|
|
||||||
}
|
|
||||||
engine.getExecutionRoot().setContextValue(AGGREGATE_EXCEPTIONS, col);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final File target = new File(project.getBuild().getDirectory());
|
|
||||||
writeDataFile(project, target, engine.getDependencies());
|
|
||||||
showSummary(project, engine.getDependencies());
|
|
||||||
checkForFailure(engine.getDependencies());
|
|
||||||
return engine;
|
return engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import java.io.InputStream;
|
|||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import org.apache.maven.artifact.Artifact;
|
import org.eclipse.aether.artifact.Artifact;
|
||||||
import org.apache.maven.doxia.sink.Sink;
|
import org.apache.maven.doxia.sink.Sink;
|
||||||
import org.apache.maven.plugin.AbstractMojo;
|
import org.apache.maven.plugin.AbstractMojo;
|
||||||
import org.apache.maven.plugin.MojoExecutionException;
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
@@ -39,6 +39,16 @@ import org.apache.maven.reporting.MavenReport;
|
|||||||
import org.apache.maven.reporting.MavenReportException;
|
import org.apache.maven.reporting.MavenReportException;
|
||||||
import org.apache.maven.settings.Proxy;
|
import org.apache.maven.settings.Proxy;
|
||||||
import org.apache.maven.settings.Server;
|
import org.apache.maven.settings.Server;
|
||||||
|
import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
|
||||||
|
import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
|
||||||
|
import org.apache.maven.shared.dependency.graph.DependencyNode;
|
||||||
|
import org.eclipse.aether.RepositorySystem;
|
||||||
|
import org.eclipse.aether.RepositorySystemSession;
|
||||||
|
import org.eclipse.aether.artifact.DefaultArtifact;
|
||||||
|
import org.eclipse.aether.repository.RemoteRepository;
|
||||||
|
import org.eclipse.aether.resolution.ArtifactRequest;
|
||||||
|
import org.eclipse.aether.resolution.ArtifactResolutionException;
|
||||||
|
import org.eclipse.aether.resolution.ArtifactResult;
|
||||||
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
|
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
|
||||||
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||||
@@ -47,6 +57,7 @@ import org.owasp.dependencycheck.dependency.Confidence;
|
|||||||
import org.owasp.dependencycheck.dependency.Dependency;
|
import org.owasp.dependencycheck.dependency.Dependency;
|
||||||
import org.owasp.dependencycheck.dependency.Identifier;
|
import org.owasp.dependencycheck.dependency.Identifier;
|
||||||
import org.owasp.dependencycheck.dependency.Vulnerability;
|
import org.owasp.dependencycheck.dependency.Vulnerability;
|
||||||
|
import org.owasp.dependencycheck.exception.ExceptionCollection;
|
||||||
import org.owasp.dependencycheck.exception.ReportException;
|
import org.owasp.dependencycheck.exception.ReportException;
|
||||||
import org.owasp.dependencycheck.reporting.ReportGenerator;
|
import org.owasp.dependencycheck.reporting.ReportGenerator;
|
||||||
import org.owasp.dependencycheck.utils.ExpectedOjectInputStream;
|
import org.owasp.dependencycheck.utils.ExpectedOjectInputStream;
|
||||||
@@ -102,6 +113,30 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
|
|||||||
*/
|
*/
|
||||||
@Parameter(readonly = true, required = true, property = "reactorProjects")
|
@Parameter(readonly = true, required = true, property = "reactorProjects")
|
||||||
private List<MavenProject> reactorProjects;
|
private List<MavenProject> reactorProjects;
|
||||||
|
/**
|
||||||
|
* The entry point to Aether, i.e. the component doing all the work.
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
private RepositorySystem repoSystem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current repository/network configuration of Maven.
|
||||||
|
*/
|
||||||
|
@Parameter(defaultValue = "${repositorySystemSession}", readonly = true)
|
||||||
|
private RepositorySystemSession repoSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The project's remote repositories to use for the resolution of plug-ins
|
||||||
|
* and their dependencies.
|
||||||
|
*/
|
||||||
|
@Parameter(defaultValue = "${project.remotePluginRepositories}", readonly = true)
|
||||||
|
private List<RemoteRepository> remoteRepos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component within Maven to build the dependency graph.
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
private DependencyGraphBuilder dependencyGraphBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The output directory. This generally maps to "target".
|
* The output directory. This generally maps to "target".
|
||||||
@@ -553,32 +588,121 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
|
|||||||
*
|
*
|
||||||
* @param project the project to scan the dependencies of
|
* @param project the project to scan the dependencies of
|
||||||
* @param engine the engine to use to scan the dependencies
|
* @param engine the engine to use to scan the dependencies
|
||||||
|
* @return a collection of exceptions that may have occurred while resolving
|
||||||
|
* and scanning the dependencies
|
||||||
*/
|
*/
|
||||||
protected void scanArtifacts(MavenProject project, MavenEngine engine) {
|
protected ExceptionCollection scanArtifacts(MavenProject project, MavenEngine engine) {
|
||||||
for (Artifact a : project.getArtifacts()) {
|
// <editor-fold defaultstate="collapsed" desc="old implementation">
|
||||||
|
/*
|
||||||
|
for (Artifact a : project.getArtifacts()) {
|
||||||
if (excludeFromScan(a)) {
|
if (excludeFromScan(a)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final List<Dependency> deps = engine.scan(a.getFile().getAbsoluteFile());
|
final List<Dependency> deps = engine.scan(a.getFile().getAbsoluteFile());
|
||||||
if (deps != null) {
|
if (deps != null) {
|
||||||
if (deps.size() == 1) {
|
if (deps.size() == 1) {
|
||||||
final Dependency d = deps.get(0);
|
final Dependency d = deps.get(0);
|
||||||
if (d != null) {
|
if (d != null) {
|
||||||
final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion());
|
final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion());
|
||||||
d.addAsEvidence("pom", ma, Confidence.HIGHEST);
|
d.addAsEvidence("pom", ma, Confidence.HIGHEST);
|
||||||
d.addProjectReference(project.getName());
|
d.addProjectReference(project.getName());
|
||||||
if (getLog().isDebugEnabled()) {
|
if (getLog().isDebugEnabled()) {
|
||||||
getLog().debug(String.format("Adding project reference %s on dependency %s", project.getName(),
|
getLog().debug(String.format("Adding project reference %s on dependency %s", project.getName(),
|
||||||
d.getDisplayFileName()));
|
d.getDisplayFileName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (getLog().isDebugEnabled()) {
|
||||||
|
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());
|
||||||
|
getLog().debug(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// </editor-fold>
|
||||||
|
try {
|
||||||
|
final DependencyNode dn = dependencyGraphBuilder.buildDependencyGraph(project, null, reactorProjects);
|
||||||
|
return collectDependencies(engine, project, dn.getChildren());
|
||||||
|
} catch (DependencyGraphBuilderException ex) {
|
||||||
|
final String msg = String.format("Unable to build dependency graph on project %s", project.getName());
|
||||||
|
getLog().debug(msg, ex);
|
||||||
|
return new ExceptionCollection(msg, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the projects artifacts using Aether and scans the resulting
|
||||||
|
* dependencies.
|
||||||
|
*
|
||||||
|
* @param engine the core dependency-check engine
|
||||||
|
* @param project the project being scanned
|
||||||
|
* @param nodes the list of dependency nodes, generally obtained via the
|
||||||
|
* DependencyGraphBuilder
|
||||||
|
* @return a collection of exceptions that may have occurred while resolving
|
||||||
|
* and scanning the dependencies
|
||||||
|
*/
|
||||||
|
private ExceptionCollection collectDependencies(MavenEngine engine, MavenProject project, List<DependencyNode> nodes) {
|
||||||
|
ExceptionCollection exCol = null;
|
||||||
|
for (DependencyNode dependencyNode : nodes) {
|
||||||
|
exCol = collectDependencies(engine, project, dependencyNode.getChildren());
|
||||||
|
if (excludeFromScan(dependencyNode.getArtifact().getScope())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final ArtifactRequest request = new ArtifactRequest();
|
||||||
|
request.setArtifact(new DefaultArtifact(dependencyNode.getArtifact().getId()));
|
||||||
|
request.setRepositories(remoteRepos);
|
||||||
|
try {
|
||||||
|
final ArtifactResult result = repoSystem.resolveArtifact(repoSession, request);
|
||||||
|
if (result.isResolved() && result.getArtifact() != null && result.getArtifact().getFile() != null) {
|
||||||
|
final List<Dependency> deps = engine.scan(result.getArtifact().getFile().getAbsoluteFile());
|
||||||
|
if (deps != null) {
|
||||||
|
if (deps.size() == 1) {
|
||||||
|
final Dependency d = deps.get(0);
|
||||||
|
if (d != null) {
|
||||||
|
final Artifact a = result.getArtifact();
|
||||||
|
final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion());
|
||||||
|
d.addAsEvidence("pom", ma, Confidence.HIGHEST);
|
||||||
|
d.addProjectReference(project.getName() + ":" + dependencyNode.getArtifact().getScope());
|
||||||
|
if (getLog().isDebugEnabled()) {
|
||||||
|
getLog().debug(String.format("Adding project reference %s on dependency %s",
|
||||||
|
project.getName(), d.getDisplayFileName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (getLog().isDebugEnabled()) {
|
||||||
|
final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s' in project %s",
|
||||||
|
dependencyNode.getArtifact().getId(), project.getName());
|
||||||
|
getLog().debug(msg);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final String msg = String.format("Error resolving '%s' in project %s",
|
||||||
|
dependencyNode.getArtifact().getId(), project.getName());
|
||||||
|
if (exCol == null) {
|
||||||
|
exCol = new ExceptionCollection();
|
||||||
|
}
|
||||||
|
getLog().error(msg);
|
||||||
|
for (Exception ex : result.getExceptions()) {
|
||||||
|
exCol.addException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (getLog().isDebugEnabled()) {
|
} else {
|
||||||
final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'",
|
final String msg = String.format("Unable to resolve '%s' in project %s",
|
||||||
a.getGroupId(), a.getArtifactId(), a.getVersion());
|
dependencyNode.getArtifact().getId(), project.getName());
|
||||||
getLog().debug(msg);
|
getLog().debug(msg);
|
||||||
|
if (exCol == null) {
|
||||||
|
exCol = new ExceptionCollection();
|
||||||
|
}
|
||||||
|
for (Exception ex : result.getExceptions()) {
|
||||||
|
exCol.addException(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (ArtifactResolutionException ex) {
|
||||||
|
if (exCol == null) {
|
||||||
|
exCol = new ExceptionCollection();
|
||||||
|
}
|
||||||
|
exCol.addException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return exCol;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -669,8 +793,7 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
|
|||||||
*/
|
*/
|
||||||
protected MavenEngine initializeEngine() throws DatabaseException {
|
protected MavenEngine initializeEngine() throws DatabaseException {
|
||||||
populateSettings();
|
populateSettings();
|
||||||
return new MavenEngine(this.project,
|
return new MavenEngine(this.project, this.reactorProjects);
|
||||||
this.reactorProjects);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -835,18 +958,18 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
|
|||||||
* Tests is the artifact should be included in the scan (i.e. is the
|
* Tests is the artifact should be included in the scan (i.e. is the
|
||||||
* dependency in a scope that is being scanned).
|
* dependency in a scope that is being scanned).
|
||||||
*
|
*
|
||||||
* @param a the Artifact to test
|
* @param scope the scope of the artifact to test
|
||||||
* @return <code>true</code> if the artifact is in an excluded scope;
|
* @return <code>true</code> if the artifact is in an excluded scope;
|
||||||
* otherwise <code>false</code>
|
* otherwise <code>false</code>
|
||||||
*/
|
*/
|
||||||
protected boolean excludeFromScan(Artifact a) {
|
protected boolean excludeFromScan(String scope) {
|
||||||
if (skipTestScope && Artifact.SCOPE_TEST.equals(a.getScope())) {
|
if (skipTestScope && org.apache.maven.artifact.Artifact.SCOPE_TEST.equals(scope)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (skipProvidedScope && Artifact.SCOPE_PROVIDED.equals(a.getScope())) {
|
if (skipProvidedScope && org.apache.maven.artifact.Artifact.SCOPE_PROVIDED.equals(scope)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (skipRuntimeScope && !Artifact.SCOPE_RUNTIME.equals(a.getScope())) {
|
if (skipRuntimeScope && !org.apache.maven.artifact.Artifact.SCOPE_RUNTIME.equals(scope)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -1133,4 +1256,5 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
//</editor-fold>
|
//</editor-fold>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class CheckMojo extends BaseDependencyCheckMojo {
|
|||||||
public boolean canGenerateReport() {
|
public boolean canGenerateReport() {
|
||||||
boolean isCapable = false;
|
boolean isCapable = false;
|
||||||
for (Artifact a : getProject().getArtifacts()) {
|
for (Artifact a : getProject().getArtifacts()) {
|
||||||
if (!excludeFromScan(a)) {
|
if (!excludeFromScan(a.getScope())) {
|
||||||
isCapable = true;
|
isCapable = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -88,11 +88,10 @@ public class CheckMojo extends BaseDependencyCheckMojo {
|
|||||||
getLog().error(msg);
|
getLog().error(msg);
|
||||||
}
|
}
|
||||||
if (engine != null) {
|
if (engine != null) {
|
||||||
scanArtifacts(getProject(), engine);
|
ExceptionCollection exCol = scanArtifacts(getProject(), engine);
|
||||||
if (engine.getDependencies().isEmpty()) {
|
if (engine.getDependencies().isEmpty()) {
|
||||||
getLog().info("No dependencies were identified that could be analyzed by dependency-check");
|
getLog().info("No dependencies were identified that could be analyzed by dependency-check");
|
||||||
} else {
|
} else {
|
||||||
ExceptionCollection exCol = null;
|
|
||||||
try {
|
try {
|
||||||
engine.analyzeDependencies();
|
engine.analyzeDependencies();
|
||||||
} catch (ExceptionCollection ex) {
|
} catch (ExceptionCollection ex) {
|
||||||
|
|||||||
@@ -53,18 +53,16 @@ Create an aggregated dependency-check report within the site.
|
|||||||
<plugins>
|
<plugins>
|
||||||
...
|
...
|
||||||
<plugin>
|
<plugin>
|
||||||
<plugin>
|
<groupId>org.owasp</groupId>
|
||||||
<groupId>org.owasp</groupId>
|
<artifactId>dependency-check-maven</artifactId>
|
||||||
<artifactId>dependency-check-maven</artifactId>
|
<version>${project.version}</version>
|
||||||
<version>${project.version}</version>
|
<reportSets>
|
||||||
<reportSets>
|
<reportSet>
|
||||||
<reportSet>
|
<reports>
|
||||||
<reports>
|
<report>aggregate</report>
|
||||||
<report>aggregate</report>
|
</reports>
|
||||||
</reports>
|
</reportSet>
|
||||||
</reportSet>
|
</reportSets>
|
||||||
</reportSets>
|
|
||||||
</plugin>
|
|
||||||
</plugin>
|
</plugin>
|
||||||
...
|
...
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import org.apache.maven.plugin.testing.stubs.ArtifactStub;
|
|||||||
import org.apache.maven.project.MavenProject;
|
import org.apache.maven.project.MavenProject;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import org.junit.Assume;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||||
import org.owasp.dependencycheck.utils.InvalidSettingException;
|
import org.owasp.dependencycheck.utils.InvalidSettingException;
|
||||||
@@ -45,7 +46,8 @@ import org.owasp.dependencycheck.utils.Settings;
|
|||||||
public class BaseDependencyCheckMojoTest extends BaseTest {
|
public class BaseDependencyCheckMojoTest extends BaseTest {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the test can be run. The test in this class fail, presumable due to jmockit, if the JDK is 1.8+.
|
* Checks if the test can be run. The test in this class fail, presumable
|
||||||
|
* due to jmockit, if the JDK is 1.8+.
|
||||||
*
|
*
|
||||||
* @return true if the JDK is below 1.8.
|
* @return true if the JDK is below 1.8.
|
||||||
*/
|
*/
|
||||||
@@ -63,7 +65,6 @@ public class BaseDependencyCheckMojoTest extends BaseTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testScanArtifacts() throws DatabaseException, InvalidSettingException {
|
public void testScanArtifacts() throws DatabaseException, InvalidSettingException {
|
||||||
//TODO get this to work under JDK 1.8
|
|
||||||
if (canRun()) {
|
if (canRun()) {
|
||||||
MavenProject project = new MockUp<MavenProject>() {
|
MavenProject project = new MockUp<MavenProject>() {
|
||||||
@Mock
|
@Mock
|
||||||
@@ -95,7 +96,11 @@ public class BaseDependencyCheckMojoTest extends BaseTest {
|
|||||||
|
|
||||||
assertTrue(engine.getDependencies().isEmpty());
|
assertTrue(engine.getDependencies().isEmpty());
|
||||||
BaseDependencyCheckMojoImpl instance = new BaseDependencyCheckMojoImpl();
|
BaseDependencyCheckMojoImpl instance = new BaseDependencyCheckMojoImpl();
|
||||||
instance.scanArtifacts(project, engine);
|
try { //the mock above fails under some JDKs
|
||||||
|
instance.scanArtifacts(project, engine);
|
||||||
|
} catch (NullPointerException ex) {
|
||||||
|
Assume.assumeNoException(ex);
|
||||||
|
}
|
||||||
assertFalse(engine.getDependencies().isEmpty());
|
assertFalse(engine.getDependencies().isEmpty());
|
||||||
engine.cleanup();
|
engine.cleanup();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.owasp.dependencycheck.maven;
|
package org.owasp.dependencycheck.maven;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.owasp.dependencycheck.utils.Settings;
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
@@ -36,8 +39,20 @@ public class BaseTest {
|
|||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void setUpClass() throws Exception {
|
public static void setUpClass() throws Exception {
|
||||||
Settings.initialize();
|
Settings.initialize();
|
||||||
InputStream mojoProperties = BaseTest.class.getClassLoader().getResourceAsStream(BaseTest.PROPERTIES_FILE);
|
InputStream mojoProperties = null;
|
||||||
Settings.mergeProperties(mojoProperties);
|
try {
|
||||||
|
mojoProperties = BaseTest.class.getClassLoader().getResourceAsStream(BaseTest.PROPERTIES_FILE);
|
||||||
|
Settings.mergeProperties(mojoProperties);
|
||||||
|
} finally {
|
||||||
|
if (mojoProperties != null) {
|
||||||
|
try {
|
||||||
|
mojoProperties.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(BaseTest.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved.
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp</groupId>
|
<groupId>org.owasp</groupId>
|
||||||
<artifactId>dependency-check-parent</artifactId>
|
<artifactId>dependency-check-parent</artifactId>
|
||||||
<version>1.4.1</version>
|
<version>1.4.3</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>dependency-check-utils</artifactId>
|
<artifactId>dependency-check-utils</artifactId>
|
||||||
|
|||||||
@@ -58,11 +58,11 @@ public final class Checksum {
|
|||||||
* @throws NoSuchAlgorithmException when an algorithm is specified that does not exist
|
* @throws NoSuchAlgorithmException when an algorithm is specified that does not exist
|
||||||
*/
|
*/
|
||||||
public static byte[] getChecksum(String algorithm, File file) throws NoSuchAlgorithmException, IOException {
|
public static byte[] getChecksum(String algorithm, File file) throws NoSuchAlgorithmException, IOException {
|
||||||
MessageDigest digest = MessageDigest.getInstance(algorithm);
|
final MessageDigest digest = MessageDigest.getInstance(algorithm);
|
||||||
FileInputStream fis = null;
|
FileInputStream fis = null;
|
||||||
try {
|
try {
|
||||||
fis = new FileInputStream(file);
|
fis = new FileInputStream(file);
|
||||||
FileChannel ch = fis.getChannel();
|
final FileChannel ch = fis.getChannel();
|
||||||
long remainingToRead = file.length();
|
long remainingToRead = file.length();
|
||||||
long start = 0;
|
long start = 0;
|
||||||
while (remainingToRead > 0) {
|
while (remainingToRead > 0) {
|
||||||
@@ -74,7 +74,7 @@ public final class Checksum {
|
|||||||
amountToRead = remainingToRead;
|
amountToRead = remainingToRead;
|
||||||
remainingToRead = 0;
|
remainingToRead = 0;
|
||||||
}
|
}
|
||||||
MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, start, amountToRead);
|
final MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, start, amountToRead);
|
||||||
digest.update(byteBuffer);
|
digest.update(byteBuffer);
|
||||||
start += amountToRead;
|
start += amountToRead;
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ public final class Checksum {
|
|||||||
* @throws NoSuchAlgorithmException when the MD5 algorithm is not available
|
* @throws NoSuchAlgorithmException when the MD5 algorithm is not available
|
||||||
*/
|
*/
|
||||||
public static String getMD5Checksum(File file) throws IOException, NoSuchAlgorithmException {
|
public static String getMD5Checksum(File file) throws IOException, NoSuchAlgorithmException {
|
||||||
byte[] b = getChecksum("MD5", file);
|
final byte[] b = getChecksum("MD5", file);
|
||||||
return getHex(b);
|
return getHex(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ public final class Checksum {
|
|||||||
* @throws NoSuchAlgorithmException when the SHA1 algorithm is not available
|
* @throws NoSuchAlgorithmException when the SHA1 algorithm is not available
|
||||||
*/
|
*/
|
||||||
public static String getSHA1Checksum(File file) throws IOException, NoSuchAlgorithmException {
|
public static String getSHA1Checksum(File file) throws IOException, NoSuchAlgorithmException {
|
||||||
byte[] b = getChecksum("SHA1", file);
|
final byte[] b = getChecksum("SHA1", file);
|
||||||
return getHex(b);
|
return getHex(b);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -300,11 +300,11 @@ public final class Downloader {
|
|||||||
* @throws DownloadFailedException a wrapper exception that contains the
|
* @throws DownloadFailedException a wrapper exception that contains the
|
||||||
* original exception as the cause
|
* original exception as the cause
|
||||||
*/
|
*/
|
||||||
protected static void checkForCommonExceptionTypes(IOException ex) throws DownloadFailedException {
|
protected static synchronized void checkForCommonExceptionTypes(IOException ex) throws DownloadFailedException {
|
||||||
Throwable cause = ex;
|
Throwable cause = ex;
|
||||||
while (cause != null) {
|
while (cause != null) {
|
||||||
if (cause instanceof java.net.UnknownHostException) {
|
if (cause instanceof java.net.UnknownHostException) {
|
||||||
final String msg = String.format("Unable to resolve domain '%s'", cause.getMessage());
|
final String msg = format("Unable to resolve domain '%s'", cause.getMessage());
|
||||||
LOGGER.error(msg);
|
LOGGER.error(msg);
|
||||||
throw new DownloadFailedException(msg);
|
throw new DownloadFailedException(msg);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import org.apache.commons.lang3.SystemUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A collection of utilities for processing information about files.
|
* A collection of utilities for processing information about files.
|
||||||
@@ -102,7 +103,7 @@ public final class FileUtils {
|
|||||||
* @return a String containing the bit bucket
|
* @return a String containing the bit bucket
|
||||||
*/
|
*/
|
||||||
public static String getBitBucket() {
|
public static String getBitBucket() {
|
||||||
if (System.getProperty("os.name").startsWith("Windows")) {
|
if (SystemUtils.IS_OS_WINDOWS) {
|
||||||
return BIT_BUCKET_WIN;
|
return BIT_BUCKET_WIN;
|
||||||
} else {
|
} else {
|
||||||
return BIT_BUCKET_UNIX;
|
return BIT_BUCKET_UNIX;
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String[] getDefaultCipherSuites() {
|
public String[] getDefaultCipherSuites() {
|
||||||
return Arrays.copyOf(ciphers, ciphers.length);
|
return sslCtxt.getSocketFactory().getDefaultCipherSuites();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,7 +88,7 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String[] getSupportedCipherSuites() {
|
public String[] getSupportedCipherSuites() {
|
||||||
return Arrays.copyOf(ciphers, ciphers.length);
|
return sslCtxt.getSocketFactory().getSupportedCipherSuites();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -125,7 +125,6 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
|||||||
final SSLSocket ss = (SSLSocket) factory.createSocket(s, host, port, autoClose);
|
final SSLSocket ss = (SSLSocket) factory.createSocket(s, host, port, autoClose);
|
||||||
|
|
||||||
ss.setEnabledProtocols(protocols);
|
ss.setEnabledProtocols(protocols);
|
||||||
ss.setEnabledCipherSuites(ciphers);
|
|
||||||
|
|
||||||
return ss;
|
return ss;
|
||||||
}
|
}
|
||||||
@@ -146,7 +145,6 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
|||||||
final SSLSocket ss = (SSLSocket) factory.createSocket(address, port, localAddress, localPort);
|
final SSLSocket ss = (SSLSocket) factory.createSocket(address, port, localAddress, localPort);
|
||||||
|
|
||||||
ss.setEnabledProtocols(protocols);
|
ss.setEnabledProtocols(protocols);
|
||||||
ss.setEnabledCipherSuites(ciphers);
|
|
||||||
|
|
||||||
return ss;
|
return ss;
|
||||||
}
|
}
|
||||||
@@ -167,7 +165,6 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
|||||||
final SSLSocket ss = (SSLSocket) factory.createSocket(host, port, localHost, localPort);
|
final SSLSocket ss = (SSLSocket) factory.createSocket(host, port, localHost, localPort);
|
||||||
|
|
||||||
ss.setEnabledProtocols(protocols);
|
ss.setEnabledProtocols(protocols);
|
||||||
ss.setEnabledCipherSuites(ciphers);
|
|
||||||
|
|
||||||
return ss;
|
return ss;
|
||||||
}
|
}
|
||||||
@@ -186,7 +183,6 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
|||||||
final SSLSocket ss = (SSLSocket) factory.createSocket(host, port);
|
final SSLSocket ss = (SSLSocket) factory.createSocket(host, port);
|
||||||
|
|
||||||
ss.setEnabledProtocols(protocols);
|
ss.setEnabledProtocols(protocols);
|
||||||
ss.setEnabledCipherSuites(ciphers);
|
|
||||||
|
|
||||||
return ss;
|
return ss;
|
||||||
}
|
}
|
||||||
@@ -205,7 +201,6 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
|||||||
final SSLSocket ss = (SSLSocket) factory.createSocket(host, port);
|
final SSLSocket ss = (SSLSocket) factory.createSocket(host, port);
|
||||||
|
|
||||||
ss.setEnabledProtocols(protocols);
|
ss.setEnabledProtocols(protocols);
|
||||||
ss.setEnabledCipherSuites(ciphers);
|
|
||||||
|
|
||||||
return ss;
|
return ss;
|
||||||
}
|
}
|
||||||
@@ -226,7 +221,6 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
|||||||
sslCtxt.init(km, tm, random);
|
sslCtxt.init(km, tm, random);
|
||||||
|
|
||||||
protocols = getProtocolList();
|
protocols = getProtocolList();
|
||||||
ciphers = getCipherList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -240,9 +234,7 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
|||||||
private void initSSLSocketFactoryEx(SSLContext ctx)
|
private void initSSLSocketFactoryEx(SSLContext ctx)
|
||||||
throws NoSuchAlgorithmException, KeyManagementException {
|
throws NoSuchAlgorithmException, KeyManagementException {
|
||||||
sslCtxt = ctx;
|
sslCtxt = ctx;
|
||||||
|
|
||||||
protocols = getProtocolList();
|
protocols = getProtocolList();
|
||||||
ciphers = getCipherList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -286,98 +278,10 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
|||||||
return aa.toArray(new String[0]);
|
return aa.toArray(new String[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the cipher list.
|
|
||||||
*
|
|
||||||
* @return the cipher list
|
|
||||||
*/
|
|
||||||
protected String[] getCipherList() {
|
|
||||||
final String[] preferredCiphers = {
|
|
||||||
// *_CHACHA20_POLY1305 are 3x to 4x faster than existing cipher suites.
|
|
||||||
// http://googleonlinesecurity.blogspot.com/2014/04/speeding-up-and-strengthening-https.html
|
|
||||||
// Use them if available. Normative names can be found at (TLS spec depends on IPSec spec):
|
|
||||||
// http://tools.ietf.org/html/draft-nir-ipsecme-chacha20-poly1305-01
|
|
||||||
// http://tools.ietf.org/html/draft-mavrogiannopoulos-chacha-tls-02
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
|
||||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_SHA",
|
|
||||||
"TLS_ECDHE_RSA_WITH_CHACHA20_SHA",
|
|
||||||
"TLS_DHE_RSA_WITH_CHACHA20_POLY1305",
|
|
||||||
"TLS_RSA_WITH_CHACHA20_POLY1305",
|
|
||||||
"TLS_DHE_RSA_WITH_CHACHA20_SHA",
|
|
||||||
"TLS_RSA_WITH_CHACHA20_SHA",
|
|
||||||
// Done with bleeding edge, back to TLS v1.2 and below
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
|
||||||
"TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
|
||||||
"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
|
|
||||||
// TLS v1.0 (with some SSLv3 interop)
|
|
||||||
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA384",
|
|
||||||
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
|
|
||||||
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
|
|
||||||
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
|
|
||||||
"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
|
||||||
"TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
|
|
||||||
"SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA",
|
|
||||||
"SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA",
|
|
||||||
// RSA key transport sucks, but they are needed as a fallback.
|
|
||||||
// For example, microsoft.com fails under all versions of TLS
|
|
||||||
// if they are not included. If only TLS 1.0 is available at
|
|
||||||
// the client, then google.com will fail too. TLS v1.3 is
|
|
||||||
// trying to deprecate them, so it will be interesteng to see
|
|
||||||
// what happens.
|
|
||||||
"TLS_RSA_WITH_AES_256_CBC_SHA256",
|
|
||||||
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
|
||||||
"TLS_RSA_WITH_AES_128_CBC_SHA256",
|
|
||||||
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
|
||||||
};
|
|
||||||
|
|
||||||
String[] availableCiphers;
|
|
||||||
|
|
||||||
try {
|
|
||||||
final SSLSocketFactory factory = sslCtxt.getSocketFactory();
|
|
||||||
availableCiphers = factory.getSupportedCipherSuites();
|
|
||||||
Arrays.sort(availableCiphers);
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOGGER.debug("Error retrieving ciphers", e);
|
|
||||||
return new String[]{
|
|
||||||
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
|
|
||||||
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
|
|
||||||
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
|
|
||||||
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
|
|
||||||
"TLS_RSA_WITH_AES_256_CBC_SHA256",
|
|
||||||
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
|
||||||
"TLS_RSA_WITH_AES_128_CBC_SHA256",
|
|
||||||
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
|
||||||
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<String> aa = new ArrayList<String>();
|
|
||||||
for (String preferredCipher : preferredCiphers) {
|
|
||||||
final int idx = Arrays.binarySearch(availableCiphers, preferredCipher);
|
|
||||||
if (idx >= 0) {
|
|
||||||
aa.add(preferredCipher);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
aa.add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV");
|
|
||||||
|
|
||||||
return aa.toArray(new String[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SSL context.
|
* The SSL context.
|
||||||
*/
|
*/
|
||||||
private SSLContext sslCtxt;
|
private SSLContext sslCtxt;
|
||||||
/**
|
|
||||||
* The cipher suites.
|
|
||||||
*/
|
|
||||||
private String[] ciphers;
|
|
||||||
/**
|
/**
|
||||||
* The protocols.
|
* The protocols.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public final class Settings {
|
|||||||
/**
|
/**
|
||||||
* The key to obtain the application name.
|
* The key to obtain the application name.
|
||||||
*/
|
*/
|
||||||
public static final String APPLICATION_VAME = "application.name";
|
public static final String APPLICATION_NAME = "application.name";
|
||||||
/**
|
/**
|
||||||
* The key to obtain the application version.
|
* The key to obtain the application version.
|
||||||
*/
|
*/
|
||||||
@@ -288,6 +288,14 @@ public final class Settings {
|
|||||||
* The properties key for whether the OpenSSL analyzer is enabled.
|
* The properties key for whether the OpenSSL analyzer is enabled.
|
||||||
*/
|
*/
|
||||||
public static final String ANALYZER_OPENSSL_ENABLED = "analyzer.openssl.enabled";
|
public static final String ANALYZER_OPENSSL_ENABLED = "analyzer.openssl.enabled";
|
||||||
|
/**
|
||||||
|
* The properties key for whether the cocoapods analyzer is enabled.
|
||||||
|
*/
|
||||||
|
public static final String ANALYZER_COCOAPODS_ENABLED = "analyzer.cocoapods.enabled";
|
||||||
|
/**
|
||||||
|
* The properties key for whether the SWIFT package manager analyzer is enabled.
|
||||||
|
*/
|
||||||
|
public static final String ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED = "analyzer.swift.package.manager.enabled";
|
||||||
/**
|
/**
|
||||||
* The properties key for the Central search URL.
|
* The properties key for the Central search URL.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import java.net.PasswordAuthentication;
|
|||||||
import java.net.Proxy;
|
import java.net.Proxy;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
import java.security.KeyManagementException;
|
import java.security.KeyManagementException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
@@ -188,7 +189,7 @@ public final class URLConnectionFactory {
|
|||||||
* @param url the URL
|
* @param url the URL
|
||||||
* @param conn the connection
|
* @param conn the connection
|
||||||
*/
|
*/
|
||||||
private static void configureTLS(URL url, HttpURLConnection conn) {
|
private static void configureTLS(URL url, URLConnection conn) {
|
||||||
if ("https".equals(url.getProtocol())) {
|
if ("https".equals(url.getProtocol())) {
|
||||||
try {
|
try {
|
||||||
final HttpsURLConnection secCon = (HttpsURLConnection) conn;
|
final HttpsURLConnection secCon = (HttpsURLConnection) conn;
|
||||||
|
|||||||
9
pom.xml
9
pom.xml
@@ -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.4.1</version>
|
<version>1.4.3</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
@@ -360,7 +360,7 @@ Copyright (c) 2012 - Jeremy Long
|
|||||||
<target name="copy xsd to site">
|
<target name="copy xsd to site">
|
||||||
<copy file="dependency-check-core/src/main/resources/schema/dependency-check.1.3.xsd" todir="target/site/"/>
|
<copy file="dependency-check-core/src/main/resources/schema/dependency-check.1.3.xsd" todir="target/site/"/>
|
||||||
<copy file="dependency-check-core/src/main/resources/schema/dependency-suppression.1.1.xsd" todir="target/site/"/>
|
<copy file="dependency-check-core/src/main/resources/schema/dependency-suppression.1.1.xsd" todir="target/site/"/>
|
||||||
<copy file="dependency-check-core/src/main/resources/schema/dependency-hint.1.0.xsd" todir="target/site/"/>
|
<copy file="dependency-check-core/src/main/resources/schema/dependency-hint.1.1.xsd" todir="target/site/"/>
|
||||||
</target>
|
</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
@@ -671,6 +671,11 @@ Copyright (c) 2012 - Jeremy Long
|
|||||||
<artifactId>plexus-sec-dispatcher</artifactId>
|
<artifactId>plexus-sec-dispatcher</artifactId>
|
||||||
<version>1.4</version>
|
<version>1.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven.shared</groupId>
|
||||||
|
<artifactId>maven-dependency-tree</artifactId>
|
||||||
|
<version>2.2</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish</groupId>
|
<groupId>org.glassfish</groupId>
|
||||||
<artifactId>javax.json</artifactId>
|
<artifactId>javax.json</artifactId>
|
||||||
|
|||||||
@@ -13,6 +13,6 @@
|
|||||||
^ \* See the License for the specific language governing permissions and\s*$
|
^ \* See the License for the specific language governing permissions and\s*$
|
||||||
^ \* limitations under the License\.\s*$
|
^ \* limitations under the License\.\s*$
|
||||||
^ \*\s*$
|
^ \*\s*$
|
||||||
^ \* Copyright \(c\) 201[0-9] (Jeremy Long|Steve Springett|Bianca Jiang|The OWASP Foundation|Institute for Defense Analyses)\. All Rights Reserved\.\s*$
|
^ \* Copyright \(c\) 201[0-9] (Jeremy Long|Steve Springett|Bianca Jiang|IBM Corporation|The OWASP Foundation|Institute for Defense Analyses)\. All Rights Reserved\.\s*$
|
||||||
^ \*/\s*$
|
^ \*/\s*$
|
||||||
^package
|
^package
|
||||||
|
|||||||
@@ -7,8 +7,9 @@
|
|||||||
<suppressions>
|
<suppressions>
|
||||||
<suppress checks=".*" files=".*[\\/]package-info\.java" />
|
<suppress checks=".*" files=".*[\\/]package-info\.java" />
|
||||||
<suppress checks=".*" files=".*[\\/]org[\\/]owasp[\\/]dependencycheck[\\/]utils[\\/]Filter.java" />
|
<suppress checks=".*" files=".*[\\/]org[\\/]owasp[\\/]dependencycheck[\\/]utils[\\/]Filter.java" />
|
||||||
<suppress checks=".*" files=".*[\\/]org[\\/]owasp[\\/]dependencycheck[\\/]utils[\\/]Checksum.java" />
|
<!--suppress checks=".*" files=".*[\\/]org[\\/]owasp[\\/]dependencycheck[\\/]utils[\\/]Checksum.java" /-->
|
||||||
<suppress checks=".*" files=".*[\\/]generated[\\/].*.java" />
|
<suppress checks=".*" files=".*[\\/]generated[\\/].*.java" />
|
||||||
<suppress checks=".*" files=".*[\\/]maven-plugin-plugin-sources[\\/].*.properties" />
|
<suppress checks=".*" files=".*[\\/]maven-plugin-plugin-sources[\\/].*.properties" />
|
||||||
<suppress checks=".*" files=".*[\\/]org[\\/]owasp[\\/]dependencycheck[\\/]org[\\/]apache[\\/].*.java" />
|
<!--suppress checks=".*" files=".*[\\/]org[\\/]owasp[\\/]dependencycheck[\\/]org[\\/]apache[\\/].*.java" /-->
|
||||||
|
<suppress checks="RegexpHeader" files=".*[\\/]org[\\/]owasp[\\/]dependencycheck[\\/]utils[\\/]SSLSocketFactoryEx.java" />
|
||||||
</suppressions>
|
</suppressions>
|
||||||
@@ -20,6 +20,8 @@ format | The report format to be generated (HTML, XML, VULN, ALL).
|
|||||||
outputDirectory | The location to write the report(s). This directory will be located in the build directory. | build/reports
|
outputDirectory | The location to write the report(s). This directory will be located in the build directory. | build/reports
|
||||||
skipTestGroups | When set to true (the default) all dependency groups that being with 'test' will be skipped. | true
|
skipTestGroups | When set to true (the default) all dependency groups that being with 'test' will be skipped. | true
|
||||||
suppressionFile | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html) |
|
suppressionFile | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html) |
|
||||||
|
skipConfigurations | A list of configurations that will be skipped. This is mutually exclusive with the scanConfigurations property. | `[]` which means no configuration is skipped.
|
||||||
|
scanConfigurations | A list of configurations that will be scanned, all other configurations are skipped. This is mutually exclusive with the skipConfigurations property. | `[]` which implicitly means all configurations get scanned.
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
```groovy
|
```groovy
|
||||||
|
|||||||
Reference in New Issue
Block a user