diff --git a/ant/pom.xml b/ant/pom.xml
index d0ca1c04098..62bb89aa6bb 100644
--- a/ant/pom.xml
+++ b/ant/pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
org.owasp
dependency-check-parent
- 8.0.3-SNAPSHOT
+ 8.1.0-SNAPSHOT
dependency-check-ant
diff --git a/archetype/pom.xml b/archetype/pom.xml
index 0af2493825a..86f9a459adb 100644
--- a/archetype/pom.xml
+++ b/archetype/pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2017 Jeremy Long. All Rights Reserved.
org.owasp
dependency-check-parent
- 8.0.3-SNAPSHOT
+ 8.1.0-SNAPSHOT
dependency-check-plugin
Dependency-Check Plugin Archetype
diff --git a/cli/pom.xml b/cli/pom.xml
index da18353cc85..5180769dfe8 100644
--- a/cli/pom.xml
+++ b/cli/pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
org.owasp
dependency-check-parent
- 8.0.3-SNAPSHOT
+ 8.1.0-SNAPSHOT
dependency-check-cli
diff --git a/core/pom.xml b/core/pom.xml
index 94b4dd784db..9db5eecfffe 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
org.owasp
dependency-check-parent
- 8.0.3-SNAPSHOT
+ 8.1.0-SNAPSHOT
dependency-check-core
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/PipfileAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/PipfileAnalyzer.java
index c76f516446b..76905edf0bb 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/PipfileAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/PipfileAnalyzer.java
@@ -44,7 +44,11 @@
import org.slf4j.LoggerFactory;
/**
- * Used to analyze Pipfile dependency files named Pipfile.
+ * Used to analyze dependencies defined in Pipfile. This analyzer works in
+ * tandem with the `PipfilelockAnalyzer` - and both analyzers use the same key
+ * to enable/disable the analyzers. The PipfilelockAnalyzer will be used over
+ * the Pipfile if the lock file exists.
+ *
*
* @author fcano
*/
@@ -55,12 +59,15 @@ public class PipfileAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The logger.
*/
- private static final Logger LOGGER = LoggerFactory.getLogger(PythonPackageAnalyzer.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(PipfileAnalyzer.class);
/**
* "Pipfile" file.
*/
- private static final String REQUIREMENTS = "Pipfile";
-
+ private static final String PIPFILE = "Pipfile";
+ /**
+ * "Pipfile.lock" file.
+ */
+ private static final String LOCKFILE = "Pipfile.lock";
/**
* The name of the analyzer.
*/
@@ -79,7 +86,7 @@ public class PipfileAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The file filter used to determine which files this analyzer supports.
*/
- private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames(REQUIREMENTS).build();
+ private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames(PIPFILE).build();
/**
* Returns the FileFilter
@@ -124,51 +131,54 @@ protected String getAnalyzerEnabledSettingKey() {
@Override
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
- LOGGER.debug("Checking file {}", dependency.getActualFilePath());
-
- if (REQUIREMENTS.equals(dependency.getFileName())) {
- engine.removeDependency(dependency);
+ engine.removeDependency(dependency);
+ final File lock = new File(dependency.getActualFile().getParentFile(), LOCKFILE);
+ if (lock.isFile()) {
+ LOGGER.debug("Skipping {} because a lock file was identified", dependency.getActualFilePath());
+ return;
+ } else {
+ LOGGER.debug("Checking file {}", dependency.getActualFilePath());
}
+
final File dependencyFile = dependency.getActualFile();
if (!dependencyFile.isFile() || dependencyFile.length() == 0) {
return;
}
final File actualFile = dependency.getActualFile();
- if (actualFile.getName().equals(REQUIREMENTS)) {
- final String contents = getFileContents(actualFile);
- if (!contents.isEmpty()) {
- final Matcher matcher = PACKAGE_VERSION.matcher(contents);
- while (matcher.find()) {
- final String identifiedPackage = matcher.group(1);
- final String identifiedVersion = matcher.group(2);
- LOGGER.debug(String.format("package, version: %s %s", identifiedPackage, identifiedVersion));
- final Dependency d = new Dependency(dependency.getActualFile(), true);
- d.setName(identifiedPackage);
- d.setVersion(identifiedVersion);
- try {
- final PackageURL purl = PackageURLBuilder.aPackageURL()
- .withType("pypi")
- .withName(identifiedPackage)
- .withVersion(identifiedVersion)
- .build();
- d.addSoftwareIdentifier(new PurlIdentifier(purl, Confidence.HIGHEST));
- } catch (MalformedPackageURLException ex) {
- LOGGER.debug("Unable to build package url for pypi", ex);
- d.addSoftwareIdentifier(new GenericIdentifier("pypi:" + identifiedPackage + "@" + identifiedVersion, Confidence.HIGH));
- }
- d.setPackagePath(String.format("%s:%s", identifiedPackage, identifiedVersion));
- d.setEcosystem(PythonDistributionAnalyzer.DEPENDENCY_ECOSYSTEM);
- final String filePath = String.format("%s:%s/%s", dependency.getFilePath(), identifiedPackage, identifiedVersion);
- d.setFilePath(filePath);
- d.setSha1sum(Checksum.getSHA1Checksum(filePath));
- d.setSha256sum(Checksum.getSHA256Checksum(filePath));
- d.setMd5sum(Checksum.getMD5Checksum(filePath));
- d.addEvidence(EvidenceType.VENDOR, REQUIREMENTS, "vendor", identifiedPackage, Confidence.HIGHEST);
- d.addEvidence(EvidenceType.PRODUCT, REQUIREMENTS, "product", identifiedPackage, Confidence.HIGHEST);
- d.addEvidence(EvidenceType.VERSION, REQUIREMENTS, "version", identifiedVersion, Confidence.HIGHEST);
- engine.addDependency(d);
+
+ final String contents = getFileContents(actualFile);
+ if (!contents.isEmpty()) {
+ final Matcher matcher = PACKAGE_VERSION.matcher(contents);
+ while (matcher.find()) {
+ final String identifiedPackage = matcher.group(1);
+ final String identifiedVersion = matcher.group(2);
+ LOGGER.debug(String.format("package, version: %s %s", identifiedPackage, identifiedVersion));
+ final Dependency d = new Dependency(dependency.getActualFile(), true);
+ d.setName(identifiedPackage);
+ d.setVersion(identifiedVersion);
+ try {
+ final PackageURL purl = PackageURLBuilder.aPackageURL()
+ .withType("pypi")
+ .withName(identifiedPackage)
+ .withVersion(identifiedVersion)
+ .build();
+ d.addSoftwareIdentifier(new PurlIdentifier(purl, Confidence.HIGHEST));
+ } catch (MalformedPackageURLException ex) {
+ LOGGER.debug("Unable to build package url for pypi", ex);
+ d.addSoftwareIdentifier(new GenericIdentifier("pypi:" + identifiedPackage + "@" + identifiedVersion, Confidence.HIGH));
}
+ d.setPackagePath(String.format("%s:%s", identifiedPackage, identifiedVersion));
+ d.setEcosystem(PythonDistributionAnalyzer.DEPENDENCY_ECOSYSTEM);
+ final String filePath = String.format("%s:%s/%s", dependency.getFilePath(), identifiedPackage, identifiedVersion);
+ d.setFilePath(filePath);
+ d.setSha1sum(Checksum.getSHA1Checksum(filePath));
+ d.setSha256sum(Checksum.getSHA256Checksum(filePath));
+ d.setMd5sum(Checksum.getMD5Checksum(filePath));
+ d.addEvidence(EvidenceType.VENDOR, PIPFILE, "vendor", identifiedPackage, Confidence.HIGHEST);
+ d.addEvidence(EvidenceType.PRODUCT, PIPFILE, "product", identifiedPackage, Confidence.HIGHEST);
+ d.addEvidence(EvidenceType.VERSION, PIPFILE, "version", identifiedVersion, Confidence.HIGHEST);
+ engine.addDependency(d);
}
}
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/PipfilelockAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/PipfilelockAnalyzer.java
new file mode 100644
index 00000000000..525cdcfb6fa
--- /dev/null
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/PipfilelockAnalyzer.java
@@ -0,0 +1,219 @@
+/*
+ * 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) 2023 The OWASP Foundation. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.analyzer;
+
+import org.apache.commons.io.FileUtils;
+import com.github.packageurl.MalformedPackageURLException;
+import com.github.packageurl.PackageURL;
+import com.github.packageurl.PackageURLBuilder;
+import java.io.BufferedInputStream;
+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.utils.FileFilterBuilder;
+import org.owasp.dependencycheck.utils.Settings;
+import org.owasp.dependencycheck.dependency.EvidenceType;
+import org.owasp.dependencycheck.exception.InitializationException;
+import org.owasp.dependencycheck.dependency.naming.GenericIdentifier;
+import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
+import org.owasp.dependencycheck.utils.Checksum;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.Set;
+import javax.annotation.concurrent.ThreadSafe;
+import javax.json.Json;
+import javax.json.JsonException;
+import javax.json.JsonObject;
+import javax.json.JsonReader;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Used to analyze dependencies defined in Pipfile.lock. This analyzer works in
+ * tandem with the `PipfileAnalyzer` - and both analyzers use the same key to
+ * enable/disable the analyzers. The PipfileAnalyzer will be skipped if the lock
+ * file exists, as the lock will provide more accurate version numbers.
+ *
+ * @author jeremy.long
+ */
+@Experimental
+@ThreadSafe
+public class PipfilelockAnalyzer extends AbstractFileTypeAnalyzer {
+
+ /**
+ * The logger.
+ */
+ private static final Logger LOGGER = LoggerFactory.getLogger(PipfilelockAnalyzer.class);
+ /**
+ * "Pipfile.lock" file.
+ */
+ private static final String LOCKFILE = "Pipfile.lock";
+
+ /**
+ * The identifiedPackage of the analyzer.
+ */
+ private static final String ANALYZER_NAME = "Pipfile.lock Analyzer";
+
+ /**
+ * The phase that this analyzer is intended to run in.
+ */
+ private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
+
+ /**
+ * The file filter used to determine which files this analyzer supports.
+ */
+ private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames(LOCKFILE).build();
+
+ /**
+ * Returns the FileFilter
+ *
+ * @return the FileFilter
+ */
+ @Override
+ protected FileFilter getFileFilter() {
+ return FILTER;
+ }
+
+ /**
+ * Returns the identifiedPackage of the analyzer.
+ *
+ * @return the identifiedPackage 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_PIPFILE_ENABLED;
+ }
+
+ @Override
+ protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
+ LOGGER.debug("Checking file {}", dependency.getActualFilePath());
+
+ engine.removeDependency(dependency);
+
+ final File dependencyFile = dependency.getActualFile();
+ if (!dependencyFile.isFile() || dependencyFile.length() == 0) {
+ return;
+ }
+
+ final File actualFile = dependency.getActualFile();
+ try (FileInputStream fin = new FileInputStream(actualFile);
+ InputStream in = new BufferedInputStream(fin);
+ JsonReader jsonReader = Json.createReader(in)) {
+
+ final JsonObject jsonLock = jsonReader.readObject();
+ final JsonObject develop = jsonLock.getJsonObject("develop");
+ final Set keys = develop.keySet();
+ for (String identifiedPackage : keys) {
+ final JsonObject dep = develop.getJsonObject(identifiedPackage);
+ final String selectedVersion = dep.getString("version", "").trim();
+ if (selectedVersion.startsWith("==") && selectedVersion.length() > 2) {
+ final String identifiedVersion = selectedVersion.substring(2).trim();
+ LOGGER.debug("package, version: {} {}", identifiedPackage, identifiedVersion);
+
+ final Dependency d = new Dependency(dependency.getActualFile(), true);
+ d.setName(identifiedPackage);
+ d.setVersion(identifiedVersion);
+ try {
+ final PackageURL purl = PackageURLBuilder.aPackageURL()
+ .withType("pypi")
+ .withName(identifiedPackage)
+ .withVersion(identifiedVersion)
+ .build();
+ d.addSoftwareIdentifier(new PurlIdentifier(purl, Confidence.HIGHEST));
+ } catch (MalformedPackageURLException ex) {
+ LOGGER.debug("Unable to build package url for pypi", ex);
+ d.addSoftwareIdentifier(new GenericIdentifier("pypi:" + identifiedPackage + "@" + identifiedVersion, Confidence.HIGH));
+ }
+ d.setPackagePath(String.format("%s:%s", identifiedPackage, identifiedVersion));
+ d.setEcosystem(PythonDistributionAnalyzer.DEPENDENCY_ECOSYSTEM);
+ final String filePath = String.format("%s:%s/%s", dependency.getFilePath(), identifiedPackage, identifiedVersion);
+ d.setFilePath(filePath);
+ d.setSha1sum(Checksum.getSHA1Checksum(filePath));
+ d.setSha256sum(Checksum.getSHA256Checksum(filePath));
+ d.setMd5sum(Checksum.getMD5Checksum(filePath));
+ d.addEvidence(EvidenceType.VENDOR, LOCKFILE, "vendor", identifiedPackage, Confidence.HIGHEST);
+ d.addEvidence(EvidenceType.PRODUCT, LOCKFILE, "product", identifiedPackage, Confidence.HIGHEST);
+ d.addEvidence(EvidenceType.VERSION, LOCKFILE, "version", identifiedVersion, Confidence.HIGHEST);
+ engine.addDependency(d);
+ } else {
+ LOGGER.debug("Skipping `{}`: Unknown version `{}` in `{}`", identifiedPackage, selectedVersion, dependency.getActualFilePath());
+ }
+ }
+ } catch (FileNotFoundException ex) {
+ throw new RuntimeException(ex);
+ } catch (IOException | JsonException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /**
+ * 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 {
+ try {
+ return FileUtils.readFileToString(actualFile, Charset.defaultCharset()).trim();
+ } catch (IOException e) {
+ throw new AnalysisException("Problem occurred while reading dependency file.", e);
+ }
+ }
+
+ /**
+ * Initializes the file type analyzer.
+ *
+ * @param engine a reference to the dependency-check engine
+ * @throws InitializationException thrown if there is an exception during
+ * initialization
+ */
+ @Override
+ protected void prepareFileTypeAnalyzer(Engine engine) throws InitializationException {
+ // No initialization needed.
+ }
+}
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 79e8c6b94f9..c40992ece46 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
@@ -21,6 +21,7 @@ org.owasp.dependencycheck.analyzer.PythonDistributionAnalyzer
org.owasp.dependencycheck.analyzer.PythonPackageAnalyzer
org.owasp.dependencycheck.analyzer.PipAnalyzer
org.owasp.dependencycheck.analyzer.PipfileAnalyzer
+org.owasp.dependencycheck.analyzer.PipfilelockAnalyzer
org.owasp.dependencycheck.analyzer.PoetryAnalyzer
org.owasp.dependencycheck.analyzer.AutoconfAnalyzer
org.owasp.dependencycheck.analyzer.OpenSSLAnalyzer
diff --git a/core/src/test/java/org/owasp/dependencycheck/analyzer/PipfilelockAnalyzerTest.java b/core/src/test/java/org/owasp/dependencycheck/analyzer/PipfilelockAnalyzerTest.java
new file mode 100644
index 00000000000..7410909dbfe
--- /dev/null
+++ b/core/src/test/java/org/owasp/dependencycheck/analyzer/PipfilelockAnalyzerTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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) 2023 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.analyzer;
+
+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.dependency.Dependency;
+
+import java.io.File;
+import org.apache.commons.lang3.ArrayUtils;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Unit tests for PipfilelockAnalyzerTest.
+ */
+public class PipfilelockAnalyzerTest extends BaseDBTestCase {
+
+ /**
+ * The analyzer to test.
+ */
+ private PipfilelockAnalyzer analyzer;
+
+ /**
+ * Correctly setup the analyzer for testing.
+ *
+ * @throws Exception thrown if there is a problem
+ */
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ analyzer = new PipfilelockAnalyzer();
+ 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 of getName method, of class PipAnalyzer.
+ */
+ @Test
+ public void testGetName() {
+ assertEquals("Pipfile.lock Analyzer", analyzer.getName());
+ }
+
+ /**
+ * Test of supportsExtension method, of class PipAnalyzer.
+ */
+ @Test
+ public void testSupportsFiles() {
+ assertFalse(analyzer.accept(new File("Pipfile")));
+ assertTrue(analyzer.accept(new File("Pipfile.lock")));
+ }
+
+ @Test
+ public void testAnalyzePackageLock() throws Exception {
+ try (Engine engine = new Engine(getSettings())) {
+ final Dependency result = new Dependency(BaseTest.getResourceAsFile(this, "pip/Pipfile.lock"));
+ engine.addDependency(result);
+ analyzer.analyze(result, engine);
+ assertFalse(ArrayUtils.contains(engine.getDependencies(), result));
+ assertEquals(76, engine.getDependencies().length);
+ boolean found = false;
+ for (Dependency d : engine.getDependencies()) {
+ if ("alabaster".equals(d.getName())) {
+ found = true;
+ assertEquals("0.7.12", d.getVersion());
+ assertThat(d.getDisplayFileName(), equalTo("alabaster:0.7.12"));
+ assertEquals(PythonDistributionAnalyzer.DEPENDENCY_ECOSYSTEM, d.getEcosystem());
+ break;
+ }
+ }
+ assertTrue("Expeced to find urllib3", found);
+ }
+ }
+}
diff --git a/core/src/test/resources/pip/Pipfile b/core/src/test/resources/pip/Pipfile
new file mode 100644
index 00000000000..78d413b2755
--- /dev/null
+++ b/core/src/test/resources/pip/Pipfile
@@ -0,0 +1,32 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[dev-packages]
+pipenv = {path = ".", editable = true, extras = ["tests", "dev"]}
+sphinx = "==4.*"
+sphinx-click = "==4.*"
+sphinxcontrib-spelling = "==7.*"
+click = "==8.0.3"
+pypiserver = "==1.*"
+stdeb = {version="*", markers="sys_platform == 'linux'"}
+zipp = {version = "==3.6.0", markers = "python_version < '3.10'"}
+pre-commit = "==2.*"
+atomicwrites = {version = "*", markers="sys_platform == 'win32'"}
+pytest-cov = "==3.*"
+typing-extensions = "==4.*"
+waitress = {version = "*", markers="sys_platform == 'win32'"}
+gunicorn = {version = "*", markers="sys_platform == 'linux'"}
+parse = "*"
+importlib-metadata = {version = "*", markers="python_version < '3.8'"}
+colorama= {version = "*", markers="sys_platform == 'win32'"}
+
+[packages]
+
+[scripts]
+tests = "bash ./run-tests.sh"
+test = "pytest -vvs"
+
+[pipenv]
+allow_prereleases = true
diff --git a/core/src/test/resources/pip/Pipfile.lock b/core/src/test/resources/pip/Pipfile.lock
new file mode 100644
index 00000000000..9e9aad580e9
--- /dev/null
+++ b/core/src/test/resources/pip/Pipfile.lock
@@ -0,0 +1,760 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "48857cc762ed1cb9fe4ec09aaf5d90931deb1e6875a09f7a09bf6fc5f438b402"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {},
+ "develop": {
+ "alabaster": {
+ "hashes": [
+ "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359",
+ "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"
+ ],
+ "version": "==0.7.12"
+ },
+ "arpeggio": {
+ "hashes": [
+ "sha256:448e332deb0e9ccd04046f1c6c14529d197f41bc2fdb3931e43fc209042fbdd3",
+ "sha256:d6b03839019bb8a68785f9292ee6a36b1954eb84b925b84a6b8a5e1e26d3ed3d"
+ ],
+ "version": "==2.0.0"
+ },
+ "atomicwrites": {
+ "hashes": [
+ "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"
+ ],
+ "markers": "sys_platform == 'win32'",
+ "version": "==1.4.1"
+ },
+ "attrs": {
+ "hashes": [
+ "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836",
+ "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==22.2.0"
+ },
+ "babel": {
+ "hashes": [
+ "sha256:1ad3eca1c885218f6dce2ab67291178944f810a10a9b5f3cb8382a5a232b64fe",
+ "sha256:5ef4b3226b0180dedded4229651c8b0e1a3a6a2837d45a073272f313e4cf97f6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.11.0"
+ },
+ "beautifulsoup4": {
+ "hashes": [
+ "sha256:58d5c3d29f5a36ffeb94f02f0d786cd53014cf9b3b3951d42e0080d8a9498d30",
+ "sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693"
+ ],
+ "markers": "python_full_version >= '3.6.0'",
+ "version": "==4.11.1"
+ },
+ "black": {
+ "hashes": [
+ "sha256:0b945a5a1e5a5321f884de0061d5a8585d947c9b608e37b6d26ceee4dfdf4b62",
+ "sha256:4db1d8027ce7ae53f0ccf02b0be0b8808fefb291d6cb1543420f4165d96d364c",
+ "sha256:5fb7641d442ede92538bc70fa0201f884753a7d0f62f26c722b7b00301b95902",
+ "sha256:63330069d8ec909cf4e2c4d43a7f00aeb03335430ef9fec6cd2328e6ebde8a77",
+ "sha256:793c9176beb2adf295f6b863d9a4dc953fe2ac359ca3da108d71d14cb2c09e52",
+ "sha256:85dede655442f5e246e7abd667fe07e14916897ba52f3640b5489bf11f7dbf67",
+ "sha256:88288a645402106b8eb9f50d7340ae741e16240bb01c2eed8466549153daa96e",
+ "sha256:88ec25a64063945b4591b6378bead544c5d3260de1c93ad96f3ad2d76ddd76fd",
+ "sha256:8dff6f0157e47fbbeada046fca144b6557d3be2fb2602d668881cd179f04a352",
+ "sha256:ca658b69260a18bf7aa0b0a6562dbbd304a737487d1318998aaca5a75901fd2c",
+ "sha256:ddbf9da228726d46f45c29024263e160d41030a415097254817d65127012d1a2",
+ "sha256:e88e4b633d64b9e7adc4a6b922f52bb204af9f90d7b1e3317e6490f2b598b1ea"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==23.1a1"
+ },
+ "bs4": {
+ "hashes": [
+ "sha256:36ecea1fd7cc5c0c6e4a1ff075df26d50da647b75376626cc186e2212886dd3a"
+ ],
+ "version": "==0.0.1"
+ },
+ "certifi": {
+ "hashes": [
+ "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3",
+ "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2022.12.7"
+ },
+ "cfgv": {
+ "hashes": [
+ "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426",
+ "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"
+ ],
+ "markers": "python_full_version >= '3.6.1'",
+ "version": "==3.3.1"
+ },
+ "charset-normalizer": {
+ "hashes": [
+ "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845",
+ "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"
+ ],
+ "markers": "python_full_version >= '3.6.0'",
+ "version": "==2.1.1"
+ },
+ "click": {
+ "hashes": [
+ "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3",
+ "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"
+ ],
+ "index": "pypi",
+ "version": "==8.0.3"
+ },
+ "click-default-group": {
+ "hashes": [
+ "sha256:d9560e8e8dfa44b3562fbc9425042a0fd6d21956fcc2db0077f63f34253ab904"
+ ],
+ "version": "==1.2.2"
+ },
+ "colorama": {
+ "hashes": [
+ "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44",
+ "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"
+ ],
+ "markers": "sys_platform == 'win32'",
+ "version": "==0.4.6"
+ },
+ "coverage": {
+ "extras": [
+ "toml"
+ ],
+ "hashes": [
+ "sha256:04691b8e832a900ed15f5bcccc2008fc2d1c8e7411251fd7d1422a84e1d72841",
+ "sha256:1a613d60be1a02c7a5184ea5c4227f48c08e0635608b9c17ae2b17efef8f2501",
+ "sha256:1d732b5dcafed67d81c5b5a0c404c31a61e13148946a3b910a340f72fdd1ec95",
+ "sha256:2b31f7f246dbff339b3b76ee81329e3eca5022ce270c831c65e841dbbb40115f",
+ "sha256:312fd77258bf1044ef4faa82091f2e88216e4b62dcf1a461d3e917144c8b09b7",
+ "sha256:321316a7b979892a13c148a9d37852b5a76f26717e4b911b606a649394629532",
+ "sha256:36c1a1b6d38ebf8a4335f65226ec36b5d6fd67743fdcbad5c52bdcd46c4f5842",
+ "sha256:38f281bb9bdd4269c451fed9451203512dadefd64676f14ed1e82c77eb5644fc",
+ "sha256:3a2d81c95d3b02638ee6ae647edc79769fd29bf5e9e5b6b0c29040579f33c260",
+ "sha256:3d40ad86a348c79c614e2b90566267dd6d45f2e6b4d2bfb794d78ea4a4b60b63",
+ "sha256:3d72e3d20b03e63bd27b1c4d6b754cd93eca82ecc5dd77b99262d5f64862ca35",
+ "sha256:3fbb59f84c8549113dcdce7c6d16c5731fe53651d0b46c0a25a5ebc7bb655869",
+ "sha256:405d8528a0ea07ca516d9007ecad4e1bd10e2eeef27411c6188d78c4e2dfcddc",
+ "sha256:420f10c852b9a489cf5a764534669a19f49732a0576c76d9489ebf287f81af6d",
+ "sha256:426895ac9f2938bec193aa998e7a77a3e65d3e46903f348e794b4192b9a5b61e",
+ "sha256:4438ba539bef21e288092b30ea2fc30e883d9af5b66ebeaf2fd7c25e2f074e39",
+ "sha256:46db409fc0c3ee5c859b84c7de9cb507166287d588390889fdf06a1afe452e16",
+ "sha256:483e120ea324c7fced6126bb9bf0535c71e9233d29cbc7e2fc4560311a5f8a32",
+ "sha256:4d7be755d7544dac2b9814e98366a065d15a16e13847eb1f5473bb714483391e",
+ "sha256:4e97b21482aa5c21e049e4755c95955ad71fb54c9488969e2f17cf30922aa5f6",
+ "sha256:5f44ba7c07e0aa4a7a2723b426c254e952da82a33d65b4a52afae4bef74a4203",
+ "sha256:62e5b942378d5f0b87caace567a70dc634ddd4d219a236fa221dc97d2fc412c8",
+ "sha256:7c669be1b01e4b2bf23aa49e987d9bedde0234a7da374a9b77ca5416d7c57002",
+ "sha256:7d47d666e17e57ef65fefc87229fde262bd5c9039ae8424bc53aa2d8f07dc178",
+ "sha256:7e184aa18f921b612ea08666c25dd92a71241c8ed40917f2824219c92289b8c7",
+ "sha256:80583c536e7e010e301002088919d4ea90566d1789ee02551574fdf3faa275ae",
+ "sha256:8217f73faf08623acb25fb2affd5d20cbcd8185213db308e46a37e6fd6a56a49",
+ "sha256:87d95eea58fb71f69b4f1c761099a19e0e9cb27d45dc1cc7042523128ee56337",
+ "sha256:8bd466135fb07f693dbdd999a5569ffbc0590e9c64df859243162f0ebee950c8",
+ "sha256:8e133ca2f8141b415ff396ba789bdeffdea8ff9a5c7fc9996ccf591d7d40ee93",
+ "sha256:8e6c0ca447b557a32642f22d0987be37950eda51c4f19fc788cebc99426284b6",
+ "sha256:9de96025ce25b9f4e744fbe558a003e673004af255da9b1f6ec243720ac5deeb",
+ "sha256:a27a8dca0dc6f0944ed9fd83c556d862e227a5cd4220e62af5d4c750389938f0",
+ "sha256:a2d4f68e4fa286fb6b00d58a1e87c79840e289d3f6e5dcb912ad7b0fbd9629fb",
+ "sha256:a6e1c77ff6f10eab496fbbcdaa7dfae84968928a0aadc43ce3c3453cec29bd79",
+ "sha256:a7b018811a0e1d3869d8d0600849953acd355a3a29c6bee0fbd24d7772bcc0a2",
+ "sha256:a99b2f2dd1236e8d9dc35974a3dc298a408cdfd512b0bb2451798cff1ce63408",
+ "sha256:ac1033942851bf01f28c76318155ea92d6648aecb924cab81fa23781d095e9ab",
+ "sha256:b6936cd38757dd323fefc157823e46436610328f0feb1419a412316f24b77f36",
+ "sha256:b6eab230b18458707b5c501548e997e42934b1c189fb4d1b78bf5aacc1c6a137",
+ "sha256:bcb57d175ff0cb4ff97fc547c74c1cb8d4c9612003f6d267ee78dad8f23d8b30",
+ "sha256:c1f02d016b9b6b5ad21949a21646714bfa7b32d6041a30f97674f05d6d6996e3",
+ "sha256:c40aaf7930680e0e5f3bd6d3d3dc97a7897f53bdce925545c4b241e0c5c3ca6a",
+ "sha256:c5e1874c601128cf54c1d4b471e915658a334fbc56d7b3c324ddc7511597ea82",
+ "sha256:c8805673b1953313adfc487d5323b4c87864e77057944a0888c98dd2f7a6052f",
+ "sha256:da458bdc9b0bcd9b8ca85bc73148631b18cc8ba03c47f29f4c017809990351aa",
+ "sha256:dcb708ab06f3f4dfc99e9f84821c9120e5f12113b90fad132311a2cb97525379",
+ "sha256:dfafc350f43fd7dc67df18c940c3b7ed208ebb797abe9fb3047f0c65be8e4c0f",
+ "sha256:e8931af864bd599c6af626575a02103ae626f57b34e3af5537d40b040d33d2ad",
+ "sha256:efa9d943189321f67f71070c309aa6f6130fa1ec35c9dfd0da0ed238938ce573",
+ "sha256:fd22ee7bff4b5c37bb6385efee1c501b75e29ca40286f037cb91c2182d1348ce"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==7.0.2"
+ },
+ "distlib": {
+ "hashes": [
+ "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46",
+ "sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e"
+ ],
+ "version": "==0.3.6"
+ },
+ "docutils": {
+ "hashes": [
+ "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125",
+ "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
+ "version": "==0.17.1"
+ },
+ "exceptiongroup": {
+ "hashes": [
+ "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e",
+ "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"
+ ],
+ "markers": "python_version < '3.11'",
+ "version": "==1.1.0"
+ },
+ "execnet": {
+ "hashes": [
+ "sha256:8f694f3ba9cc92cab508b152dcfe322153975c29bda272e2fd7f3f00f36e47c5",
+ "sha256:a295f7cc774947aac58dde7fdc85f4aa00c42adf5d8f5468fc630c1acf30a142"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
+ "version": "==1.9.0"
+ },
+ "filelock": {
+ "hashes": [
+ "sha256:7b319f24340b51f55a2bf7a12ac0755a9b03e718311dac567a0f4f7fabd2f5de",
+ "sha256:f58d535af89bb9ad5cd4df046f741f8553a418c01a7856bf0d173bbc9f6bd16d"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==3.9.0"
+ },
+ "flake8": {
+ "hashes": [
+ "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b",
+ "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
+ "version": "==3.9.2"
+ },
+ "flaky": {
+ "hashes": [
+ "sha256:3ad100780721a1911f57a165809b7ea265a7863305acb66708220820caf8aa0d",
+ "sha256:d6eda73cab5ae7364504b7c44670f70abed9e75f77dd116352f662817592ec9c"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==3.7.0"
+ },
+ "gunicorn": {
+ "hashes": [
+ "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e",
+ "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"
+ ],
+ "index": "pypi",
+ "markers": "sys_platform == 'linux'",
+ "version": "==20.1.0"
+ },
+ "identify": {
+ "hashes": [
+ "sha256:14b7076b29c99b1b0b8b08e96d448c7b877a9b07683cd8cfda2ea06af85ffa1c",
+ "sha256:e7db36b772b188099616aaf2accbee122949d1c6a1bac4f38196720d6f9f06db"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==2.5.11"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4",
+ "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.4"
+ },
+ "imagesize": {
+ "hashes": [
+ "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b",
+ "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.4.1"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:7efb448ec9a5e313a57655d35aa54cd3e01b7e1fbcf72dce1bf06119420f5bad",
+ "sha256:e354bedeb60efa6affdcc8ae121b73544a7aa74156d047311948f6d711cd378d"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==6.0.0"
+ },
+ "incremental": {
+ "hashes": [
+ "sha256:912feeb5e0f7e0188e6f42241d2f450002e11bbc0937c65865045854c24c0bd0",
+ "sha256:b864a1f30885ee72c5ac2835a761b8fe8aa9c28b9395cacf27286602688d3e51"
+ ],
+ "version": "==22.10.0"
+ },
+ "iniconfig": {
+ "hashes": [
+ "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3",
+ "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"
+ ],
+ "version": "==1.1.1"
+ },
+ "invoke": {
+ "hashes": [
+ "sha256:41b428342d466a82135d5ab37119685a989713742be46e42a3a399d685579314",
+ "sha256:d9694a865764dd3fd91f25f7e9a97fb41666e822bbb00e670091e3f43933574d"
+ ],
+ "version": "==1.7.3"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852",
+ "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==3.1.2"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003",
+ "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88",
+ "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5",
+ "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7",
+ "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a",
+ "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603",
+ "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1",
+ "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135",
+ "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247",
+ "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6",
+ "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601",
+ "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77",
+ "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02",
+ "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e",
+ "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63",
+ "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f",
+ "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980",
+ "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b",
+ "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812",
+ "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff",
+ "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96",
+ "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1",
+ "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925",
+ "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a",
+ "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6",
+ "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e",
+ "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f",
+ "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4",
+ "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f",
+ "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3",
+ "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c",
+ "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a",
+ "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417",
+ "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a",
+ "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a",
+ "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37",
+ "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452",
+ "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933",
+ "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a",
+ "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==2.1.1"
+ },
+ "mccabe": {
+ "hashes": [
+ "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
+ "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
+ ],
+ "version": "==0.6.1"
+ },
+ "mock": {
+ "hashes": [
+ "sha256:335ef0bf9bcd27505c0c1720d4eac2783f18d07d6f45ac49542b57885a1996dd",
+ "sha256:fd552787228eb2ab8352f270470fa93c9ad8b9cbc565c5558ee3faed8edb3853"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==5.0.0"
+ },
+ "mypy-extensions": {
+ "hashes": [
+ "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d",
+ "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"
+ ],
+ "version": "==0.4.3"
+ },
+ "nodeenv": {
+ "hashes": [
+ "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e",
+ "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'",
+ "version": "==1.7.0"
+ },
+ "packaging": {
+ "hashes": [
+ "sha256:2198ec20bd4c017b8f9717e00f0c8714076fc2fd93816750ab48e2c41de2cfd3",
+ "sha256:957e2148ba0e1a3b282772e791ef1d8083648bc131c8ab0c1feba110ce1146c3"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==22.0"
+ },
+ "parse": {
+ "hashes": [
+ "sha256:9ff82852bcb65d139813e2a5197627a94966245c897796760a3a2a8eb66f020b"
+ ],
+ "index": "pypi",
+ "version": "==1.19.0"
+ },
+ "parver": {
+ "hashes": [
+ "sha256:c66d3347a4858643875ef959d8ba7a269d5964bfb690b0dd998b8f39da930be2",
+ "sha256:d4a3dbb93c53373ee9a0ba055e4858c44169b204b912e49d003ead95db9a9bca"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==0.4"
+ },
+ "pathspec": {
+ "hashes": [
+ "sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6",
+ "sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==0.10.3"
+ },
+ "pipenv": {
+ "editable": true,
+ "extras": [
+ "dev",
+ "tests"
+ ],
+ "path": "."
+ },
+ "platformdirs": {
+ "hashes": [
+ "sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490",
+ "sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==2.6.2"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159",
+ "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==1.0.0"
+ },
+ "pre-commit": {
+ "hashes": [
+ "sha256:31ef31af7e474a8d8995027fefdfcf509b5c913ff31f2015b4ec4beb26a6f658",
+ "sha256:e2f91727039fc39a92f58a588a25b87f936de6567eed4f0e673e0507edc75bad"
+ ],
+ "index": "pypi",
+ "version": "==2.21.0"
+ },
+ "pycodestyle": {
+ "hashes": [
+ "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068",
+ "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.7.0"
+ },
+ "pyenchant": {
+ "hashes": [
+ "sha256:1cf830c6614362a78aab78d50eaf7c6c93831369c52e1bb64ffae1df0341e637",
+ "sha256:5a636832987eaf26efe971968f4d1b78e81f62bca2bde0a9da210c7de43c3bce",
+ "sha256:5facc821ece957208a81423af7d6ec7810dad29697cb0d77aae81e4e11c8e5a6",
+ "sha256:6153f521852e23a5add923dbacfbf4bebbb8d70c4e4bad609a8e0f9faeb915d1"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2.2"
+ },
+ "pyflakes": {
+ "hashes": [
+ "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3",
+ "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.3.1"
+ },
+ "pygments": {
+ "hashes": [
+ "sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297",
+ "sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.14.0"
+ },
+ "pypiserver": {
+ "hashes": [
+ "sha256:24804a717ccd4611aa805621eead821f9d389163f6020a500c7e05f191884ba2",
+ "sha256:bea067627793ebcab6574549b7a7e9099cceeb5b902a73f4df09734c11fc3cdf"
+ ],
+ "index": "pypi",
+ "version": "==1.5.1"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71",
+ "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==7.2.0"
+ },
+ "pytest-cov": {
+ "hashes": [
+ "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6",
+ "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"
+ ],
+ "index": "pypi",
+ "version": "==3.0.0"
+ },
+ "pytest-timeout": {
+ "hashes": [
+ "sha256:c07ca07404c612f8abbe22294b23c368e2e5104b521c1790195561f37e1ac3d9",
+ "sha256:f6f50101443ce70ad325ceb4473c4255e9d74e3c7cd0ef827309dfa4c0d975c6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pytest-xdist": {
+ "hashes": [
+ "sha256:40fdb8f3544921c5dfcd486ac080ce22870e71d82ced6d2e78fa97c2addd480c",
+ "sha256:70a76f191d8a1d2d6be69fc440cdf85f3e4c03c08b520fd5dc5d338d6cf07d89"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==3.1.0"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:7ccfae7b4b2c067464a6733c6261673fdb8fd1be905460396b97a073e9fa683a",
+ "sha256:93007def75ae22f7cd991c84e02d434876818661f8df9ad5df9e950ff4e52cfd"
+ ],
+ "version": "==2022.7"
+ },
+ "pyyaml": {
+ "hashes": [
+ "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf",
+ "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293",
+ "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b",
+ "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57",
+ "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b",
+ "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4",
+ "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07",
+ "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba",
+ "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9",
+ "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287",
+ "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513",
+ "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0",
+ "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782",
+ "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0",
+ "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92",
+ "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f",
+ "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2",
+ "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc",
+ "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1",
+ "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c",
+ "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86",
+ "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4",
+ "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c",
+ "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34",
+ "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b",
+ "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d",
+ "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c",
+ "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb",
+ "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7",
+ "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737",
+ "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3",
+ "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d",
+ "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358",
+ "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53",
+ "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78",
+ "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803",
+ "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a",
+ "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f",
+ "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174",
+ "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==6.0"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983",
+ "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"
+ ],
+ "markers": "python_version >= '3.7' and python_version < '4'",
+ "version": "==2.28.1"
+ },
+ "setuptools": {
+ "hashes": [
+ "sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54",
+ "sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==65.6.3"
+ },
+ "snowballstemmer": {
+ "hashes": [
+ "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1",
+ "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"
+ ],
+ "version": "==2.2.0"
+ },
+ "soupsieve": {
+ "hashes": [
+ "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759",
+ "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.3.2.post1"
+ },
+ "sphinx": {
+ "hashes": [
+ "sha256:7bf8ca9637a4ee15af412d1a1d9689fec70523a68ca9bb9127c2f3eeb344e2e6",
+ "sha256:ebf612653238bcc8f4359627a9b7ce44ede6fdd75d9d30f68255c7383d3a6226"
+ ],
+ "index": "pypi",
+ "version": "==4.5.0"
+ },
+ "sphinx-click": {
+ "hashes": [
+ "sha256:2821c10a68fc9ee6ce7c92fad26540d8d8c8f45e6d7258f0e4fb7529ae8fab49",
+ "sha256:cc67692bd28f482c7f01531c61b64e9d2f069bfcf3d24cbbb51d4a84a749fa48"
+ ],
+ "index": "pypi",
+ "version": "==4.4.0"
+ },
+ "sphinxcontrib-applehelp": {
+ "hashes": [
+ "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a",
+ "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==1.0.2"
+ },
+ "sphinxcontrib-devhelp": {
+ "hashes": [
+ "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e",
+ "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==1.0.2"
+ },
+ "sphinxcontrib-htmlhelp": {
+ "hashes": [
+ "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07",
+ "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.0"
+ },
+ "sphinxcontrib-jsmath": {
+ "hashes": [
+ "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178",
+ "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==1.0.1"
+ },
+ "sphinxcontrib-qthelp": {
+ "hashes": [
+ "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72",
+ "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==1.0.3"
+ },
+ "sphinxcontrib-serializinghtml": {
+ "hashes": [
+ "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd",
+ "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==1.1.5"
+ },
+ "sphinxcontrib-spelling": {
+ "hashes": [
+ "sha256:56561c3f6a155b0946914e4de988729859315729dc181b5e4dc8a68fe78de35a",
+ "sha256:95a0defef8ffec6526f9e83b20cc24b08c9179298729d87976891840e3aa3064"
+ ],
+ "index": "pypi",
+ "version": "==7.7.0"
+ },
+ "stdeb": {
+ "hashes": [
+ "sha256:08c22c9c03b28a140fe3ec5064b53a5288279f22e596ca06b0be698d50c93cf2"
+ ],
+ "index": "pypi",
+ "markers": "sys_platform == 'linux'",
+ "version": "==0.10.0"
+ },
+ "tomli": {
+ "hashes": [
+ "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
+ "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"
+ ],
+ "markers": "python_version < '3.11'",
+ "version": "==2.0.1"
+ },
+ "towncrier": {
+ "hashes": [
+ "sha256:9767a899a4d6856950f3598acd9e8f08da2663c49fdcda5ea0f9e6ba2afc8eea",
+ "sha256:9c49d7e75f646a9aea02ae904c0bc1639c8fd14a01292d2b123b8d307564034d"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==22.12.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa",
+ "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"
+ ],
+ "index": "pypi",
+ "version": "==4.4.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc",
+ "sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
+ "version": "==1.26.13"
+ },
+ "virtualenv": {
+ "hashes": [
+ "sha256:ce3b1684d6e1a20a3e5ed36795a97dfc6af29bc3970ca8dab93e11ac6094b3c4",
+ "sha256:f8b927684efc6f1cc206c9db297a570ab9ad0e51c16fa9e45487d36d1905c058"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==20.17.1"
+ },
+ "virtualenv-clone": {
+ "hashes": [
+ "sha256:418ee935c36152f8f153c79824bb93eaf6f0f7984bae31d3f48f350b9183501a",
+ "sha256:44d5263bceed0bac3e1424d64f798095233b64def1c5689afa43dc3223caf5b0"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==0.5.7"
+ },
+ "waitress": {
+ "hashes": [
+ "sha256:7500c9625927c8ec60f54377d590f67b30c8e70ef4b8894214ac6e4cad233d2a",
+ "sha256:780a4082c5fbc0fde6a2fcfe5e26e6efc1e8f425730863c04085769781f51eba"
+ ],
+ "markers": "sys_platform == 'win32'",
+ "version": "==2.1.2"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832",
+ "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc"
+ ],
+ "markers": "python_version < '3.10'",
+ "version": "==3.6.0"
+ }
+ }
+}
diff --git a/maven/pom.xml b/maven/pom.xml
index e5ce1333b45..746ded454cd 100644
--- a/maven/pom.xml
+++ b/maven/pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
org.owasp
dependency-check-parent
- 8.0.3-SNAPSHOT
+ 8.1.0-SNAPSHOT
dependency-check-maven
maven-plugin
diff --git a/pom.xml b/pom.xml
index 8243c71987d..7977a9e6f50 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long
org.owasp
dependency-check-parent
- 8.0.3-SNAPSHOT
+ 8.1.0-SNAPSHOT
pom
diff --git a/utils/pom.xml b/utils/pom.xml
index c8ce4842d30..7d48bb73725 100644
--- a/utils/pom.xml
+++ b/utils/pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved.
org.owasp
dependency-check-parent
- 8.0.3-SNAPSHOT
+ 8.1.0-SNAPSHOT
dependency-check-utils