diff --git a/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java b/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java
index 3f6a5556f2a..684f74b031d 100644
--- a/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java
+++ b/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java
@@ -302,6 +302,10 @@ public class Check extends Update {
* Whether the pip analyzer should be enabled.
*/
private Boolean pipAnalyzerEnabled;
+ /**
+ * Whether the Maven install.json analyzer should be enabled.
+ */
+ private Boolean mavenInstallAnalyzerEnabled;
/**
* Whether the pipfile analyzer should be enabled.
*/
@@ -1986,6 +1990,7 @@ protected void populateSettings() throws BuildException {
getSettings().setStringIfNotNull(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, bundleAuditPath);
getSettings().setStringIfNotNull(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_WORKING_DIRECTORY, bundleAuditWorkingDirectory);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled);
+ getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_MAVEN_INSTALL_ENABLED, mavenInstallAnalyzerEnabled);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_PIP_ENABLED, pipAnalyzerEnabled);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_PIPFILE_ENABLED, pipfileAnalyzerEnabled);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled);
diff --git a/cli/src/main/java/org/owasp/dependencycheck/App.java b/cli/src/main/java/org/owasp/dependencycheck/App.java
index acfd6f7737c..9cb11c3f56a 100644
--- a/cli/src/main/java/org/owasp/dependencycheck/App.java
+++ b/cli/src/main/java/org/owasp/dependencycheck/App.java
@@ -511,6 +511,8 @@ protected void populateSettings(CliParser cli) throws InvalidSettingException {
!cli.hasDisableOption(CliParser.ARGUMENT.DISABLE_PY_PKG, Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED));
settings.setBoolean(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED,
!cli.hasDisableOption(CliParser.ARGUMENT.DISABLE_AUTOCONF, Settings.KEYS.ANALYZER_AUTOCONF_ENABLED));
+ settings.setBoolean(Settings.KEYS.ANALYZER_MAVEN_INSTALL_ENABLED,
+ !cli.hasDisableOption(CliParser.ARGUMENT.DISABLE_MAVEN_INSTALL, Settings.KEYS.ANALYZER_MAVEN_INSTALL_ENABLED));
settings.setBoolean(Settings.KEYS.ANALYZER_PIP_ENABLED,
!cli.hasDisableOption(CliParser.ARGUMENT.DISABLE_PIP, Settings.KEYS.ANALYZER_PIP_ENABLED));
settings.setBoolean(Settings.KEYS.ANALYZER_PIPFILE_ENABLED,
diff --git a/cli/src/main/java/org/owasp/dependencycheck/CliParser.java b/cli/src/main/java/org/owasp/dependencycheck/CliParser.java
index f2263123615..a70c43ab5a5 100644
--- a/cli/src/main/java/org/owasp/dependencycheck/CliParser.java
+++ b/cli/src/main/java/org/owasp/dependencycheck/CliParser.java
@@ -1196,6 +1196,10 @@ public static class ARGUMENT {
* Disables the Autoconf Analyzer.
*/
public static final String DISABLE_AUTOCONF = "disableAutoconf";
+ /**
+ * Disables the Maven install Analyzer.
+ */
+ public static final String DISABLE_MAVEN_INSTALL = "disableMavenInstall";
/**
* Disables the pip Analyzer.
*/
diff --git a/cli/src/test/resources/sample.properties b/cli/src/test/resources/sample.properties
index e82ad42eee9..e47f5af1e00 100644
--- a/cli/src/test/resources/sample.properties
+++ b/cli/src/test/resources/sample.properties
@@ -9,6 +9,7 @@ analyzer.python.distribution.enabled=true
analyzer.python.package.enabled=true
analyzer.ruby.gemspec.enabled=true
analyzer.autoconf.enabled=true
+analyzer.maveninstall.enabled=true
analyzer.pip.enabled=true
analyzer.pipfile.enabled=true
analyzer.cmake.enabled=true
diff --git a/cli/src/test/resources/sample2.properties b/cli/src/test/resources/sample2.properties
index 1b145acb1cf..3baaa1c6d38 100644
--- a/cli/src/test/resources/sample2.properties
+++ b/cli/src/test/resources/sample2.properties
@@ -9,6 +9,7 @@ analyzer.python.distribution.enabled=false
analyzer.python.package.enabled=false
analyzer.ruby.gemspec.enabled=false
analyzer.autoconf.enabled=false
+analyzer.maveninstall.enabled=false
analyzer.pip.enabled=false
analyzer.pipfile.enabled=false
analyzer.cmake.enabled=false
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/PinnedMavenInstallAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/PinnedMavenInstallAnalyzer.java
new file mode 100644
index 00000000000..33a57689441
--- /dev/null
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/PinnedMavenInstallAnalyzer.java
@@ -0,0 +1,262 @@
+/*
+ * 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) 2020 The OWASP Foundation. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.analyzer;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
+import com.github.packageurl.MalformedPackageURLException;
+import com.github.packageurl.PackageURL;
+import com.github.packageurl.PackageURLBuilder;
+import org.owasp.dependencycheck.Engine;
+import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
+import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
+import org.owasp.dependencycheck.dependency.Confidence;
+import org.owasp.dependencycheck.dependency.Dependency;
+import org.owasp.dependencycheck.dependency.EvidenceType;
+import org.owasp.dependencycheck.dependency.naming.GenericIdentifier;
+import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
+import org.owasp.dependencycheck.utils.Settings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.concurrent.ThreadSafe;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.regex.Pattern;
+
+/**
+ * Used to analyze Maven pinned dependency files named {@code *install*.json}, a Java Maven dependency lockfile
+ * like Python's {@code requirements.txt}.
+ *
+ * @author dhalperi
+ * @see rules_jvm_external
+ */
+@Experimental
+@ThreadSafe
+public class PinnedMavenInstallAnalyzer extends AbstractFileTypeAnalyzer {
+
+ /**
+ * The logger.
+ */
+ private static final Logger LOGGER = LoggerFactory.getLogger(PinnedMavenInstallAnalyzer.class);
+
+ /**
+ * The name of the analyzer.
+ */
+ private static final String ANALYZER_NAME = "Pinned Maven install Analyzer";
+
+ /**
+ * The phase that this analyzer is intended to run in.
+ */
+ private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
+
+ /**
+ * Pattern matching files with "install" in the basename and extension "json".
+ *
+ *
This regex is designed to explicitly skip files named {@code install.json} since those are used for
+ * Cloudflare installations and this will save on work.
+ */
+ private static final Pattern MAVEN_INSTALL_JSON_PATTERN = Pattern.compile("(.+install.*|.*install.+)\\.json");
+
+ /**
+ * Match any files that look like *install*.json.
+ */
+ private static final FileFilter FILTER = (File file) -> MAVEN_INSTALL_JSON_PATTERN.matcher(file.getName()).matches();
+
+ @Override
+ protected FileFilter getFileFilter() {
+ return FILTER;
+ }
+
+ @Override
+ public String getName() {
+ return ANALYZER_NAME;
+ }
+
+ @Override
+ public AnalysisPhase getAnalysisPhase() {
+ return ANALYSIS_PHASE;
+ }
+
+ @Override
+ protected String getAnalyzerEnabledSettingKey() {
+ return Settings.KEYS.ANALYZER_MAVEN_INSTALL_ENABLED;
+ }
+
+ @Override
+ protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
+ LOGGER.debug("Checking file {}", dependency.getActualFilePath());
+
+ final File dependencyFile = dependency.getActualFile();
+ if (!dependencyFile.isFile() || dependencyFile.length() == 0) {
+ return;
+ }
+
+ DependencyTree tree;
+ try {
+ InstallFile installFile = INSTALL_FILE_READER.readValue(dependencyFile);
+ tree = installFile.dependencyTree;
+ } catch (IOException e) {
+ return;
+ }
+
+ if (tree == null) {
+ return;
+ } else if (!Objects.equals(tree.autogeneratedSentinel, "THERE_IS_NO_DATA_ONLY_ZUUL")) {
+ return;
+ }
+
+ engine.removeDependency(dependency);
+
+ if (!Objects.equals(tree.version, "0.1.0")) {
+ LOGGER.warn("Unsupported pinned maven_install.json version {}. Continuing optimistically.", tree.version);
+ }
+
+ List deps = tree.dependencies;
+ if (deps == null) {
+ deps = Collections.emptyList();
+ }
+
+ for (MavenDependency dep : deps) {
+ if (dep.coord == null) {
+ LOGGER.warn("Unexpected null coordinate in {}", dependency.getActualFilePath());
+ continue;
+ }
+
+ LOGGER.debug("Analyzing {}", dep.coord);
+ String[] pieces = dep.coord.split(":");
+ if (pieces.length < 3 || pieces.length > 5) {
+ LOGGER.warn("Invalid maven coordinate {}", dep.coord);
+ continue;
+ }
+
+ String group = pieces[0];
+ String artifact = pieces[1];
+ String version;
+ String classifier = null;
+ if (pieces.length == 3) {
+ version = pieces[2];
+ } else if (pieces.length == 4) {
+ classifier = pieces[2];
+ version = pieces[3];
+ } else {
+ // length == 5 as guaranteed above.
+ classifier = pieces[3];
+ version = pieces[4];
+ }
+
+ if ("sources".equals(classifier) || "javadoc".equals(classifier)) {
+ LOGGER.debug("Skipping sources jar {}", dep.coord);
+ continue;
+ }
+
+ final Dependency d = new Dependency(dependency.getActualFile(), true);
+ d.setEcosystem(Ecosystem.JAVA);
+ d.addEvidence(EvidenceType.VENDOR, "project", "groupid", group, Confidence.HIGHEST);
+ d.addEvidence(EvidenceType.PRODUCT, "project", "artifactid", artifact, Confidence.HIGHEST);
+ d.addEvidence(EvidenceType.VERSION, "project", "version", version, Confidence.HIGHEST);
+ d.setName(String.format("%s:%s", group, artifact));
+ d.setFilePath(String.format("%s>>%s", dependency.getActualFile(), dep.coord));
+ d.setFileName(dep.coord);
+ try {
+ final PackageURLBuilder purl = PackageURLBuilder.aPackageURL()
+ .withType(PackageURL.StandardTypes.MAVEN)
+ .withNamespace(group)
+ .withName(artifact)
+ .withVersion(version);
+ if (classifier != null) {
+ purl.withQualifier("classifier", classifier);
+ }
+ d.addSoftwareIdentifier(new PurlIdentifier(purl.build(), Confidence.HIGHEST));
+ } catch (MalformedPackageURLException e) {
+ d.addSoftwareIdentifier(new GenericIdentifier("maven_install JSON coord " + dep.coord, Confidence.HIGH));
+ }
+ d.setVersion(version);
+ engine.addDependency(d);
+ }
+ }
+
+ @Override
+ protected void prepareFileTypeAnalyzer(Engine engine) {
+ // No initialization needed.
+ }
+
+ /**
+ * Represents the entire pinned Maven dependency set in an install.json file.
+ *
+ * At the time of writing, the latest version is 0.1.0, and the dependencies are stored in {@code .dependency_tree.dependencies[].coord}.
+ *
+ *
The only top-level key we care about is {@code .dependency_tree}.
+ */
+ private static class InstallFile {
+ @JsonProperty("dependency_tree")
+ public DependencyTree dependencyTree;
+ }
+
+ /**
+ * Represents the values at {@code .dependency_tree} in the {@link InstallFile install file}.
+ */
+ private static class DependencyTree {
+ /**
+ * A sentinel value placed in the file to indicate that it is an auto-generated pinned maven install file.
+ */
+ @JsonProperty("__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY")
+ public String autogeneratedSentinel;
+
+ /**
+ * A list of Maven dependencies made available. Note that this list is transitively closed and pinned to a specific version of each artifact.
+ */
+ @JsonProperty("dependencies")
+ public List dependencies;
+
+ /**
+ * The file format version.
+ */
+ @JsonProperty("version")
+ public String version;
+ }
+
+ /**
+ * Represents a single dependency in the list at {@code .dependency_tree.dependencies}.
+ */
+ private static class MavenDependency {
+ /**
+ * The standard Maven coordinate string {@code group:artifact[:optional classifier][:optional packaging]:version}.
+ */
+ @JsonProperty("coord")
+ public String coord;
+ }
+
+ /**
+ * A reusable reader for {@link InstallFile}.
+ */
+ private static final ObjectReader INSTALL_FILE_READER;
+
+ static {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ INSTALL_FILE_READER = mapper.readerFor(InstallFile.class);
+ }
+}
diff --git a/core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer b/core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer
index 65ac43b55ab..9f70c0ee7cc 100644
--- a/core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer
+++ b/core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer
@@ -42,3 +42,4 @@ org.owasp.dependencycheck.analyzer.SwiftPackageResolvedAnalyzer
org.owasp.dependencycheck.analyzer.VersionFilterAnalyzer
org.owasp.dependencycheck.analyzer.OssIndexAnalyzer
org.owasp.dependencycheck.analyzer.PerlCpanfileAnalyzer
+org.owasp.dependencycheck.analyzer.PinnedMavenInstallAnalyzer
diff --git a/core/src/main/resources/dependencycheck.properties b/core/src/main/resources/dependencycheck.properties
index 3b233fcaa6b..4ea60acb863 100644
--- a/core/src/main/resources/dependencycheck.properties
+++ b/core/src/main/resources/dependencycheck.properties
@@ -129,6 +129,7 @@ analyzer.python.package.enabled=true
analyzer.ruby.gemspec.enabled=true
analyzer.bundle.audit.enabled=true
analyzer.autoconf.enabled=true
+analyzer.maveninstall.enabled=true
analyzer.pip.enabled=true
analyzer.pipfile.enabled=true
analyzer.cmake.enabled=true
diff --git a/core/src/test/java/org/owasp/dependencycheck/analyzer/PinnedMavenInstallAnalyzerTest.java b/core/src/test/java/org/owasp/dependencycheck/analyzer/PinnedMavenInstallAnalyzerTest.java
new file mode 100644
index 00000000000..5732bb7d39e
--- /dev/null
+++ b/core/src/test/java/org/owasp/dependencycheck/analyzer/PinnedMavenInstallAnalyzerTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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) 2020 The OWASP Foundation. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.analyzer;
+
+import org.apache.commons.lang3.ArrayUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.owasp.dependencycheck.BaseDBTestCase;
+import org.owasp.dependencycheck.BaseTest;
+import org.owasp.dependencycheck.Engine;
+import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
+import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
+import org.owasp.dependencycheck.dependency.Dependency;
+
+import java.io.File;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.*;
+
+/**
+ * Unit tests for {@link PinnedMavenInstallAnalyzer}.
+ */
+public class PinnedMavenInstallAnalyzerTest extends BaseDBTestCase {
+
+ /**
+ * The analyzer to test.
+ */
+ private PinnedMavenInstallAnalyzer analyzer;
+
+ /**
+ * Correctly set up the analyzer for testing.
+ *
+ * @throws Exception thrown if there is a problem
+ */
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ analyzer = new PinnedMavenInstallAnalyzer();
+ analyzer.initialize(getSettings());
+ analyzer.setFilesMatched(true);
+ analyzer.prepare(null);
+ }
+
+ /**
+ * Cleanup the analyzer's temp files, etc.
+ *
+ * @throws Exception thrown if there is a problem
+ */
+ @After
+ @Override
+ public void tearDown() throws Exception {
+ analyzer.close();
+ super.tearDown();
+ }
+
+ @Test
+ public void testGetName() {
+ assertEquals("Pinned Maven install Analyzer", analyzer.getName());
+ }
+
+ @Test
+ public void testSupportsFiles() {
+ assertTrue(analyzer.accept(new File("install_maven.json")));
+ assertTrue(analyzer.accept(new File("maven_install.json")));
+ assertTrue(analyzer.accept(new File("rules_jvm_external_install.json")));
+ assertTrue(analyzer.accept(new File("pinned_install_gplonly.json")));
+ assertFalse("should not accept Cloudflare install.json", analyzer.accept(new File("install.json")));
+ assertFalse(analyzer.accept(new File("maven_install.txt")));
+ assertFalse(analyzer.accept(new File("pinned.json")));
+ assertFalse(analyzer.accept(new File("install.json.zip")));
+ }
+
+ /**
+ * Tests that the analyzer correctly pulls dependencies out of a pinned {@code maven_install.json}.
+ */
+ @Test
+ public void testAnalyzePinnedInstallJson() throws Exception {
+ try (Engine engine = new Engine(getSettings())) {
+ final Dependency result = new Dependency(BaseTest.getResourceAsFile(this, "maven_install.json"));
+ engine.addDependency(result);
+ analyzer.analyze(result, engine);
+ assertFalse(ArrayUtils.contains(engine.getDependencies(), result));
+ assertEquals(10, engine.getDependencies().length);
+ boolean found = false;
+ for (Dependency d : engine.getDependencies()) {
+ if ("com.google.errorprone:error_prone_annotations".equals(d.getName())) {
+ found = true;
+ assertEquals("2.3.4", d.getVersion());
+ assertEquals(Ecosystem.JAVA, d.getEcosystem());
+ }
+ }
+ assertTrue("Expected to find com.google.errorprone:error_prone_annotations:2.3.4", found);
+ }
+ }
+
+ /**
+ * Tests that the analyzer ignores a Cloudflare-style {@code install.json}.
+ */
+ @Test
+ public void testAnalyzeOtherInstallJson() throws Exception {
+ try (Engine engine = new Engine(getSettings())) {
+ final Dependency result = new Dependency(BaseTest.getResourceAsFile(this, "install.json"));
+ engine.addDependency(result);
+ analyzer.analyze(result, engine);
+ assertTrue(ArrayUtils.contains(engine.getDependencies(), result));
+ assertEquals(1, engine.getDependencies().length);
+ }
+ }
+}
diff --git a/core/src/test/resources/dependencycheck.properties b/core/src/test/resources/dependencycheck.properties
index 72293950ce2..751c6706943 100644
--- a/core/src/test/resources/dependencycheck.properties
+++ b/core/src/test/resources/dependencycheck.properties
@@ -110,6 +110,7 @@ analyzer.python.distribution.enabled=true
analyzer.python.package.enabled=true
analyzer.ruby.gemspec.enabled=true
analyzer.autoconf.enabled=true
+analyzer.maveninstall.enabled=true
analyzer.pip.enabled=true
analyzer.pipfile.enabled=true
analyzer.cmake.enabled=true
diff --git a/maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java b/maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java
index 586a077e8b5..154a0f6dde4 100644
--- a/maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java
+++ b/maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java
@@ -438,6 +438,12 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
@SuppressWarnings("CanBeFinal")
@Parameter(property = "autoconfAnalyzerEnabled")
private Boolean autoconfAnalyzerEnabled;
+ /**
+ * Sets whether or not the Maven install Analyzer should be used.
+ */
+ @SuppressWarnings("CanBeFinal")
+ @Parameter(property = "mavenInstallAnalyzerEnabled")
+ private Boolean mavenInstallAnalyzerEnabled;
/**
* Sets whether or not the pip Analyzer should be used.
*/
@@ -2095,6 +2101,7 @@ protected void populateSettings() {
settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled);
settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled);
settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled);
+ settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_MAVEN_INSTALL_ENABLED, mavenInstallAnalyzerEnabled);
settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PIP_ENABLED, pipAnalyzerEnabled);
settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PIPFILE_ENABLED, pipfileAnalyzerEnabled);
settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled);
diff --git a/src/test/resources/install.json b/src/test/resources/install.json
new file mode 100644
index 00000000000..bc07b9f1c39
--- /dev/null
+++ b/src/test/resources/install.json
@@ -0,0 +1,15 @@
+{
+ "$schema": "http://json.schemastore.org/install",
+ "resources": {
+ "head": [],
+ "body": []
+ },
+ "options": {
+ "properties": {}
+ },
+ "preview": {
+ "handlers": []
+ },
+ "hooks": [],
+ "dns": []
+}
\ No newline at end of file
diff --git a/src/test/resources/maven_install.json b/src/test/resources/maven_install.json
new file mode 100644
index 00000000000..d9ace0113c8
--- /dev/null
+++ b/src/test/resources/maven_install.json
@@ -0,0 +1,296 @@
+{
+ "dependency_tree": {
+ "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL",
+ "__INPUT_ARTIFACTS_HASH": -501192379,
+ "__RESOLVED_ARTIFACTS_HASH": -859727869,
+ "conflict_resolution": {},
+ "dependencies": [
+ {
+ "coord": "com.google.code.findbugs:jsr305:3.0.2",
+ "dependencies": [],
+ "directDependencies": [],
+ "file": "v1/https/repo1.maven.org/maven2/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar"
+ ],
+ "sha256": "766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7",
+ "url": "https://repo1.maven.org/maven2/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar"
+ },
+ {
+ "coord": "com.google.code.findbugs:jsr305:jar:sources:3.0.2",
+ "dependencies": [],
+ "directDependencies": [],
+ "file": "v1/https/repo1.maven.org/maven2/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2-sources.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2-sources.jar"
+ ],
+ "sha256": "1c9e85e272d0708c6a591dc74828c71603053b48cc75ae83cce56912a2aa063b",
+ "url": "https://repo1.maven.org/maven2/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2-sources.jar"
+ },
+ {
+ "coord": "com.google.errorprone:error_prone_annotations:2.3.4",
+ "dependencies": [],
+ "directDependencies": [],
+ "file": "v1/https/repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations/2.3.4/error_prone_annotations-2.3.4.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations/2.3.4/error_prone_annotations-2.3.4.jar"
+ ],
+ "sha256": "baf7d6ea97ce606c53e11b6854ba5f2ce7ef5c24dddf0afa18d1260bd25b002c",
+ "url": "https://repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations/2.3.4/error_prone_annotations-2.3.4.jar"
+ },
+ {
+ "coord": "com.google.errorprone:error_prone_annotations:jar:sources:2.3.4",
+ "dependencies": [],
+ "directDependencies": [],
+ "file": "v1/https/repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations/2.3.4/error_prone_annotations-2.3.4-sources.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations/2.3.4/error_prone_annotations-2.3.4-sources.jar"
+ ],
+ "sha256": "0b1011d1e2ea2eab35a545cffd1cff3877f131134c8020885e8eaf60a7d72f91",
+ "url": "https://repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations/2.3.4/error_prone_annotations-2.3.4-sources.jar"
+ },
+ {
+ "coord": "com.google.guava:failureaccess:1.0.1",
+ "dependencies": [],
+ "directDependencies": [],
+ "file": "v1/https/repo1.maven.org/maven2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar"
+ ],
+ "sha256": "a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26",
+ "url": "https://repo1.maven.org/maven2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar"
+ },
+ {
+ "coord": "com.google.guava:failureaccess:jar:sources:1.0.1",
+ "dependencies": [],
+ "directDependencies": [],
+ "file": "v1/https/repo1.maven.org/maven2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1-sources.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1-sources.jar"
+ ],
+ "sha256": "092346eebbb1657b51aa7485a246bf602bb464cc0b0e2e1c7e7201fadce1e98f",
+ "url": "https://repo1.maven.org/maven2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1-sources.jar"
+ },
+ {
+ "coord": "com.google.guava:guava-testlib:29.0-jre",
+ "dependencies": [
+ "com.google.code.findbugs:jsr305:3.0.2",
+ "com.google.errorprone:error_prone_annotations:2.3.4",
+ "com.google.guava:failureaccess:1.0.1",
+ "com.google.guava:guava:29.0-jre",
+ "com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava",
+ "com.google.j2objc:j2objc-annotations:1.3",
+ "junit:junit:4.13",
+ "org.checkerframework:checker-qual:2.11.1",
+ "org.hamcrest:hamcrest-core:1.3"
+ ],
+ "directDependencies": [
+ "com.google.code.findbugs:jsr305:3.0.2",
+ "com.google.errorprone:error_prone_annotations:2.3.4",
+ "com.google.guava:guava:29.0-jre",
+ "com.google.j2objc:j2objc-annotations:1.3",
+ "junit:junit:4.13",
+ "org.checkerframework:checker-qual:2.11.1"
+ ],
+ "file": "v1/https/repo1.maven.org/maven2/com/google/guava/guava-testlib/29.0-jre/guava-testlib-29.0-jre.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/com/google/guava/guava-testlib/29.0-jre/guava-testlib-29.0-jre.jar"
+ ],
+ "sha256": "f15908de80ff261adde7823d1df599b7447de4863f7c521068ecf881cb1fc79b",
+ "url": "https://repo1.maven.org/maven2/com/google/guava/guava-testlib/29.0-jre/guava-testlib-29.0-jre.jar"
+ },
+ {
+ "coord": "com.google.guava:guava-testlib:jar:sources:29.0-jre",
+ "dependencies": [
+ "com.google.code.findbugs:jsr305:jar:sources:3.0.2",
+ "com.google.errorprone:error_prone_annotations:jar:sources:2.3.4",
+ "com.google.guava:failureaccess:jar:sources:1.0.1",
+ "com.google.guava:guava:jar:sources:29.0-jre",
+ "com.google.guava:listenablefuture:jar:sources:9999.0-empty-to-avoid-conflict-with-guava",
+ "com.google.j2objc:j2objc-annotations:jar:sources:1.3",
+ "junit:junit:jar:sources:4.13",
+ "org.checkerframework:checker-qual:jar:sources:2.11.1",
+ "org.hamcrest:hamcrest-core:jar:sources:1.3"
+ ],
+ "directDependencies": [
+ "com.google.code.findbugs:jsr305:jar:sources:3.0.2",
+ "com.google.errorprone:error_prone_annotations:jar:sources:2.3.4",
+ "com.google.guava:guava:jar:sources:29.0-jre",
+ "com.google.j2objc:j2objc-annotations:jar:sources:1.3",
+ "junit:junit:jar:sources:4.13",
+ "org.checkerframework:checker-qual:jar:sources:2.11.1"
+ ],
+ "file": "v1/https/repo1.maven.org/maven2/com/google/guava/guava-testlib/29.0-jre/guava-testlib-29.0-jre-sources.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/com/google/guava/guava-testlib/29.0-jre/guava-testlib-29.0-jre-sources.jar"
+ ],
+ "sha256": "810a5ebff92f48af06e47ba3fb35c9ee38b777b5bf25eb2b1c99b595c53d0fe8",
+ "url": "https://repo1.maven.org/maven2/com/google/guava/guava-testlib/29.0-jre/guava-testlib-29.0-jre-sources.jar"
+ },
+ {
+ "coord": "com.google.guava:guava:29.0-jre",
+ "dependencies": [
+ "com.google.code.findbugs:jsr305:3.0.2",
+ "com.google.errorprone:error_prone_annotations:2.3.4",
+ "com.google.guava:failureaccess:1.0.1",
+ "com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava",
+ "com.google.j2objc:j2objc-annotations:1.3",
+ "org.checkerframework:checker-qual:2.11.1"
+ ],
+ "directDependencies": [
+ "com.google.code.findbugs:jsr305:3.0.2",
+ "com.google.errorprone:error_prone_annotations:2.3.4",
+ "com.google.guava:failureaccess:1.0.1",
+ "com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava",
+ "com.google.j2objc:j2objc-annotations:1.3",
+ "org.checkerframework:checker-qual:2.11.1"
+ ],
+ "file": "v1/https/repo1.maven.org/maven2/com/google/guava/guava/29.0-jre/guava-29.0-jre.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/com/google/guava/guava/29.0-jre/guava-29.0-jre.jar"
+ ],
+ "sha256": "b22c5fb66d61e7b9522531d04b2f915b5158e80aa0b40ee7282c8bfb07b0da25",
+ "url": "https://repo1.maven.org/maven2/com/google/guava/guava/29.0-jre/guava-29.0-jre.jar"
+ },
+ {
+ "coord": "com.google.guava:guava:jar:sources:29.0-jre",
+ "dependencies": [
+ "com.google.code.findbugs:jsr305:jar:sources:3.0.2",
+ "com.google.errorprone:error_prone_annotations:jar:sources:2.3.4",
+ "com.google.guava:failureaccess:jar:sources:1.0.1",
+ "com.google.guava:listenablefuture:jar:sources:9999.0-empty-to-avoid-conflict-with-guava",
+ "com.google.j2objc:j2objc-annotations:jar:sources:1.3",
+ "org.checkerframework:checker-qual:jar:sources:2.11.1"
+ ],
+ "directDependencies": [
+ "com.google.code.findbugs:jsr305:jar:sources:3.0.2",
+ "com.google.errorprone:error_prone_annotations:jar:sources:2.3.4",
+ "com.google.guava:failureaccess:jar:sources:1.0.1",
+ "com.google.guava:listenablefuture:jar:sources:9999.0-empty-to-avoid-conflict-with-guava",
+ "com.google.j2objc:j2objc-annotations:jar:sources:1.3",
+ "org.checkerframework:checker-qual:jar:sources:2.11.1"
+ ],
+ "file": "v1/https/repo1.maven.org/maven2/com/google/guava/guava/29.0-jre/guava-29.0-jre-sources.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/com/google/guava/guava/29.0-jre/guava-29.0-jre-sources.jar"
+ ],
+ "sha256": "cfcbe29dd5125f5b360370b4ecd7f7ef44fba68f4f037e90bce7315682afc0ea",
+ "url": "https://repo1.maven.org/maven2/com/google/guava/guava/29.0-jre/guava-29.0-jre-sources.jar"
+ },
+ {
+ "coord": "com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava",
+ "dependencies": [],
+ "directDependencies": [],
+ "file": "v1/https/repo1.maven.org/maven2/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar"
+ ],
+ "sha256": "b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99",
+ "url": "https://repo1.maven.org/maven2/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar"
+ },
+ {
+ "coord": "com.google.guava:listenablefuture:jar:sources:9999.0-empty-to-avoid-conflict-with-guava",
+ "dependencies": [],
+ "directDependencies": [],
+ "file": null
+ },
+ {
+ "coord": "com.google.j2objc:j2objc-annotations:1.3",
+ "dependencies": [],
+ "directDependencies": [],
+ "file": "v1/https/repo1.maven.org/maven2/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.jar"
+ ],
+ "sha256": "21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b",
+ "url": "https://repo1.maven.org/maven2/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.jar"
+ },
+ {
+ "coord": "com.google.j2objc:j2objc-annotations:jar:sources:1.3",
+ "dependencies": [],
+ "directDependencies": [],
+ "file": "v1/https/repo1.maven.org/maven2/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3-sources.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3-sources.jar"
+ ],
+ "sha256": "ba4df669fec153fa4cd0ef8d02c6d3ef0702b7ac4cabe080facf3b6e490bb972",
+ "url": "https://repo1.maven.org/maven2/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3-sources.jar"
+ },
+ {
+ "coord": "junit:junit:4.13",
+ "dependencies": [
+ "org.hamcrest:hamcrest-core:1.3"
+ ],
+ "directDependencies": [
+ "org.hamcrest:hamcrest-core:1.3"
+ ],
+ "file": "v1/https/repo1.maven.org/maven2/junit/junit/4.13/junit-4.13.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/junit/junit/4.13/junit-4.13.jar"
+ ],
+ "sha256": "4b8532f63bdc0e0661507f947eb324a954d1dbac631ad19c8aa9a00feed1d863",
+ "url": "https://repo1.maven.org/maven2/junit/junit/4.13/junit-4.13.jar"
+ },
+ {
+ "coord": "junit:junit:jar:sources:4.13",
+ "dependencies": [
+ "org.hamcrest:hamcrest-core:jar:sources:1.3"
+ ],
+ "directDependencies": [
+ "org.hamcrest:hamcrest-core:jar:sources:1.3"
+ ],
+ "file": "v1/https/repo1.maven.org/maven2/junit/junit/4.13/junit-4.13-sources.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/junit/junit/4.13/junit-4.13-sources.jar"
+ ],
+ "sha256": "3d5451031736d4904582b211858a09eeefdb26eb08f0633ca8addf04fde3e0fc",
+ "url": "https://repo1.maven.org/maven2/junit/junit/4.13/junit-4.13-sources.jar"
+ },
+ {
+ "coord": "org.checkerframework:checker-qual:2.11.1",
+ "dependencies": [],
+ "directDependencies": [],
+ "file": "v1/https/repo1.maven.org/maven2/org/checkerframework/checker-qual/2.11.1/checker-qual-2.11.1.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/org/checkerframework/checker-qual/2.11.1/checker-qual-2.11.1.jar"
+ ],
+ "sha256": "015224a4b1dc6de6da053273d4da7d39cfea20e63038169fc45ac0d1dc9c5938",
+ "url": "https://repo1.maven.org/maven2/org/checkerframework/checker-qual/2.11.1/checker-qual-2.11.1.jar"
+ },
+ {
+ "coord": "org.checkerframework:checker-qual:jar:sources:2.11.1",
+ "dependencies": [],
+ "directDependencies": [],
+ "file": "v1/https/repo1.maven.org/maven2/org/checkerframework/checker-qual/2.11.1/checker-qual-2.11.1-sources.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/org/checkerframework/checker-qual/2.11.1/checker-qual-2.11.1-sources.jar"
+ ],
+ "sha256": "7d3b990687be9b980a9dc7853f4b0f279eb437e28efe3c9903acaf20450f55b5",
+ "url": "https://repo1.maven.org/maven2/org/checkerframework/checker-qual/2.11.1/checker-qual-2.11.1-sources.jar"
+ },
+ {
+ "coord": "org.hamcrest:hamcrest-core:1.3",
+ "dependencies": [],
+ "directDependencies": [],
+ "file": "v1/https/repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar"
+ ],
+ "sha256": "66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9",
+ "url": "https://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar"
+ },
+ {
+ "coord": "org.hamcrest:hamcrest-core:jar:sources:1.3",
+ "dependencies": [],
+ "directDependencies": [],
+ "file": "v1/https/repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar",
+ "mirror_urls": [
+ "https://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar"
+ ],
+ "sha256": "e223d2d8fbafd66057a8848cc94222d63c3cedd652cc48eddc0ab5c39c0f84df",
+ "url": "https://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar"
+ }
+ ],
+ "version": "0.1.0"
+ }
+}
diff --git a/utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java b/utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java
index b57810d4ac2..51c4bb40e01 100644
--- a/utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java
+++ b/utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java
@@ -429,6 +429,10 @@ public static final class KEYS {
* The properties key for whether the Autoconf analyzer is enabled.
*/
public static final String ANALYZER_AUTOCONF_ENABLED = "analyzer.autoconf.enabled";
+ /**
+ * The properties key for whether the maven_install.json analyzer is enabled.
+ */
+ public static final String ANALYZER_MAVEN_INSTALL_ENABLED = "analyzer.maveninstall.enabled";
/**
* The properties key for whether the pip analyzer is enabled.
*/