diff --git a/.gitignore b/.gitignore
index 1c55ffdfe..09bf20505 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
*/target/**
+# IntelliJ test run side-effects
+dependency-check-core/data/
# Intellij project files
*.iml
*.ipr
diff --git a/dependency-check-cli/pom.xml b/dependency-check-cli/pom.xml
index 2fa1b66c9..820458255 100644
--- a/dependency-check-cli/pom.xml
+++ b/dependency-check-cli/pom.xml
@@ -198,7 +198,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
${reporting.javadoc-plugin.version}
false
- Copyright© 2012-15 Jeremy Long. All Rights Reserved.
+ Copyright� 2012-15 Jeremy Long. All Rights Reserved.
@@ -333,7 +333,6 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
ch.qos.logback
logback-classic
- ${logback.version}
diff --git a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java
index 81e0008e7..d068d435b 100644
--- a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java
+++ b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java
@@ -351,22 +351,27 @@ public class App {
}
}
+ /**
+ * Creates a file appender and adds it to logback.
+ *
+ * @param verboseLog the path to the verbose log file
+ */
private void prepareLogger(String verboseLog) {
- StaticLoggerBinder loggerBinder = StaticLoggerBinder.getSingleton();
- LoggerContext context = (LoggerContext) loggerBinder.getLoggerFactory();
+ final StaticLoggerBinder loggerBinder = StaticLoggerBinder.getSingleton();
+ final LoggerContext context = (LoggerContext) loggerBinder.getLoggerFactory();
final PatternLayoutEncoder encoder = new PatternLayoutEncoder();
encoder.setPattern("%d %C:%L%n%-5level - %msg%n");
encoder.setContext(context);
encoder.start();
- FileAppender fa = new FileAppender();
+ final FileAppender fa = new FileAppender();
fa.setAppend(true);
fa.setEncoder(encoder);
fa.setContext(context);
fa.setFile(verboseLog);
final File f = new File(verboseLog);
String name = f.getName();
- int i = name.lastIndexOf('.');
+ final int i = name.lastIndexOf('.');
if (i > 1) {
name = name.substring(0, i);
}
diff --git a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/CliParser.java b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/CliParser.java
index e0eeb24ad..313537ab3 100644
--- a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/CliParser.java
+++ b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/CliParser.java
@@ -497,9 +497,9 @@ public final class CliParser {
*
* @return true if the disableAutoconf command line argument was specified; otherwise false
*/
- public boolean isAutoconfDisabled() {
+ public boolean isAutoconfDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_AUTOCONF);
- }
+ }
/**
* Returns true if the disableNexus command line argument was specified.
diff --git a/dependency-check-core/pom.xml b/dependency-check-core/pom.xml
index c38321a85..0af57a434 100644
--- a/dependency-check-core/pom.xml
+++ b/dependency-check-core/pom.xml
@@ -372,8 +372,13 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
- org.slf4j
- slf4j-simple
+ ch.qos.logback
+ logback-core
+ test
+
+
+ ch.qos.logback
+ logback-classic
test
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java
index 949c4ce47..69036b9a9 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java
@@ -17,13 +17,6 @@
*/
package org.owasp.dependencycheck;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.EnumMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
import org.owasp.dependencycheck.analyzer.AnalysisPhase;
import org.owasp.dependencycheck.analyzer.Analyzer;
import org.owasp.dependencycheck.analyzer.AnalyzerService;
@@ -43,6 +36,14 @@ import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
/**
* Scans files, directories, etc. for Dependencies. Analyzers are loaded and used to process the files found by the scan, if a
* file is encountered and an Analyzer is associated with the file type then the file is turned into a dependency.
@@ -167,7 +168,6 @@ public class Engine {
*
* @param paths an array of paths to files or directories to be analyzed
* @return the list of dependencies scanned
- *
* @since v0.3.2.5
*/
public List scan(String[] paths) {
@@ -200,7 +200,6 @@ public class Engine {
*
* @param files an array of paths to files or directories to be analyzed.
* @return the list of dependencies
- *
* @since v0.3.2.5
*/
public List scan(File[] files) {
@@ -220,7 +219,6 @@ public class Engine {
*
* @param files a set of paths to files or directories to be analyzed
* @return the list of dependencies scanned
- *
* @since v0.3.2.5
*/
public List scan(Set files) {
@@ -240,7 +238,6 @@ public class Engine {
*
* @param files a set of paths to files or directories to be analyzed
* @return the list of dependencies scanned
- *
* @since v0.3.2.5
*/
public List scan(List files) {
@@ -260,9 +257,7 @@ public class Engine {
*
* @param file the path to a file or directory to be analyzed
* @return the list of dependencies scanned
- *
* @since v0.3.2.4
- *
*/
public List scan(File file) {
if (file.exists()) {
@@ -324,7 +319,7 @@ public class Engine {
Dependency dependency = null;
if (supportsExtension(extension)) {
dependency = new Dependency(file);
- if (extension == null ? fileName == null : extension.equals(fileName)) {
+ if (extension.equals(fileName)) {
dependency.setFileExtension(extension);
}
dependencies.add(dependency);
@@ -333,7 +328,10 @@ public class Engine {
}
/**
- * Runs the analyzers against all of the dependencies.
+ * Runs the analyzers against all of the dependencies. Since the mutable dependencies list is exposed via
+ * {@link #getDependencies()}, this method iterates over a copy of the dependencies list. Thus, the potential for
+ * {@link java.util.ConcurrentModificationException}s is avoided, and analyzers may safely add or remove entries
+ * from the dependencies list.
*/
public void analyzeDependencies() {
boolean autoUpdate = true;
@@ -512,7 +510,7 @@ public class Engine {
/**
* Checks the CPE Index to ensure documents exists. If none exist a NoDataException is thrown.
*
- * @throws NoDataException thrown if no data exists in the CPE Index
+ * @throws NoDataException thrown if no data exists in the CPE Index
* @throws DatabaseException thrown if there is an exception opening the database
*/
private void ensureDataExists() throws NoDataException, DatabaseException {
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java
index 054adde34..f8eade81e 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java
@@ -42,7 +42,6 @@ import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Evidence;
import org.owasp.dependencycheck.utils.DCResources;
import org.owasp.dependencycheck.utils.Settings;
-import org.slf4j.Logger;
import org.slf4j.cal10n.LocLogger;
import org.slf4j.cal10n.LocLoggerFactory;
import org.w3c.dom.Document;
@@ -79,15 +78,15 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Message Conveyer
*/
- private IMessageConveyor messageConveyer = new MessageConveyor(Locale.getDefault());
+ private final IMessageConveyor MESSAGE_CONVERYOR = new MessageConveyor(Locale.getDefault());
/**
* LocLoggerFactory for localized logger
*/
- private LocLoggerFactory llFactory = new LocLoggerFactory(messageConveyer);
+ private final LocLoggerFactory LLFACTORY = new LocLoggerFactory(MESSAGE_CONVERYOR);
/**
* Logger
*/
- private LocLogger LOGGER = llFactory.getLocLogger(AssemblyAnalyzer.class);
+ private final LocLogger LOGGER = LLFACTORY.getLocLogger(AssemblyAnalyzer.class);
/**
* Builds the beginnings of a List for ProcessBuilder
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.java
index 47d038d66..1e81a0df6 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.java
@@ -35,219 +35,238 @@ import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.utils.UrlStringUtils;
/**
- * Used to analyze Autoconf input files named configure.ac or configure.in.
- * Files simply named "configure" are also analyzed, assuming they are generated
- * by Autoconf, and contain certain special package descriptor variables.
+ * Used to analyze Autoconf input files named configure.ac or configure.in. Files simply named "configure" are also analyzed,
+ * assuming they are generated by Autoconf, and contain certain special package descriptor variables.
*
* @author Dale Visser
* @see Autoconf - GNU Project - Free Software Foundation (FSF)
*/
public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
- /**
- * Autoconf output filename.
- */
- private static final String CONFIGURE = "configure";
+ /**
+ * Autoconf output filename.
+ */
+ private static final String CONFIGURE = "configure";
- /**
- * Autoconf input filename.
- */
- private static final String CONFIGURE_IN = "configure.in";
+ /**
+ * Autoconf input filename.
+ */
+ private static final String CONFIGURE_IN = "configure.in";
- /**
- * Autoconf input filename.
- */
- private static final String CONFIGURE_AC = "configure.ac";
+ /**
+ * Autoconf input filename.
+ */
+ private static final String CONFIGURE_AC = "configure.ac";
- /**
- * The name of the analyzer.
- */
- private static final String ANALYZER_NAME = "Autoconf Analyzer";
+ /**
+ * The name of the analyzer.
+ */
+ private static final String ANALYZER_NAME = "Autoconf Analyzer";
- /**
- * The phase that this analyzer is intended to run in.
- */
- private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
+ /**
+ * The phase that this analyzer is intended to run in.
+ */
+ private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
- /**
- * The set of file extensions supported by this analyzer.
- */
- private static final Set EXTENSIONS = newHashSet("ac", "in",
- CONFIGURE);
+ /**
+ * The set of file extensions supported by this analyzer.
+ */
+ private static final Set EXTENSIONS = newHashSet("ac", "in",
+ CONFIGURE);
- /**
- * Matches AC_INIT variables in the output configure script.
- */
- private static final Pattern PACKAGE_VAR = Pattern.compile(
- "PACKAGE_(.+?)='(.*?)'", Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
+ /**
+ * Matches AC_INIT variables in the output configure script.
+ */
+ private static final Pattern PACKAGE_VAR = Pattern.compile(
+ "PACKAGE_(.+?)='(.*?)'", Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
- /**
- * Matches AC_INIT statement in configure.ac file.
- */
- private static final Pattern AC_INIT_PATTERN;
- static {
- // each instance of param or sep_param has a capture group
- final String param = "\\[{0,2}(.+?)\\]{0,2}";
- final String sep_param = "\\s*,\\s*" + param;
- // Group 1: Package
- // Group 2: Version
- // Group 3: optional
- // Group 4: Bug report address (if it exists)
- // Group 5: optional
- // Group 6: Tarname (if it exists)
- // Group 7: optional
- // Group 8: URL (if it exists)
- AC_INIT_PATTERN = Pattern.compile(String.format(
- "AC_INIT\\(%s%s(%s)?(%s)?(%s)?\\s*\\)", param, sep_param,
- sep_param, sep_param, sep_param), Pattern.DOTALL
- | Pattern.CASE_INSENSITIVE);
- }
+ /**
+ * Matches AC_INIT statement in configure.ac file.
+ */
+ private static final Pattern AC_INIT_PATTERN;
- /**
- * Returns a list of file EXTENSIONS supported by this analyzer.
- *
- * @return a list of file EXTENSIONS supported by this analyzer.
- */
- @Override
- public Set getSupportedExtensions() {
- return EXTENSIONS;
- }
+ static {
+ // each instance of param or sep_param has a capture group
+ final String param = "\\[{0,2}(.+?)\\]{0,2}";
+ final String sepParam = "\\s*,\\s*" + param;
+ // Group 1: Package
+ // Group 2: Version
+ // Group 3: optional
+ // Group 4: Bug report address (if it exists)
+ // Group 5: optional
+ // Group 6: Tarname (if it exists)
+ // Group 7: optional
+ // Group 8: URL (if it exists)
+ AC_INIT_PATTERN = Pattern.compile(String.format(
+ "AC_INIT\\(%s%s(%s)?(%s)?(%s)?\\s*\\)", param, sepParam,
+ sepParam, sepParam, sepParam), Pattern.DOTALL
+ | Pattern.CASE_INSENSITIVE);
+ }
- /**
- * Returns the name of the analyzer.
- *
- * @return the name of the analyzer.
- */
- @Override
- public String getName() {
- return ANALYZER_NAME;
- }
+ /**
+ * Returns a list of file EXTENSIONS supported by this analyzer.
+ *
+ * @return a list of file EXTENSIONS supported by this analyzer.
+ */
+ @Override
+ public Set getSupportedExtensions() {
+ return EXTENSIONS;
+ }
- /**
- * Returns the phase that the analyzer is intended to run in.
- *
- * @return the phase that the analyzer is intended to run in.
- */
- public AnalysisPhase getAnalysisPhase() {
- return ANALYSIS_PHASE;
- }
+ /**
+ * Returns the name of the analyzer.
+ *
+ * @return the name of the analyzer.
+ */
+ @Override
+ public String getName() {
+ return ANALYZER_NAME;
+ }
- /**
- * 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_PYTHON_DISTRIBUTION_ENABLED;
- }
+ /**
+ * Returns the phase that the analyzer is intended to run in.
+ *
+ * @return the phase that the analyzer is intended to run in.
+ */
+ public AnalysisPhase getAnalysisPhase() {
+ return ANALYSIS_PHASE;
+ }
- @Override
- protected void analyzeFileType(Dependency dependency, Engine engine)
- throws AnalysisException {
- final File actualFile = dependency.getActualFile();
- final String name = actualFile.getName();
- if (name.startsWith(CONFIGURE)) {
- final File parent = actualFile.getParentFile();
- final String parentName = parent.getName();
- dependency.setDisplayFileName(parentName + "/" + name);
- final boolean isOutputScript = CONFIGURE.equals(name);
- if (isOutputScript || CONFIGURE_AC.equals(name)
- || CONFIGURE_IN.equals(name)) {
- final String contents = getFileContents(actualFile);
- if (!contents.isEmpty()) {
- if (isOutputScript) {
- extractConfigureScriptEvidence(dependency, name,
- contents);
- } else {
- gatherEvidence(dependency, name, contents);
- }
- }
- }
- } else {
- // copy, alter and set in case some other thread is iterating over
- final List deps = new ArrayList(
- engine.getDependencies());
- deps.remove(dependency);
- engine.setDependencies(deps);
- }
- }
+ /**
+ * 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_PYTHON_DISTRIBUTION_ENABLED;
+ }
- private void extractConfigureScriptEvidence(Dependency dependency,
- final String name, final String contents) {
- final Matcher matcher = PACKAGE_VAR.matcher(contents);
- while (matcher.find()) {
- final String variable = matcher.group(1);
- final String value = matcher.group(2);
- if (!value.isEmpty()) {
- if (variable.endsWith("NAME")) {
- dependency.getProductEvidence().addEvidence(name, variable,
- value, Confidence.HIGHEST);
- } else if ("VERSION".equals(variable)) {
- dependency.getVersionEvidence().addEvidence(name, variable,
- value, Confidence.HIGHEST);
- } else if ("BUGREPORT".equals(variable)) {
- dependency.getVendorEvidence().addEvidence(name, variable,
- value, Confidence.HIGH);
- } else if ("URL".equals(variable)) {
- dependency.getVendorEvidence().addEvidence(name, variable,
- value, Confidence.HIGH);
- }
- }
- }
- }
+ @Override
+ protected void analyzeFileType(Dependency dependency, Engine engine)
+ throws AnalysisException {
+ final File actualFile = dependency.getActualFile();
+ final String name = actualFile.getName();
+ if (name.startsWith(CONFIGURE)) {
+ final File parent = actualFile.getParentFile();
+ final String parentName = parent.getName();
+ dependency.setDisplayFileName(parentName + "/" + name);
+ final boolean isOutputScript = CONFIGURE.equals(name);
+ if (isOutputScript || CONFIGURE_AC.equals(name)
+ || CONFIGURE_IN.equals(name)) {
+ final String contents = getFileContents(actualFile);
+ if (!contents.isEmpty()) {
+ if (isOutputScript) {
+ extractConfigureScriptEvidence(dependency, name,
+ contents);
+ } else {
+ gatherEvidence(dependency, name, contents);
+ }
+ }
+ }
+ } else {
+ // copy, alter and set in case some other thread is iterating over
+ final List deps = new ArrayList(
+ engine.getDependencies());
+ deps.remove(dependency);
+ engine.setDependencies(deps);
+ }
+ }
- private String getFileContents(final File actualFile)
- throws AnalysisException {
- String contents = "";
- try {
- contents = FileUtils.readFileToString(actualFile).trim();
- } catch (IOException e) {
- throw new AnalysisException(
- "Problem occured while reading dependency file.", e);
- }
- return contents;
- }
+ /**
+ * Extracts evidence from the configuration.
+ *
+ * @param dependency the dependency being analyzed
+ * @param name the name of the source of evidence
+ * @param contents the contents to analyze for evidence
+ */
+ private void extractConfigureScriptEvidence(Dependency dependency,
+ final String name, final String contents) {
+ final Matcher matcher = PACKAGE_VAR.matcher(contents);
+ while (matcher.find()) {
+ final String variable = matcher.group(1);
+ final String value = matcher.group(2);
+ if (!value.isEmpty()) {
+ if (variable.endsWith("NAME")) {
+ dependency.getProductEvidence().addEvidence(name, variable,
+ value, Confidence.HIGHEST);
+ } else if ("VERSION".equals(variable)) {
+ dependency.getVersionEvidence().addEvidence(name, variable,
+ value, Confidence.HIGHEST);
+ } else if ("BUGREPORT".equals(variable)) {
+ dependency.getVendorEvidence().addEvidence(name, variable,
+ value, Confidence.HIGH);
+ } else if ("URL".equals(variable)) {
+ dependency.getVendorEvidence().addEvidence(name, variable,
+ value, Confidence.HIGH);
+ }
+ }
+ }
+ }
- private void gatherEvidence(Dependency dependency, final String name,
- String contents) {
- final Matcher matcher = AC_INIT_PATTERN.matcher(contents);
- if (matcher.find()) {
- final EvidenceCollection productEvidence = dependency
- .getProductEvidence();
- productEvidence.addEvidence(name, "Package", matcher.group(1),
- Confidence.HIGHEST);
- dependency.getVersionEvidence().addEvidence(name,
- "Package Version", matcher.group(2), Confidence.HIGHEST);
- final EvidenceCollection vendorEvidence = dependency
- .getVendorEvidence();
- if (null != matcher.group(3)) {
- vendorEvidence.addEvidence(name, "Bug report address",
- matcher.group(4), Confidence.HIGH);
- }
- if (null != matcher.group(5)) {
- productEvidence.addEvidence(name, "Tarname", matcher.group(6),
- Confidence.HIGH);
- }
- if (null != matcher.group(7)) {
- final String url = matcher.group(8);
- if (UrlStringUtils.isUrl(url)) {
- vendorEvidence.addEvidence(name, "URL", url,
- Confidence.HIGH);
- }
- }
- }
- }
+ /**
+ * Retrieves the contents of a given file.
+ *
+ * @param actualFile the file to read
+ * @return the contents of the file
+ * @throws AnalysisException thrown if there is an IO Exception
+ */
+ private String getFileContents(final File actualFile)
+ throws AnalysisException {
+ String contents = "";
+ try {
+ contents = FileUtils.readFileToString(actualFile).trim();
+ } catch (IOException e) {
+ throw new AnalysisException(
+ "Problem occured while reading dependency file.", e);
+ }
+ return contents;
+ }
- /**
- * Initializes the file type analyzer.
- *
- * @throws Exception
- * thrown if there is an exception during initialization
- */
- @Override
- protected void initializeFileTypeAnalyzer() throws Exception {
- // No initialization needed.
- }
-}
\ No newline at end of file
+ /**
+ * Gathers evidence from a given file
+ *
+ * @param dependency the dependency to add evidence to
+ * @param name the source of the evidence
+ * @param contents the evidence to analyze
+ */
+ private void gatherEvidence(Dependency dependency, final String name,
+ String contents) {
+ final Matcher matcher = AC_INIT_PATTERN.matcher(contents);
+ if (matcher.find()) {
+ final EvidenceCollection productEvidence = dependency
+ .getProductEvidence();
+ productEvidence.addEvidence(name, "Package", matcher.group(1),
+ Confidence.HIGHEST);
+ dependency.getVersionEvidence().addEvidence(name,
+ "Package Version", matcher.group(2), Confidence.HIGHEST);
+ final EvidenceCollection vendorEvidence = dependency
+ .getVendorEvidence();
+ if (null != matcher.group(3)) {
+ vendorEvidence.addEvidence(name, "Bug report address",
+ matcher.group(4), Confidence.HIGH);
+ }
+ if (null != matcher.group(5)) {
+ productEvidence.addEvidence(name, "Tarname", matcher.group(6),
+ Confidence.HIGH);
+ }
+ if (null != matcher.group(7)) {
+ final String url = matcher.group(8);
+ if (UrlStringUtils.isUrl(url)) {
+ vendorEvidence.addEvidence(name, "URL", url,
+ Confidence.HIGH);
+ }
+ }
+ }
+ }
+
+ /**
+ * Initializes the file type analyzer.
+ *
+ * @throws Exception thrown if there is an exception during initialization
+ */
+ @Override
+ protected void initializeFileTypeAnalyzer() throws Exception {
+ // No initialization needed.
+ }
+}
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java
index a44b7f5f5..f9c180446 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java
@@ -657,6 +657,9 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
final String source = "Manifest";
+ String specificationVersion = null;
+ boolean hasImplementationVersion = false;
+
for (Entry