mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-01-14 15:53:36 +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~
|
||||
#coverity
|
||||
/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
|
||||
================
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
|
||||
<parent>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.4.1</version>
|
||||
<version>1.4.3</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dependency-check-ant</artifactId>
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
|
||||
<parent>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.4.1</version>
|
||||
<version>1.4.3</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dependency-check-cli</artifactId>
|
||||
|
||||
@@ -158,8 +158,13 @@ public class App {
|
||||
exitCode = -4;
|
||||
}
|
||||
try {
|
||||
runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getProjectName(), cli.getScanFiles(),
|
||||
cli.getExcludeList(), cli.getSymLinkDepth());
|
||||
final String[] scanFiles = cli.getScanFiles();
|
||||
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) {
|
||||
LOGGER.error("An invalid scan path was detected; unable to scan '//*' paths");
|
||||
exitCode = -10;
|
||||
@@ -293,7 +298,7 @@ public class App {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
if (exCol != null && exCol.getExceptions().size()>0) {
|
||||
if (exCol != null && exCol.getExceptions().size() > 0) {
|
||||
throw exCol;
|
||||
}
|
||||
} finally {
|
||||
@@ -301,7 +306,7 @@ public class App {
|
||||
engine.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -196,6 +196,10 @@ public final class CliParser {
|
||||
isValid = false;
|
||||
final String msg = String.format("Invalid '%s' argument: '%s'%nUnable to scan paths that start with '//'.", argumentName, path);
|
||||
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() {
|
||||
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"));
|
||||
System.out.println(version);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
<parent>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.4.1</version>
|
||||
<version>1.4.3</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dependency-check-core</artifactId>
|
||||
|
||||
@@ -368,7 +368,7 @@ public class Engine implements FileFilter {
|
||||
}
|
||||
|
||||
LOGGER.debug("\n----------------------------------------------------\nBEGIN ANALYSIS\n----------------------------------------------------");
|
||||
LOGGER.info("Analysis Starting");
|
||||
LOGGER.info("Analysis Started");
|
||||
final long analysisStart = System.currentTimeMillis();
|
||||
|
||||
// analysis phases
|
||||
|
||||
@@ -130,15 +130,26 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
|
||||
}
|
||||
} else {
|
||||
file = new File(suppressionFilePath);
|
||||
InputStream suppressionsFromClasspath = null;
|
||||
if (!file.exists()) {
|
||||
final InputStream suppressionsFromClasspath = this.getClass().getClassLoader().getResourceAsStream(suppressionFilePath);
|
||||
if (suppressionsFromClasspath != null) {
|
||||
deleteTempFile = true;
|
||||
file = FileUtils.getTempFile("suppression", "xml");
|
||||
try {
|
||||
org.apache.commons.io.FileUtils.copyInputStreamToFile(suppressionsFromClasspath, file);
|
||||
} catch (IOException ex) {
|
||||
throwSuppressionParseException("Unable to locate suppressions file in classpath", ex);
|
||||
try {
|
||||
suppressionsFromClasspath = this.getClass().getClassLoader().getResourceAsStream(suppressionFilePath);
|
||||
if (suppressionsFromClasspath != null) {
|
||||
deleteTempFile = true;
|
||||
file = FileUtils.getTempFile("suppression", "xml");
|
||||
try {
|
||||
org.apache.commons.io.FileUtils.copyInputStreamToFile(suppressionsFromClasspath, file);
|
||||
} 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 {
|
||||
if (archive != null && destination != null) {
|
||||
String archiveExt = FileUtils.getFileExtension(archive.getName());
|
||||
if (archiveExt == null) {
|
||||
return;
|
||||
}
|
||||
archiveExt = archiveExt.toLowerCase();
|
||||
|
||||
FileInputStream fis;
|
||||
try {
|
||||
fis = new FileInputStream(archive);
|
||||
@@ -364,7 +370,6 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
LOGGER.debug("", ex);
|
||||
throw new AnalysisException("Archive file was not found.", ex);
|
||||
}
|
||||
final String archiveExt = FileUtils.getFileExtension(archive.getName()).toLowerCase();
|
||||
try {
|
||||
if (ZIPPABLES.contains(archiveExt)) {
|
||||
final BufferedInputStream in = new BufferedInputStream(fis);
|
||||
@@ -414,8 +419,9 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
if ("jar".equals(archiveExt) && in.markSupported()) {
|
||||
in.mark(7);
|
||||
final byte[] b = new byte[7];
|
||||
in.read(b);
|
||||
if (b[0] == '#'
|
||||
final int read = in.read(b);
|
||||
if (read == 7
|
||||
&& b[0] == '#'
|
||||
&& b[1] == '!'
|
||||
&& b[2] == '/'
|
||||
&& 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 javax.xml.parsers.ParserConfigurationException;
|
||||
import org.owasp.dependencycheck.exception.InitializationException;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
private List<String> buildArgumentList() {
|
||||
protected List<String> buildArgumentList() {
|
||||
// Use file.separator as a wild guess as to whether this is Windows
|
||||
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) {
|
||||
args.add(Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH));
|
||||
} else {
|
||||
} else if (isInPath("mono")) {
|
||||
args.add("mono");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
args.add(grokAssemblyExe.getPath());
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
@@ -116,6 +118,10 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
}
|
||||
|
||||
final List<String> args = buildArgumentList();
|
||||
if (args == null) {
|
||||
LOGGER.warn("Assembly Analyzer was unable to execute");
|
||||
return;
|
||||
}
|
||||
args.add(dependency.getActualFilePath());
|
||||
final ProcessBuilder pb = new ProcessBuilder(args);
|
||||
Document doc = null;
|
||||
@@ -203,8 +209,6 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
IOUtils.copy(is, fos);
|
||||
|
||||
grokAssemblyExe = tempFile;
|
||||
// Set the temp file to get deleted when we're done
|
||||
grokAssemblyExe.deleteOnExit();
|
||||
LOGGER.debug("Extracted GrokAssembly.exe to {}", grokAssemblyExe.getPath());
|
||||
} catch (IOException ioe) {
|
||||
this.setEnabled(false);
|
||||
@@ -229,6 +233,22 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
// Now, need to see if GrokAssembly actually runs from this location.
|
||||
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 {
|
||||
final ProcessBuilder pb = new ProcessBuilder(args);
|
||||
final Process p = pb.start();
|
||||
@@ -246,6 +266,7 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
throw new InitializationException("Could not execute .NET AssemblyAnalyzer");
|
||||
}
|
||||
} catch (InitializationException e) {
|
||||
setEnabled(false);
|
||||
throw e;
|
||||
} catch (Throwable e) {
|
||||
LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer;\n"
|
||||
@@ -272,10 +293,12 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
super.close();
|
||||
try {
|
||||
if (grokAssemblyExe != null && !grokAssemblyExe.delete()) {
|
||||
LOGGER.debug("Unable to delete temporary GrokAssembly.exe; attempting delete on exit");
|
||||
grokAssemblyExe.deleteOnExit();
|
||||
}
|
||||
} catch (SecurityException se) {
|
||||
LOGGER.debug("Can't delete temporary GrokAssembly.exe");
|
||||
grokAssemblyExe.deleteOnExit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,4 +343,29 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
protected String getAnalyzerEnabledSettingKey() {
|
||||
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 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) {
|
||||
Dependency currentDep = dependency;
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.index.CorruptIndexException;
|
||||
import org.apache.lucene.queryparser.classic.ParseException;
|
||||
@@ -550,7 +551,7 @@ public class CPEAnalyzer implements Analyzer {
|
||||
final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>();
|
||||
|
||||
//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.
|
||||
for (Confidence conf : Confidence.values()) {
|
||||
for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) {
|
||||
@@ -801,6 +802,12 @@ public class CPEAnalyzer implements Analyzer {
|
||||
*/
|
||||
@Override
|
||||
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);
|
||||
if (conf == 0) {
|
||||
conf = this.evidenceConfidence.compareTo(o.evidenceConfidence);
|
||||
@@ -809,6 +816,7 @@ public class CPEAnalyzer implements Analyzer {
|
||||
}
|
||||
}
|
||||
return conf;
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +229,8 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
LOGGER.warn("Unable to download pom.xml for {} from Central; "
|
||||
+ "this could result in undetected CPE/CVEs.", dependency.getFileName());
|
||||
} 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
while (subIterator.hasNext()) {
|
||||
final Dependency nextDependency = subIterator.next();
|
||||
Dependency main = null;
|
||||
if (hashesMatch(dependency, nextDependency) && !containedInWar(dependency.getFilePath())
|
||||
&& !containedInWar(nextDependency.getFilePath())) {
|
||||
if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) {
|
||||
@@ -143,8 +144,14 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|
||||
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
||||
break; //since we merged into the next dependency - skip forward to the next in mainIterator
|
||||
}
|
||||
} else if (isSameRubyGem(dependency, nextDependency)) {
|
||||
final Dependency main = getMainGemspecDependency(dependency, nextDependency);
|
||||
} else if ((main = getMainGemspecDependency(dependency, nextDependency)) != null) {
|
||||
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) {
|
||||
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
||||
} else {
|
||||
@@ -302,10 +309,13 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|
||||
String right = rFile.getParent();
|
||||
if (left == null) {
|
||||
return right == null;
|
||||
} else if (right == null) {
|
||||
return false;
|
||||
}
|
||||
if (left.equalsIgnoreCase(right)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (left.matches(".*[/\\\\]repository[/\\\\].*") && right.matches(".*[/\\\\]repository[/\\\\].*")) {
|
||||
left = getBaseRepoPath(left);
|
||||
right = getBaseRepoPath(right);
|
||||
@@ -376,6 +386,49 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|
||||
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'
|
||||
* 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
|
||||
*/
|
||||
//CSOFF: WhitespaceAfter
|
||||
private static final NameFileFilter IGNORED_FILES = new NameFileFilter(new String[]{
|
||||
"__init__.py",
|
||||
"__init__.pyc",
|
||||
"__init__.pyo",
|
||||
});
|
||||
"__init__.pyo",});
|
||||
//CSON: WhitespaceAfter
|
||||
|
||||
/**
|
||||
* Collects information about the file name.
|
||||
@@ -93,26 +94,27 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer {
|
||||
|
||||
//add version evidence
|
||||
final DependencyVersion version = DependencyVersionUtil.parseVersion(fileName);
|
||||
final String packageName = DependencyVersionUtil.parsePreVersion(fileName);
|
||||
if (version != null) {
|
||||
// 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
|
||||
// struts2-core.jar
|
||||
if (version.getVersionParts() == null || version.getVersionParts().size() < 2) {
|
||||
dependency.getVersionEvidence().addEvidence("file", "name",
|
||||
dependency.getVersionEvidence().addEvidence("file", "version",
|
||||
version.toString(), Confidence.MEDIUM);
|
||||
} else {
|
||||
dependency.getVersionEvidence().addEvidence("file", "version",
|
||||
version.toString(), Confidence.HIGHEST);
|
||||
}
|
||||
dependency.getVersionEvidence().addEvidence("file", "name",
|
||||
fileName, Confidence.MEDIUM);
|
||||
packageName, Confidence.MEDIUM);
|
||||
}
|
||||
|
||||
if (!IGNORED_FILES.accept(f)) {
|
||||
dependency.getProductEvidence().addEvidence("file", "name",
|
||||
fileName, Confidence.HIGH);
|
||||
packageName, Confidence.HIGH);
|
||||
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()) {
|
||||
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.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) {
|
||||
return;
|
||||
}
|
||||
@@ -311,14 +314,21 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer {
|
||||
} else {
|
||||
file = new File(filePath);
|
||||
if (!file.exists()) {
|
||||
final InputStream fromClasspath = this.getClass().getClassLoader().getResourceAsStream(filePath);
|
||||
if (fromClasspath != null) {
|
||||
deleteTempFile = true;
|
||||
file = FileUtils.getTempFile("hint", "xml");
|
||||
try {
|
||||
org.apache.commons.io.FileUtils.copyInputStreamToFile(fromClasspath, file);
|
||||
} catch (IOException ex) {
|
||||
throw new HintParseException("Unable to locate suppressions file in classpath", ex);
|
||||
InputStream fromClasspath = null;
|
||||
try {
|
||||
fromClasspath = this.getClass().getClassLoader().getResourceAsStream(filePath);
|
||||
if (fromClasspath != null) {
|
||||
deleteTempFile = true;
|
||||
file = FileUtils.getTempFile("hint", "xml");
|
||||
try {
|
||||
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 {
|
||||
pom = PomUtils.readPom(externalPom);
|
||||
}
|
||||
pom.processProperties(pomProperties);
|
||||
foundSomething |= setPomEvidence(dependency, pom, classes);
|
||||
if (pom != null) {
|
||||
pom.processProperties(pomProperties);
|
||||
foundSomething |= setPomEvidence(dependency, pom, classes);
|
||||
}
|
||||
}
|
||||
} catch (AnalysisException ex) {
|
||||
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");
|
||||
try {
|
||||
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);
|
||||
fos = new FileOutputStream(file);
|
||||
IOUtils.copy(input, fos);
|
||||
@@ -487,7 +492,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
}
|
||||
|
||||
final String originalGroupID = groupid;
|
||||
if (groupid.startsWith("org.") || groupid.startsWith("com.")) {
|
||||
if (groupid != null && (groupid.startsWith("org.") || groupid.startsWith("com."))) {
|
||||
groupid = groupid.substring(4);
|
||||
}
|
||||
|
||||
@@ -496,7 +501,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
}
|
||||
|
||||
final String originalArtifactID = artifactid;
|
||||
if (artifactid.startsWith("org.") || artifactid.startsWith("com.")) {
|
||||
if (artifactid != null && (artifactid.startsWith("org.") || artifactid.startsWith("com."))) {
|
||||
artifactid = artifactid.substring(4);
|
||||
}
|
||||
|
||||
@@ -685,7 +690,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
foundSomething = true;
|
||||
versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
|
||||
} else if ("specification-version".equalsIgnoreCase(key)) {
|
||||
specificationVersion = key;
|
||||
specificationVersion = value;
|
||||
} else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
|
||||
foundSomething = true;
|
||||
vendorEvidence.addEvidence(source, key, value, Confidence.HIGH);
|
||||
@@ -704,17 +709,12 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
addMatchingValues(classInformation, value, productEvidence);
|
||||
// //the following caused false positives.
|
||||
// } 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)) {
|
||||
foundSomething = true;
|
||||
versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
|
||||
} else if (key.equalsIgnoreCase(Attributes.Name.MAIN_CLASS.toString())) {
|
||||
continue;
|
||||
//skipping main class as if this has important information to add
|
||||
// it will be added during class name analysis... if other fields
|
||||
// have the information from the class name then they will get added...
|
||||
//skipping main class as if this has important information to add it will be added during class name analysis...
|
||||
} else {
|
||||
key = key.toLowerCase();
|
||||
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; "
|
||||
+ "this could result in undetected CPE/CVEs.", dependency.getFileName());
|
||||
} 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import org.apache.commons.io.filefilter.NameFileFilter;
|
||||
import org.apache.commons.io.filefilter.SuffixFileFilter;
|
||||
import org.apache.commons.io.input.AutoCloseInputStream;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||
@@ -228,10 +228,13 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
throw new AnalysisException(ex);
|
||||
}
|
||||
|
||||
collectWheelMetadata(
|
||||
dependency,
|
||||
getMatchingFile(getMatchingFile(temp, folderFilter),
|
||||
metadataFilter));
|
||||
File matchingFile = getMatchingFile(temp, folderFilter);
|
||||
if (matchingFile != null) {
|
||||
matchingFile = getMatchingFile(matchingFile, metadataFilter);
|
||||
if (matchingFile != null) {
|
||||
collectWheelMetadata(dependency, matchingFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -354,13 +357,22 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
if (null == manifest) {
|
||||
LOGGER.debug("Manifest file not found.");
|
||||
} else {
|
||||
InputStream in = null;
|
||||
try {
|
||||
result.load(new AutoCloseInputStream(new BufferedInputStream(
|
||||
new FileInputStream(manifest))));
|
||||
in = new BufferedInputStream(new FileInputStream(manifest));
|
||||
result.load(in);
|
||||
} catch (MessagingException e) {
|
||||
LOGGER.warn(e.getMessage(), e);
|
||||
} catch (FileNotFoundException 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;
|
||||
|
||||
@@ -23,25 +23,26 @@ import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||
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.Dependency;
|
||||
import org.owasp.dependencycheck.dependency.Reference;
|
||||
import org.owasp.dependencycheck.dependency.Vulnerability;
|
||||
import org.owasp.dependencycheck.exception.InitializationException;
|
||||
import org.owasp.dependencycheck.utils.FileFilterBuilder;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
import org.slf4j.Logger;
|
||||
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
|
||||
@@ -279,11 +280,16 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
}
|
||||
final File parentFile = dependency.getActualFile().getParentFile();
|
||||
final Process process = launchBundleAudit(parentFile);
|
||||
final int exitValue;
|
||||
try {
|
||||
process.waitFor();
|
||||
exitValue = process.waitFor();
|
||||
} catch (InterruptedException 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 errReader = null;
|
||||
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 {
|
||||
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);
|
||||
|
||||
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
|
||||
* 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;
|
||||
|
||||
@@ -43,7 +43,7 @@ import org.owasp.dependencycheck.dependency.Dependency;
|
||||
* {@link RubyGemspecAnalyzer}, so it will enabled/disabled with
|
||||
* {@link RubyGemspecAnalyzer}.
|
||||
*
|
||||
* @author Bianca Jiang (biancajiang@gmail.com)
|
||||
* @author Bianca Jiang (https://twitter.com/biancajiang)
|
||||
*/
|
||||
@Experimental
|
||||
public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer {
|
||||
|
||||
@@ -217,6 +217,9 @@ public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
return name.contains(VERSION_FILE_NAME);
|
||||
}
|
||||
});
|
||||
if (matchingFiles == null) {
|
||||
return;
|
||||
}
|
||||
for (File f : matchingFiles) {
|
||||
try {
|
||||
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.
|
||||
*
|
||||
* @param rootURL the URL of the repository on which searches should execute. Only parameters are added to this (so it should
|
||||
* end in /select)
|
||||
* @param rootURL the URL of the repository on which searches should
|
||||
* execute. Only parameters are added to this (so it should end in /select)
|
||||
*/
|
||||
public CentralSearch(URL 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
|
||||
* populated with the GAV.
|
||||
* Searches the configured Central URL for the given sha1 hash. If the
|
||||
* artifact is found, a <code>MavenArtifact</code> is populated with the
|
||||
* GAV.
|
||||
*
|
||||
* @param sha1 the SHA-1 hash string for which to search
|
||||
* @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 {
|
||||
if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) {
|
||||
throw new IllegalArgumentException("Invalid SHA1 format");
|
||||
}
|
||||
|
||||
List<MavenArtifact> result = null;
|
||||
final URL url = new URL(rootURL + String.format("?q=1:\"%s\"&wt=xml", sha1));
|
||||
|
||||
LOGGER.debug("Searching Central url {}", url);
|
||||
@@ -116,7 +118,7 @@ public class CentralSearch {
|
||||
if ("0".equals(numFound)) {
|
||||
missing = true;
|
||||
} else {
|
||||
final List<MavenArtifact> result = new ArrayList<MavenArtifact>();
|
||||
result = new ArrayList<MavenArtifact>();
|
||||
final NodeList docs = (NodeList) xpath.evaluate("/response/result/doc", doc, XPathConstants.NODESET);
|
||||
for (int i = 0; i < docs.getLength(); i++) {
|
||||
final String g = xpath.evaluate("./str[@name='g']", docs.item(i));
|
||||
@@ -144,16 +146,12 @@ public class CentralSearch {
|
||||
useHTTPS = true;
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.trace("Version: {}", v);
|
||||
result.add(new MavenArtifact(g, a, v, jarAvailable, pomAvailable, useHTTPS));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
// Anything else is jacked up XML stuff that we really can't recover
|
||||
// from well
|
||||
// Anything else is jacked up XML stuff that we really can't recover from well
|
||||
throw new IOException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
@@ -162,10 +160,9 @@ public class CentralSearch {
|
||||
}
|
||||
} else {
|
||||
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");
|
||||
}
|
||||
|
||||
return null;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,10 +209,13 @@ public final class CpeMemoryIndex {
|
||||
|
||||
final Set<Pair<String, String>> data = cve.getVendorProductList();
|
||||
for (Pair<String, String> pair : data) {
|
||||
v.setStringValue(pair.getLeft());
|
||||
p.setStringValue(pair.getRight());
|
||||
indexWriter.addDocument(doc);
|
||||
resetFieldAnalyzer();
|
||||
//todo figure out why there are null products
|
||||
if (pair.getLeft() != null && pair.getRight() != null) {
|
||||
v.setStringValue(pair.getLeft());
|
||||
p.setStringValue(pair.getRight());
|
||||
indexWriter.addDocument(doc);
|
||||
resetFieldAnalyzer();
|
||||
}
|
||||
}
|
||||
} catch (DatabaseException ex) {
|
||||
LOGGER.debug("", ex);
|
||||
|
||||
@@ -36,8 +36,10 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Loads the configured database driver and returns the database connection. If the embedded H2 database is used obtaining a
|
||||
* connection will ensure the database file exists and that the appropriate table structure has been created.
|
||||
* Loads the configured database driver and returns the database connection. If
|
||||
* 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
|
||||
*/
|
||||
@@ -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
|
||||
* successfully.
|
||||
* Initializes the connection factory. Ensuring that the appropriate drivers
|
||||
* 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.
|
||||
if (connectionString != null) {
|
||||
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
|
||||
* unregistered prior to the 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.
|
||||
* Cleans up resources and unloads any registered database drivers. This
|
||||
* needs to be called to ensure the driver is unregistered prior to the
|
||||
* 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) {
|
||||
try {
|
||||
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
|
||||
* @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 {
|
||||
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
|
||||
* @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 {
|
||||
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
|
||||
* @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
|
||||
* current schema version is 2.9 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.
|
||||
* Updates the database schema by loading the upgrade script for the version
|
||||
* specified. The intended use is that if the current schema version is 2.9
|
||||
* 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 appExpectedVersion the schema version that the application expects
|
||||
* @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)
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @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 {
|
||||
ResultSet rs = null;
|
||||
@@ -359,7 +374,13 @@ public final class ConnectionFactory {
|
||||
rs = ps.executeQuery();
|
||||
if (rs.next()) {
|
||||
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));
|
||||
if (db == null) {
|
||||
throw new DatabaseException("Invalid database schema");
|
||||
}
|
||||
if (appDbVersion.compareTo(db) > 0) {
|
||||
LOGGER.debug("Current Schema: {}", DB_SCHEMA_VERSION);
|
||||
LOGGER.debug("DB Schema: {}", rs.getString(1));
|
||||
|
||||
@@ -87,10 +87,12 @@ public class CveDB {
|
||||
open();
|
||||
try {
|
||||
final String databaseProductName = conn.getMetaData().getDatabaseProductName();
|
||||
batchSupported = conn.getMetaData().supportsBatchUpdates();
|
||||
LOGGER.debug("Database dialect: {}", databaseProductName);
|
||||
final Locale dbDialect = new Locale(databaseProductName);
|
||||
statementBundle = ResourceBundle.getBundle("data/dbStatements", dbDialect);
|
||||
if ("mysql".equalsIgnoreCase(databaseProductName)) {
|
||||
batchSupported = false;
|
||||
}
|
||||
} catch (SQLException se) {
|
||||
LOGGER.warn("Problem loading database specific dialect!", se);
|
||||
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 "
|
||||
+ "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",
|
||||
dd, dd, Settings.getString(Settings.KEYS.APPLICATION_VAME));
|
||||
dd, dd, Settings.getString(Settings.KEYS.APPLICATION_NAME));
|
||||
LOGGER.debug("", ex);
|
||||
} finally {
|
||||
DBUtils.closeResultSet(rs);
|
||||
|
||||
@@ -158,6 +158,7 @@ public class CpeUpdater extends BaseUpdater implements CachedWebDataSource {
|
||||
final String originalPath = file.getPath();
|
||||
final File gzip = new File(originalPath + ".gz");
|
||||
if (gzip.isFile() && !gzip.delete()) {
|
||||
LOGGER.debug("Failed to delete intial temporary file {}", gzip.toString());
|
||||
gzip.deleteOnExit();
|
||||
}
|
||||
if (!file.renameTo(gzip)) {
|
||||
@@ -192,8 +193,9 @@ public class CpeUpdater extends BaseUpdater implements CachedWebDataSource {
|
||||
LOGGER.trace("ignore", ex);
|
||||
}
|
||||
}
|
||||
if (gzip.isFile()) {
|
||||
FileUtils.deleteQuietly(gzip);
|
||||
if (gzip.isFile() && !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();
|
||||
}
|
||||
} 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) {
|
||||
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) {
|
||||
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 {
|
||||
if (conn != null) {
|
||||
conn.disconnect();
|
||||
|
||||
@@ -77,10 +77,10 @@ public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource {
|
||||
}
|
||||
if (autoUpdate && checkUpdate()) {
|
||||
final UpdateableNvdCve updateable = getUpdatesNeeded();
|
||||
getProperties().save(DatabaseProperties.LAST_CHECKED, Long.toString(System.currentTimeMillis()));
|
||||
if (updateable.isUpdateNeeded()) {
|
||||
performUpdate(updateable);
|
||||
}
|
||||
getProperties().save(DatabaseProperties.LAST_CHECKED, Long.toString(System.currentTimeMillis()));
|
||||
}
|
||||
} 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);
|
||||
@@ -156,93 +156,86 @@ public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource {
|
||||
* @throws UpdateException is thrown if there is an error updating the
|
||||
* database
|
||||
*/
|
||||
public void performUpdate(UpdateableNvdCve updateable) throws UpdateException {
|
||||
private void performUpdate(UpdateableNvdCve updateable) throws UpdateException {
|
||||
int maxUpdates = 0;
|
||||
try {
|
||||
for (NvdCveInfo cve : updateable) {
|
||||
if (cve.getNeedsUpdate()) {
|
||||
maxUpdates += 1;
|
||||
for (NvdCveInfo cve : updateable) {
|
||||
if (cve.getNeedsUpdate()) {
|
||||
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;
|
||||
|
||||
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 >= 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();
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,8 +55,9 @@ public class DownloadTask implements Callable<Future<ProcessTask>> {
|
||||
* @param nvdCveInfo the NVD CVE info
|
||||
* @param processor the processor service to submit the downloaded files to
|
||||
* @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
|
||||
* dependencies have a correct reference to the global settings.
|
||||
* @param settings a reference to the global settings object; this is
|
||||
* 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
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
public void cleanup() {
|
||||
boolean deleted = false;
|
||||
try {
|
||||
if (first != null && first.exists()) {
|
||||
deleted = first.delete();
|
||||
}
|
||||
} finally {
|
||||
if (first != null && (first.exists() || !deleted)) {
|
||||
first.deleteOnExit();
|
||||
}
|
||||
if (first != null && first.exists() && first.delete()) {
|
||||
LOGGER.debug("Failed to delete first temporary file {}", second.toString());
|
||||
first.deleteOnExit();
|
||||
}
|
||||
try {
|
||||
deleted = false;
|
||||
if (second != null && second.exists()) {
|
||||
deleted = second.delete();
|
||||
}
|
||||
} finally {
|
||||
if (second != null && (second.exists() || !deleted)) {
|
||||
second.deleteOnExit();
|
||||
}
|
||||
if (second != null && second.exists() && !second.delete()) {
|
||||
LOGGER.debug("Failed to delete second temporary file {}", second.toString());
|
||||
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
|
||||
* @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 File gzip = new File(originalPath + ".gz");
|
||||
if (gzip.isFile() && !gzip.delete()) {
|
||||
LOGGER.debug("Failed to delete initial temporary file when extracting 'gz' {}", gzip.toString());
|
||||
gzip.deleteOnExit();
|
||||
}
|
||||
if (!file.renameTo(gzip)) {
|
||||
@@ -312,8 +303,9 @@ public class DownloadTask implements Callable<Future<ProcessTask>> {
|
||||
LOGGER.trace("ignore", ex);
|
||||
}
|
||||
}
|
||||
if (gzip.isFile()) {
|
||||
FileUtils.deleteQuietly(gzip);
|
||||
if (gzip.isFile() && !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;
|
||||
|
||||
import java.io.Serializable;
|
||||
import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||
|
||||
/**
|
||||
* 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
|
||||
public int compareTo(Reference o) {
|
||||
if (source.equals(o.source)) {
|
||||
if (name.equals(o.name)) {
|
||||
if (url.equals(o.url)) {
|
||||
return 0; //they are equal
|
||||
} else {
|
||||
return url.compareTo(o.url);
|
||||
}
|
||||
} else {
|
||||
return name.compareTo(o.name);
|
||||
}
|
||||
} else {
|
||||
return source.compareTo(o.source);
|
||||
}
|
||||
return new CompareToBuilder()
|
||||
.append(source, o.source)
|
||||
.append(name, o.name)
|
||||
.append(url, o.url)
|
||||
.toComparison();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.io.Serializable;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||
|
||||
/**
|
||||
* Contains the information about a vulnerability.
|
||||
@@ -161,7 +162,8 @@ public class Vulnerability implements Serializable, Comparable<Vulnerability> {
|
||||
* Adds an entry for vulnerable software.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
public boolean addVulnerableSoftware(String cpe, String previousVersion) {
|
||||
@@ -390,28 +392,32 @@ public class Vulnerability implements Serializable, Comparable<Vulnerability> {
|
||||
sb.append(this.name);
|
||||
sb.append("\nReferences:\n");
|
||||
for (Reference reference : this.references) {
|
||||
sb.append("=> ");
|
||||
sb.append(reference);
|
||||
sb.append("\n");
|
||||
sb.append("=> ");
|
||||
sb.append(reference);
|
||||
sb.append("\n");
|
||||
}
|
||||
sb.append("\nSoftware:\n");
|
||||
for (VulnerableSoftware software : this.vulnerableSoftware) {
|
||||
sb.append("=> ");
|
||||
sb.append(software);
|
||||
sb.append("\n");
|
||||
sb.append("=> ");
|
||||
sb.append(software);
|
||||
sb.append("\n");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two vulnerabilities.
|
||||
*
|
||||
* @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
|
||||
* the specified vulnerability
|
||||
* @return a negative integer, zero, or a positive integer as this object is
|
||||
* less than, equal to, or greater than the specified vulnerability
|
||||
*/
|
||||
@Override
|
||||
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.
|
||||
*
|
||||
* @param cpeId a CPE identifier
|
||||
* @param previous a flag indicating whether or not all previous versions were affected (any non-null value is
|
||||
* considered true)
|
||||
* @param previous a flag indicating whether or not all previous versions
|
||||
* were affected (any non-null value is considered true)
|
||||
*/
|
||||
public void setMatchedCPE(String cpeId, String previous) {
|
||||
matchedCPE = cpeId;
|
||||
|
||||
@@ -90,7 +90,8 @@ public class ExceptionCollection extends Exception {
|
||||
this.exceptions.add(exceptions);
|
||||
this.fatal = fatal;
|
||||
}
|
||||
/**
|
||||
|
||||
/**
|
||||
* Instantiates a new exception collection.
|
||||
*
|
||||
* @param msg the exception message
|
||||
@@ -195,7 +196,7 @@ public class ExceptionCollection extends Exception {
|
||||
*/
|
||||
@Override
|
||||
public void printStackTrace(PrintStream s) {
|
||||
s.println("Multiple Exceptions Occured");
|
||||
s.println("Multiple Exceptions Occurred");
|
||||
super.printStackTrace(s);
|
||||
for (Throwable t : this.exceptions) {
|
||||
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
|
||||
public void printStackTrace() {
|
||||
this.printStackTrace(System.err);
|
||||
public String getMessage() {
|
||||
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>
|
||||
* 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
|
||||
*/
|
||||
@@ -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}))?");
|
||||
/**
|
||||
* Regular expression to extract a single version number without periods. This is a last ditch effort just to check in case we
|
||||
* are missing a version number using the previous regex.
|
||||
* Regular expression to extract a single version number without periods.
|
||||
* 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}))?");
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@@ -48,7 +57,8 @@ public final class DependencyVersionUtil {
|
||||
|
||||
/**
|
||||
* <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>
|
||||
* Example:
|
||||
* Give the file name: library-name-1.4.1r2-release.jar
|
||||
@@ -95,4 +105,30 @@ public final class DependencyVersionUtil {
|
||||
}
|
||||
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";
|
||||
/**
|
||||
* Attribute name.
|
||||
* Attribute value.
|
||||
*/
|
||||
private static final String VENDOR = "vendor";
|
||||
/**
|
||||
* Attribute value.
|
||||
*/
|
||||
private static final String PRODUCT = "product";
|
||||
/**
|
||||
* Attribute value.
|
||||
*/
|
||||
private static final String VERSION = "version";
|
||||
/**
|
||||
* Attribute name.
|
||||
*/
|
||||
@@ -168,16 +176,25 @@ public class HintHandler extends DefaultHandler {
|
||||
attr.getValue(VALUE),
|
||||
Confidence.valueOf(attr.getValue(CONFIDENCE)));
|
||||
}
|
||||
} else if (inAddNode) {
|
||||
rule.addAddProduct(attr.getValue(SOURCE),
|
||||
attr.getValue(NAME),
|
||||
attr.getValue(VALUE),
|
||||
Confidence.valueOf(attr.getValue(CONFIDENCE)));
|
||||
} else {
|
||||
rule.addGivenProduct(attr.getValue(SOURCE),
|
||||
attr.getValue(NAME),
|
||||
attr.getValue(VALUE),
|
||||
Confidence.valueOf(attr.getValue(CONFIDENCE)));
|
||||
} else if (PRODUCT.equals(hintType)) {
|
||||
if (inAddNode) {
|
||||
rule.addAddProduct(attr.getValue(SOURCE),
|
||||
attr.getValue(NAME),
|
||||
attr.getValue(VALUE),
|
||||
Confidence.valueOf(attr.getValue(CONFIDENCE)));
|
||||
} else {
|
||||
rule.addGivenProduct(attr.getValue(SOURCE),
|
||||
attr.getValue(NAME),
|
||||
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)) {
|
||||
final PropertyType pt = new PropertyType();
|
||||
|
||||
@@ -64,7 +64,7 @@ public class HintParser {
|
||||
/**
|
||||
* 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.
|
||||
@@ -104,8 +104,9 @@ public class HintParser {
|
||||
* @throws SAXException thrown if the XML cannot be parsed
|
||||
*/
|
||||
public Hints parseHints(InputStream inputStream) throws HintParseException, SAXException {
|
||||
InputStream schemaStream = null;
|
||||
try {
|
||||
final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(HINT_SCHEMA);
|
||||
schemaStream = this.getClass().getClassLoader().getResourceAsStream(HINT_SCHEMA);
|
||||
final HintHandler handler = new HintHandler();
|
||||
final SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
@@ -141,6 +142,14 @@ public class HintParser {
|
||||
} catch (IOException ex) {
|
||||
LOGGER.debug("", 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>();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@@ -106,11 +115,6 @@ public class HintRule {
|
||||
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.
|
||||
*
|
||||
@@ -132,6 +136,27 @@ public class HintRule {
|
||||
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.
|
||||
*/
|
||||
|
||||
@@ -48,13 +48,17 @@ public final class PomUtils {
|
||||
*
|
||||
* @param file the pom.xml file
|
||||
* @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 {
|
||||
Model model = null;
|
||||
try {
|
||||
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) {
|
||||
LOGGER.warn("Unable to parse pom '{}'", file.getPath());
|
||||
LOGGER.debug("", ex);
|
||||
@@ -68,7 +72,6 @@ public final class PomUtils {
|
||||
LOGGER.debug("", 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 jar the jar file to extract the pom from
|
||||
* @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 {
|
||||
final ZipEntry entry = jar.getEntry(path);
|
||||
@@ -86,7 +90,9 @@ public final class PomUtils {
|
||||
try {
|
||||
final PomParser parser = new PomParser();
|
||||
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) {
|
||||
LOGGER.warn("Unable to parse pom '{}' in jar '{}'; invalid signature", path, jar.getName());
|
||||
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 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 {
|
||||
final Model pom = PomUtils.readPom(pomFile);
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.xml.suppression;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
@@ -33,7 +31,7 @@ public class SuppressionErrorHandler implements ErrorHandler {
|
||||
/**
|
||||
* 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.
|
||||
@@ -70,7 +68,7 @@ public class SuppressionErrorHandler implements ErrorHandler {
|
||||
*/
|
||||
@Override
|
||||
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
|
||||
*/
|
||||
public List<SuppressionRule> parseSuppressionRules(InputStream inputStream) throws SuppressionParseException, SAXException {
|
||||
InputStream schemaStream = null;
|
||||
try {
|
||||
final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(SUPPRESSION_SCHEMA);
|
||||
schemaStream = this.getClass().getClassLoader().getResourceAsStream(SUPPRESSION_SCHEMA);
|
||||
final SuppressionHandler handler = new SuppressionHandler();
|
||||
final SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
@@ -157,6 +158,14 @@ public class SuppressionParser {
|
||||
} catch (IOException ex) {
|
||||
LOGGER.debug("", 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
|
||||
*/
|
||||
private List<SuppressionRule> parseOldSuppressionRules(InputStream inputStream) throws SuppressionParseException {
|
||||
InputStream schemaStream = null;
|
||||
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 SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
@@ -200,6 +210,14 @@ public class SuppressionParser {
|
||||
} catch (IOException ex) {
|
||||
LOGGER.debug("", 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.RubyBundleAuditAnalyzer
|
||||
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"?>
|
||||
<hints xmlns="https://jeremylong.github.io/DependencyCheck/dependency-hint.1.0.xsd">
|
||||
<hint>
|
||||
<given>
|
||||
<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="spring-core" confidence="HIGH"/>
|
||||
</given>
|
||||
<add>
|
||||
<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="vmware" confidence="HIGH"/>
|
||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="pivotal" confidence="HIGH"/>
|
||||
</add>
|
||||
</hint>
|
||||
<hint>
|
||||
<given>
|
||||
<evidence type="product" source="jar" name="package name" value="springframework" confidence="LOW"/>
|
||||
<fileName contains="spring"/>
|
||||
</given>
|
||||
<add>
|
||||
<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="vmware" confidence="HIGH"/>
|
||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="pivotal" confidence="HIGH"/>
|
||||
</add>
|
||||
</hint>
|
||||
<hint>
|
||||
<given>
|
||||
<evidence type="product" source="jar" name="package name" value="springframework" confidence="LOW"/>
|
||||
</given>
|
||||
<add>
|
||||
<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="pivotal" confidence="HIGH"/>
|
||||
</add>
|
||||
</hint>
|
||||
<hint>
|
||||
<given>
|
||||
<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"/>
|
||||
</given>
|
||||
<add>
|
||||
<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="vmware" confidence="HIGH"/>
|
||||
</add>
|
||||
</hint>
|
||||
<hint>
|
||||
<given>
|
||||
<evidence type="vendor" source="composer.lock" name="vendor" value="symfony" confidence="HIGHEST"/>
|
||||
</given>
|
||||
<add>
|
||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="sensiolabs" confidence="HIGHEST"/>
|
||||
</add>
|
||||
</hint>
|
||||
<hint>
|
||||
<given>
|
||||
<evidence type="vendor" source="composer.lock" name="vendor" value="zendframework" confidence="HIGHEST"/>
|
||||
</given>
|
||||
<add>
|
||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="zend" confidence="HIGHEST"/>
|
||||
</add>
|
||||
</hint>
|
||||
<hint>
|
||||
<given>
|
||||
<evidence type="product" source="composer.lock" name="product" value="zendframework" confidence="HIGHEST"/>
|
||||
</given>
|
||||
<add>
|
||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="zend_framework" confidence="HIGHEST"/>
|
||||
</add>
|
||||
</hint>
|
||||
<vendorDuplicatingHint value="sun" duplicate="oracle"/>
|
||||
<vendorDuplicatingHint value="oracle" duplicate="sun"/>
|
||||
<hints xmlns="https://jeremylong.github.io/DependencyCheck/dependency-hint.1.1.xsd">
|
||||
<hint>
|
||||
<given>
|
||||
<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="spring-core" confidence="HIGH"/>
|
||||
</given>
|
||||
<add>
|
||||
<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="vmware" confidence="HIGH"/>
|
||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="pivotal" confidence="HIGH"/>
|
||||
</add>
|
||||
</hint>
|
||||
<hint>
|
||||
<given>
|
||||
<evidence type="product" source="jar" name="package name" value="springframework" confidence="LOW"/>
|
||||
<fileName contains="spring"/>
|
||||
</given>
|
||||
<add>
|
||||
<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="vmware" confidence="HIGH"/>
|
||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="pivotal" confidence="HIGH"/>
|
||||
</add>
|
||||
</hint>
|
||||
<hint>
|
||||
<given>
|
||||
<evidence type="product" source="jar" name="package name" value="springframework" confidence="LOW"/>
|
||||
</given>
|
||||
<add>
|
||||
<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="pivotal" confidence="HIGH"/>
|
||||
</add>
|
||||
</hint>
|
||||
<hint>
|
||||
<given>
|
||||
<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"/>
|
||||
</given>
|
||||
<add>
|
||||
<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="vmware" confidence="HIGH"/>
|
||||
</add>
|
||||
</hint>
|
||||
<hint>
|
||||
<given>
|
||||
<evidence type="vendor" source="composer.lock" name="vendor" value="symfony" confidence="HIGHEST"/>
|
||||
</given>
|
||||
<add>
|
||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="sensiolabs" confidence="HIGHEST"/>
|
||||
</add>
|
||||
</hint>
|
||||
<hint>
|
||||
<given>
|
||||
<evidence type="vendor" source="composer.lock" name="vendor" value="zendframework" confidence="HIGHEST"/>
|
||||
</given>
|
||||
<add>
|
||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="zend" confidence="HIGHEST"/>
|
||||
</add>
|
||||
</hint>
|
||||
<hint>
|
||||
<given>
|
||||
<evidence type="product" source="composer.lock" name="product" value="zendframework" confidence="HIGHEST"/>
|
||||
</given>
|
||||
<add>
|
||||
<evidence type="vendor" source="hint analyzer" name="vendor" value="zend_framework" confidence="HIGHEST"/>
|
||||
</add>
|
||||
</hint>
|
||||
|
||||
<!-- 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>
|
||||
@@ -410,7 +410,7 @@
|
||||
<notes><![CDATA[
|
||||
Aether false positive.
|
||||
]]></notes>
|
||||
<gav regex="true">org.eclipse.aether:aether.*</gav>
|
||||
<gav regex="true">org\.eclipse\.aether:aether.*</gav>
|
||||
<cpe>cpe:/a:eclipse:eclipse_ide</cpe>
|
||||
</suppress>
|
||||
<suppress base="true">
|
||||
@@ -420,4 +420,11 @@
|
||||
<filePath regex="true">.*\.(jar|ear|war|pom)</filePath>
|
||||
<cpe>cpe:/a:services_project:services</cpe>
|
||||
</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>
|
||||
|
||||
@@ -96,6 +96,8 @@ analyzer.nuspec.enabled=true
|
||||
analyzer.openssl.enabled=true
|
||||
analyzer.central.enabled=true
|
||||
analyzer.nexus.enabled=false
|
||||
analyzer.cocoapods.enabled=true
|
||||
analyzer.swift.package.manager.enabled=true
|
||||
#whether the nexus analyzer uses the proxy
|
||||
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 org.junit.Assume;
|
||||
import static org.junit.Assume.assumeFalse;
|
||||
import static org.junit.Assume.assumeNotNull;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.owasp.dependencycheck.BaseTest;
|
||||
@@ -61,6 +62,7 @@ public class AssemblyAnalyzerTest extends BaseTest {
|
||||
analyzer = new AssemblyAnalyzer();
|
||||
analyzer.accept(new File("test.dll")); // trick into "thinking it is active"
|
||||
analyzer.initialize();
|
||||
Assume.assumeTrue("Mono is not installed, skipping tests.", analyzer.buildArgumentList() == null);
|
||||
} catch (Exception e) {
|
||||
if (e.getMessage().contains("Could not execute .NET AssemblyAnalyzer")) {
|
||||
LOGGER.warn("Exception setting up AssemblyAnalyzer. Tests will be incomplete");
|
||||
@@ -81,7 +83,7 @@ public class AssemblyAnalyzerTest extends BaseTest {
|
||||
|
||||
@Test
|
||||
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");
|
||||
Dependency d = new Dependency(f);
|
||||
analyzer.analyze(d, null);
|
||||
@@ -104,7 +106,7 @@ public class AssemblyAnalyzerTest extends BaseTest {
|
||||
|
||||
@Test
|
||||
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");
|
||||
|
||||
Dependency d = new Dependency(f);
|
||||
@@ -116,9 +118,10 @@ public class AssemblyAnalyzerTest extends BaseTest {
|
||||
|
||||
@Test
|
||||
public void testNonexistent() {
|
||||
assumeNotNull(analyzer.buildArgumentList());
|
||||
|
||||
// Tweak the log level so the warning doesn't show in the console
|
||||
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 test = new File(f.getParent(), "nonexistent.dll");
|
||||
Dependency d = new Dependency(test);
|
||||
|
||||
@@ -189,6 +189,7 @@ public class CPEAnalyzerIntegrationTest extends BaseDBTestCase {
|
||||
instance.determineCPE(spring);
|
||||
instance.determineCPE(spring3);
|
||||
instance.close();
|
||||
|
||||
|
||||
String expResult = "cpe:/a:apache:struts:2.1.2";
|
||||
Identifier expIdentifier = new Identifier("cpe", expResult, expResult);
|
||||
|
||||
@@ -117,7 +117,6 @@ public class RubyBundleAuditAnalyzerTest extends BaseDBTestCase {
|
||||
final Engine engine = new Engine();
|
||||
analyzer.analyze(result, engine);
|
||||
int size = engine.getDependencies().size();
|
||||
|
||||
assertTrue(size >= 1);
|
||||
|
||||
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
|
||||
// public void testUpdate() throws Exception {
|
||||
// StandardUpdate instance = getStandardUpdateTask();
|
||||
// instance.update();
|
||||
// //TODO make this an actual test
|
||||
// }
|
||||
@Test
|
||||
public void testUpdate() throws Exception {
|
||||
NvdCveUpdater instance = getUpdater();
|
||||
instance.update();
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
public void testHandler() throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException, SAXException, FileNotFoundException, UnsupportedEncodingException, IOException {
|
||||
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();
|
||||
|
||||
SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?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>
|
||||
<given>
|
||||
<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>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.4.1</version>
|
||||
<version>1.4.3</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
@@ -208,6 +208,10 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
||||
<groupId>org.sonatype.plexus</groupId>
|
||||
<artifactId>plexus-sec-dispatcher</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.shared</groupId>
|
||||
<artifactId>maven-dependency-tree</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jmockit</groupId>
|
||||
<artifactId>jmockit</artifactId>
|
||||
|
||||
@@ -19,10 +19,8 @@ package org.owasp.dependencycheck.maven;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
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.ResolutionScope;
|
||||
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.dependency.Dependency;
|
||||
import org.owasp.dependencycheck.exception.ExceptionCollection;
|
||||
import org.owasp.dependencycheck.exception.ReportException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
@@ -49,18 +44,13 @@ import org.owasp.dependencycheck.utils.Settings;
|
||||
@Mojo(
|
||||
name = "aggregate",
|
||||
defaultPhase = LifecyclePhase.VERIFY,
|
||||
/*aggregator = true,*/
|
||||
aggregator = true,
|
||||
threadSafe = false,
|
||||
requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,
|
||||
requiresOnline = true
|
||||
)
|
||||
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
|
||||
* and generates the subsequent reports.
|
||||
@@ -72,108 +62,78 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
|
||||
*/
|
||||
@Override
|
||||
public void runCheck() throws MojoExecutionException, MojoFailureException {
|
||||
final MavenEngine engine = generateDataFile();
|
||||
final MavenEngine engine = loadEngine();
|
||||
if (engine == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (getProject() == getLastProject()) {
|
||||
//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);
|
||||
}
|
||||
ExceptionCollection exCol = scanArtifacts(getProject(), engine);
|
||||
|
||||
File outputDir = getCorrectOutputDirectory(current);
|
||||
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(current.getBuild().getDirectory());
|
||||
for (MavenProject childProject : getDescendants(this.getProject())) {
|
||||
final ExceptionCollection ex = scanArtifacts(childProject, engine);
|
||||
if (ex != null) {
|
||||
if (exCol == null) {
|
||||
exCol = ex;
|
||||
}
|
||||
try {
|
||||
writeReports(engine, current, outputDir);
|
||||
} catch (ReportException ex) {
|
||||
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);
|
||||
}
|
||||
exCol.getExceptions().addAll(ex.getExceptions());
|
||||
if (ex.isFatal()) {
|
||||
exCol.setFatal(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
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
|
||||
* project.
|
||||
@@ -264,16 +224,15 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the engine, runs a scan, and writes the serialized
|
||||
* dependencies to disk.
|
||||
* Initializes the engine.
|
||||
*
|
||||
* @return the MavenEngine used to execute dependency-check
|
||||
* @throws MojoExecutionException thrown if there is an exception running
|
||||
* the mojo
|
||||
* the Mojo
|
||||
* @throws MojoFailureException thrown if dependency-check is configured to
|
||||
* fail the build if severe CVEs are identified.
|
||||
*/
|
||||
protected MavenEngine generateDataFile() throws MojoExecutionException, MojoFailureException {
|
||||
protected MavenEngine loadEngine() throws MojoExecutionException, MojoFailureException {
|
||||
MavenEngine engine = null;
|
||||
try {
|
||||
engine = initializeEngine();
|
||||
@@ -286,59 +245,7 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
|
||||
throw new MojoExecutionException(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;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import java.io.InputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.List;
|
||||
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.plugin.AbstractMojo;
|
||||
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.settings.Proxy;
|
||||
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.nvdcve.CveDB;
|
||||
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.Identifier;
|
||||
import org.owasp.dependencycheck.dependency.Vulnerability;
|
||||
import org.owasp.dependencycheck.exception.ExceptionCollection;
|
||||
import org.owasp.dependencycheck.exception.ReportException;
|
||||
import org.owasp.dependencycheck.reporting.ReportGenerator;
|
||||
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")
|
||||
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".
|
||||
@@ -553,32 +588,121 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
|
||||
*
|
||||
* @param project the project to scan the dependencies of
|
||||
* @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) {
|
||||
for (Artifact a : project.getArtifacts()) {
|
||||
protected ExceptionCollection scanArtifacts(MavenProject project, MavenEngine engine) {
|
||||
// <editor-fold defaultstate="collapsed" desc="old implementation">
|
||||
/*
|
||||
for (Artifact a : project.getArtifacts()) {
|
||||
if (excludeFromScan(a)) {
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
final List<Dependency> deps = engine.scan(a.getFile().getAbsoluteFile());
|
||||
if (deps != null) {
|
||||
if (deps.size() == 1) {
|
||||
final Dependency d = deps.get(0);
|
||||
if (d != null) {
|
||||
final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion());
|
||||
d.addAsEvidence("pom", ma, Confidence.HIGHEST);
|
||||
d.addProjectReference(project.getName());
|
||||
if (getLog().isDebugEnabled()) {
|
||||
getLog().debug(String.format("Adding project reference %s on dependency %s", project.getName(),
|
||||
d.getDisplayFileName()));
|
||||
if (deps.size() == 1) {
|
||||
final Dependency d = deps.get(0);
|
||||
if (d != null) {
|
||||
final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion());
|
||||
d.addAsEvidence("pom", ma, Confidence.HIGHEST);
|
||||
d.addProjectReference(project.getName());
|
||||
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:%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()) {
|
||||
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());
|
||||
} else {
|
||||
final String msg = String.format("Unable to resolve '%s' in project %s",
|
||||
dependencyNode.getArtifact().getId(), project.getName());
|
||||
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 {
|
||||
populateSettings();
|
||||
return new MavenEngine(this.project,
|
||||
this.reactorProjects);
|
||||
return new MavenEngine(this.project, 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
|
||||
* 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;
|
||||
* otherwise <code>false</code>
|
||||
*/
|
||||
protected boolean excludeFromScan(Artifact a) {
|
||||
if (skipTestScope && Artifact.SCOPE_TEST.equals(a.getScope())) {
|
||||
protected boolean excludeFromScan(String scope) {
|
||||
if (skipTestScope && org.apache.maven.artifact.Artifact.SCOPE_TEST.equals(scope)) {
|
||||
return true;
|
||||
}
|
||||
if (skipProvidedScope && Artifact.SCOPE_PROVIDED.equals(a.getScope())) {
|
||||
if (skipProvidedScope && org.apache.maven.artifact.Artifact.SCOPE_PROVIDED.equals(scope)) {
|
||||
return true;
|
||||
}
|
||||
if (skipRuntimeScope && !Artifact.SCOPE_RUNTIME.equals(a.getScope())) {
|
||||
if (skipRuntimeScope && !org.apache.maven.artifact.Artifact.SCOPE_RUNTIME.equals(scope)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -1133,4 +1256,5 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
|
||||
return ret;
|
||||
}
|
||||
//</editor-fold>
|
||||
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public class CheckMojo extends BaseDependencyCheckMojo {
|
||||
public boolean canGenerateReport() {
|
||||
boolean isCapable = false;
|
||||
for (Artifact a : getProject().getArtifacts()) {
|
||||
if (!excludeFromScan(a)) {
|
||||
if (!excludeFromScan(a.getScope())) {
|
||||
isCapable = true;
|
||||
break;
|
||||
}
|
||||
@@ -88,11 +88,10 @@ public class CheckMojo extends BaseDependencyCheckMojo {
|
||||
getLog().error(msg);
|
||||
}
|
||||
if (engine != null) {
|
||||
scanArtifacts(getProject(), engine);
|
||||
ExceptionCollection exCol = scanArtifacts(getProject(), engine);
|
||||
if (engine.getDependencies().isEmpty()) {
|
||||
getLog().info("No dependencies were identified that could be analyzed by dependency-check");
|
||||
} else {
|
||||
ExceptionCollection exCol = null;
|
||||
try {
|
||||
engine.analyzeDependencies();
|
||||
} catch (ExceptionCollection ex) {
|
||||
|
||||
@@ -53,18 +53,16 @@ Create an aggregated dependency-check report within the site.
|
||||
<plugins>
|
||||
...
|
||||
<plugin>
|
||||
<plugin>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<reportSets>
|
||||
<reportSet>
|
||||
<reports>
|
||||
<report>aggregate</report>
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
</plugin>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<reportSets>
|
||||
<reportSet>
|
||||
<reports>
|
||||
<report>aggregate</report>
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
</plugin>
|
||||
...
|
||||
</plugins>
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.apache.maven.plugin.testing.stubs.ArtifactStub;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Assume;
|
||||
import org.junit.Test;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||
import org.owasp.dependencycheck.utils.InvalidSettingException;
|
||||
@@ -45,7 +46,8 @@ import org.owasp.dependencycheck.utils.Settings;
|
||||
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.
|
||||
*/
|
||||
@@ -63,7 +65,6 @@ public class BaseDependencyCheckMojoTest extends BaseTest {
|
||||
*/
|
||||
@Test
|
||||
public void testScanArtifacts() throws DatabaseException, InvalidSettingException {
|
||||
//TODO get this to work under JDK 1.8
|
||||
if (canRun()) {
|
||||
MavenProject project = new MockUp<MavenProject>() {
|
||||
@Mock
|
||||
@@ -95,7 +96,11 @@ public class BaseDependencyCheckMojoTest extends BaseTest {
|
||||
|
||||
assertTrue(engine.getDependencies().isEmpty());
|
||||
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());
|
||||
engine.cleanup();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.maven;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
@@ -36,8 +39,20 @@ public class BaseTest {
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
Settings.initialize();
|
||||
InputStream mojoProperties = BaseTest.class.getClassLoader().getResourceAsStream(BaseTest.PROPERTIES_FILE);
|
||||
Settings.mergeProperties(mojoProperties);
|
||||
InputStream mojoProperties = null;
|
||||
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
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved.
|
||||
<parent>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.4.1</version>
|
||||
<version>1.4.3</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dependency-check-utils</artifactId>
|
||||
|
||||
@@ -58,11 +58,11 @@ public final class Checksum {
|
||||
* @throws NoSuchAlgorithmException when an algorithm is specified that does not exist
|
||||
*/
|
||||
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;
|
||||
try {
|
||||
fis = new FileInputStream(file);
|
||||
FileChannel ch = fis.getChannel();
|
||||
final FileChannel ch = fis.getChannel();
|
||||
long remainingToRead = file.length();
|
||||
long start = 0;
|
||||
while (remainingToRead > 0) {
|
||||
@@ -74,7 +74,7 @@ public final class Checksum {
|
||||
amountToRead = remainingToRead;
|
||||
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);
|
||||
start += amountToRead;
|
||||
}
|
||||
@@ -99,7 +99,7 @@ public final class Checksum {
|
||||
* @throws NoSuchAlgorithmException when the MD5 algorithm is not available
|
||||
*/
|
||||
public static String getMD5Checksum(File file) throws IOException, NoSuchAlgorithmException {
|
||||
byte[] b = getChecksum("MD5", file);
|
||||
final byte[] b = getChecksum("MD5", file);
|
||||
return getHex(b);
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ public final class Checksum {
|
||||
* @throws NoSuchAlgorithmException when the SHA1 algorithm is not available
|
||||
*/
|
||||
public static String getSHA1Checksum(File file) throws IOException, NoSuchAlgorithmException {
|
||||
byte[] b = getChecksum("SHA1", file);
|
||||
final byte[] b = getChecksum("SHA1", file);
|
||||
return getHex(b);
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -300,11 +300,11 @@ public final class Downloader {
|
||||
* @throws DownloadFailedException a wrapper exception that contains the
|
||||
* 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;
|
||||
while (cause != null) {
|
||||
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);
|
||||
throw new DownloadFailedException(msg);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.slf4j.LoggerFactory;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
|
||||
/**
|
||||
* A collection of utilities for processing information about files.
|
||||
@@ -102,7 +103,7 @@ public final class FileUtils {
|
||||
* @return a String containing the bit bucket
|
||||
*/
|
||||
public static String getBitBucket() {
|
||||
if (System.getProperty("os.name").startsWith("Windows")) {
|
||||
if (SystemUtils.IS_OS_WINDOWS) {
|
||||
return BIT_BUCKET_WIN;
|
||||
} else {
|
||||
return BIT_BUCKET_UNIX;
|
||||
|
||||
@@ -78,7 +78,7 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
||||
*/
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites() {
|
||||
return Arrays.copyOf(ciphers, ciphers.length);
|
||||
return sslCtxt.getSocketFactory().getDefaultCipherSuites();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,7 +88,7 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
||||
*/
|
||||
@Override
|
||||
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);
|
||||
|
||||
ss.setEnabledProtocols(protocols);
|
||||
ss.setEnabledCipherSuites(ciphers);
|
||||
|
||||
return ss;
|
||||
}
|
||||
@@ -146,7 +145,6 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
||||
final SSLSocket ss = (SSLSocket) factory.createSocket(address, port, localAddress, localPort);
|
||||
|
||||
ss.setEnabledProtocols(protocols);
|
||||
ss.setEnabledCipherSuites(ciphers);
|
||||
|
||||
return ss;
|
||||
}
|
||||
@@ -167,7 +165,6 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
||||
final SSLSocket ss = (SSLSocket) factory.createSocket(host, port, localHost, localPort);
|
||||
|
||||
ss.setEnabledProtocols(protocols);
|
||||
ss.setEnabledCipherSuites(ciphers);
|
||||
|
||||
return ss;
|
||||
}
|
||||
@@ -186,7 +183,6 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
||||
final SSLSocket ss = (SSLSocket) factory.createSocket(host, port);
|
||||
|
||||
ss.setEnabledProtocols(protocols);
|
||||
ss.setEnabledCipherSuites(ciphers);
|
||||
|
||||
return ss;
|
||||
}
|
||||
@@ -205,7 +201,6 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
||||
final SSLSocket ss = (SSLSocket) factory.createSocket(host, port);
|
||||
|
||||
ss.setEnabledProtocols(protocols);
|
||||
ss.setEnabledCipherSuites(ciphers);
|
||||
|
||||
return ss;
|
||||
}
|
||||
@@ -226,7 +221,6 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
||||
sslCtxt.init(km, tm, random);
|
||||
|
||||
protocols = getProtocolList();
|
||||
ciphers = getCipherList();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -240,9 +234,7 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
||||
private void initSSLSocketFactoryEx(SSLContext ctx)
|
||||
throws NoSuchAlgorithmException, KeyManagementException {
|
||||
sslCtxt = ctx;
|
||||
|
||||
protocols = getProtocolList();
|
||||
ciphers = getCipherList();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -286,98 +278,10 @@ public class SSLSocketFactoryEx extends SSLSocketFactory {
|
||||
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.
|
||||
*/
|
||||
private SSLContext sslCtxt;
|
||||
/**
|
||||
* The cipher suites.
|
||||
*/
|
||||
private String[] ciphers;
|
||||
/**
|
||||
* The protocols.
|
||||
*/
|
||||
|
||||
@@ -55,7 +55,7 @@ public final class Settings {
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@@ -288,6 +288,14 @@ public final class Settings {
|
||||
* The properties key for whether the OpenSSL analyzer is 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.
|
||||
*/
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.net.PasswordAuthentication;
|
||||
import java.net.Proxy;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
@@ -188,7 +189,7 @@ public final class URLConnectionFactory {
|
||||
* @param url the URL
|
||||
* @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())) {
|
||||
try {
|
||||
final HttpsURLConnection secCon = (HttpsURLConnection) conn;
|
||||
|
||||
9
pom.xml
9
pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long
|
||||
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.4.1</version>
|
||||
<version>1.4.3</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
@@ -360,7 +360,7 @@ Copyright (c) 2012 - Jeremy Long
|
||||
<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-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>
|
||||
</configuration>
|
||||
</execution>
|
||||
@@ -671,6 +671,11 @@ Copyright (c) 2012 - Jeremy Long
|
||||
<artifactId>plexus-sec-dispatcher</artifactId>
|
||||
<version>1.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.shared</groupId>
|
||||
<artifactId>maven-dependency-tree</artifactId>
|
||||
<version>2.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish</groupId>
|
||||
<artifactId>javax.json</artifactId>
|
||||
|
||||
@@ -13,6 +13,6 @@
|
||||
^ \* See the License for the specific language governing permissions and\s*$
|
||||
^ \* limitations under the License\.\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*$
|
||||
^package
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
<suppressions>
|
||||
<suppress checks=".*" files=".*[\\/]package-info\.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=".*[\\/]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>
|
||||
@@ -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
|
||||
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) |
|
||||
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
|
||||
```groovy
|
||||
|
||||
Reference in New Issue
Block a user