diff --git a/core/pom.xml b/core/pom.xml
index eb3f6b21b64..fe5a4e7a4e7 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -213,8 +213,8 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
test
- commons-collections
- commons-collections
+ org.apache.commons
+ commons-collections4
org.apache.commons
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractNpmAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractNpmAnalyzer.java
index 27f90409b69..7065429a9ea 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractNpmAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractNpmAnalyzer.java
@@ -21,6 +21,8 @@
import com.github.packageurl.PackageURL;
import com.github.packageurl.PackageURL.StandardTypes;
import com.github.packageurl.PackageURLBuilder;
+import com.vdurmont.semver4j.Semver;
+import com.vdurmont.semver4j.Semver.SemverType;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.data.nodeaudit.Advisory;
import org.owasp.dependencycheck.data.nodeaudit.NodeAuditSearch;
@@ -38,6 +40,7 @@
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.annotation.concurrent.ThreadSafe;
@@ -48,6 +51,7 @@
import javax.json.JsonString;
import javax.json.JsonValue;
import javax.json.JsonValue.ValueType;
+import org.apache.commons.collections4.MultiValuedMap;
import org.apache.commons.lang3.StringUtils;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.analyzer.exception.UnexpectedAnalysisException;
@@ -440,7 +444,7 @@ protected void prepareFileTypeAnalyzer(Engine engine) throws InitializationExcep
* @throws CpeValidationException thrown when a CPE cannot be created
*/
protected void processResults(final List advisories, Engine engine,
- Dependency dependency, Map dependencyMap)
+ Dependency dependency, MultiValuedMap dependencyMap)
throws CpeValidationException {
for (Advisory advisory : advisories) {
//Create a new vulnerability out of the advisory returned by nsp.
@@ -464,9 +468,8 @@ protected void processResults(final List advisories, Engine engine,
String version = advisory.getVersion();
if (version == null && dependencyMap.containsKey(advisory.getModuleName())) {
- version = dependencyMap.get(advisory.getModuleName());
+ version = determineVersionFromMap(advisory.getVulnerableVersions(), dependencyMap.get(advisory.getModuleName()));
}
-
final Dependency existing = findDependency(engine, advisory.getModuleName(), version);
if (existing == null) {
final Dependency nodeModule = createDependency(dependency, advisory.getModuleName(), version, "transitive");
@@ -509,4 +512,17 @@ protected void replaceOrAddVulnerability(Dependency dependency, Vulnerability vu
protected NodeAuditSearch getSearcher() {
return searcher;
}
+
+ public String determineVersionFromMap(String versionRange, Collection availableVersions) {
+ if (availableVersions.size()==1) {
+ return availableVersions.iterator().next();
+ }
+ for (String v : availableVersions){
+ Semver version = new Semver(v, SemverType.NPM);
+ if (version.satisfies(versionRange)) {
+ return v;
+ }
+ }
+ return availableVersions.iterator().next();
+ }
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/NodeAuditAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/NodeAuditAnalyzer.java
index 90c7d139abe..ee33b8f3d64 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/NodeAuditAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/NodeAuditAnalyzer.java
@@ -30,15 +30,15 @@
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import javax.annotation.concurrent.ThreadSafe;
import javax.json.Json;
import javax.json.JsonException;
import javax.json.JsonObject;
import javax.json.JsonReader;
+import org.apache.commons.collections4.MultiValuedMap;
+import org.apache.commons.collections4.multimap.HashSetValuedHashMap;
import org.owasp.dependencycheck.analyzer.exception.SearchException;
import org.owasp.dependencycheck.analyzer.exception.UnexpectedAnalysisException;
import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
@@ -140,7 +140,8 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
}
final File packageJson = new File(packageLock.getParentFile(), "package.json");
final List advisories;
- final Map dependencyMap = new HashMap<>();
+ final MultiValuedMap dependencyMap = new HashSetValuedHashMap<>();
+ //final Map dependencyMap = new HashMap<>();
if (packageJson.isFile()) {
advisories = analyzePackage(packageLock, packageJson, dependency, dependencyMap);
} else {
@@ -170,7 +171,7 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
* submitting the npm audit API payload
*/
private List analyzePackage(final File lockFile, final File packageFile,
- Dependency dependency, Map dependencyMap)
+ Dependency dependency, MultiValuedMap dependencyMap)
throws AnalysisException {
try {
final JsonReader packageReader = Json.createReader(FileUtils.openInputStream(packageFile));
@@ -227,7 +228,7 @@ private List analyzePackage(final File lockFile, final File packageFil
* @throws AnalysisException thrown when there is an error creating or
* submitting the npm audit API payload
*/
- private List legacyAnalysis(final File file, Dependency dependency, Map dependencyMap)
+ private List legacyAnalysis(final File file, Dependency dependency, MultiValuedMap dependencyMap)
throws AnalysisException {
try (JsonReader jsonReader = Json.createReader(FileUtils.openInputStream(file))) {
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/PnpmAuditAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/PnpmAuditAnalyzer.java
index 27b652d0904..712f8df116a 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/PnpmAuditAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/PnpmAuditAnalyzer.java
@@ -43,9 +43,9 @@
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
+import org.apache.commons.collections4.MultiValuedMap;
+import org.apache.commons.collections4.multimap.HashSetValuedHashMap;
@ThreadSafe
public class PnpmAuditAnalyzer extends AbstractNpmAnalyzer {
@@ -89,7 +89,7 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
return;
}
final List advisories;
- final Map dependencyMap = new HashMap<>();
+ final MultiValuedMap dependencyMap = new HashSetValuedHashMap<>();
advisories = analyzePackage(packageLock, dependency);
try {
processResults(advisories, engine, dependency, dependencyMap);
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/YarnAuditAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/YarnAuditAnalyzer.java
index 85ddac2be76..1ebf482cec1 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/YarnAuditAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/YarnAuditAnalyzer.java
@@ -23,15 +23,15 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import javax.annotation.concurrent.ThreadSafe;
import javax.json.Json;
import javax.json.JsonException;
import javax.json.JsonObject;
import javax.json.JsonReader;
+import org.apache.commons.collections4.MultiValuedMap;
+import org.apache.commons.collections4.multimap.HashSetValuedHashMap;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
@@ -102,7 +102,7 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
}
final File packageJson = new File(packageLock.getParentFile(), "package.json");
final List advisories;
- final Map dependencyMap = new HashMap<>();
+ final MultiValuedMap dependencyMap = new HashSetValuedHashMap<>();
advisories = analyzePackage(packageLock, packageJson, dependency, dependencyMap);
try {
processResults(advisories, engine, dependency, dependencyMap);
@@ -276,7 +276,7 @@ private JsonObject fetchYarnAuditJson(Dependency dependency, boolean skipDevDepe
* submitting the npm audit API payload
*/
private List analyzePackage(final File lockFile, final File packageFile,
- Dependency dependency, Map dependencyMap)
+ Dependency dependency, MultiValuedMap dependencyMap)
throws AnalysisException {
try {
final Boolean skipDevDependencies = getSettings().getBoolean(Settings.KEYS.ANALYZER_NODE_AUDIT_SKIPDEV, false);
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/NpmPayloadBuilder.java b/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/NpmPayloadBuilder.java
index 7bc7ca90dec..eb12e5502a9 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/NpmPayloadBuilder.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/NpmPayloadBuilder.java
@@ -17,6 +17,7 @@
*/
package org.owasp.dependencycheck.data.nodeaudit;
+import com.esotericsoftware.minlog.Log;
import org.owasp.dependencycheck.analyzer.NodePackageAnalyzer;
import java.util.Map;
@@ -28,6 +29,7 @@
import javax.json.JsonString;
import javax.json.JsonValue;
import javax.annotation.concurrent.ThreadSafe;
+import org.apache.commons.collections4.MultiValuedMap;
/**
* Class used to create the payload to submit to the NPM Audit API service.
@@ -56,7 +58,7 @@ private NpmPayloadBuilder() {
* @return the npm audit API payload
*/
public static JsonObject build(JsonObject lockJson, JsonObject packageJson,
- Map dependencyMap, boolean skipDevDependencies) {
+ MultiValuedMap dependencyMap, boolean skipDevDependencies) {
final JsonObjectBuilder payloadBuilder = Json.createObjectBuilder();
addProjectInfo(packageJson, payloadBuilder);
@@ -132,7 +134,7 @@ public static JsonObject build(JsonObject lockJson, JsonObject packageJson,
* populated while building the payload
* @return the JSON payload for NPN Audit
*/
- public static JsonObject build(JsonObject packageJson, Map dependencyMap) {
+ public static JsonObject build(JsonObject packageJson, MultiValuedMap dependencyMap) {
final JsonObjectBuilder payloadBuilder = Json.createObjectBuilder();
addProjectInfo(packageJson, payloadBuilder);
@@ -215,7 +217,7 @@ private static void addConstantElements(final JsonObjectBuilder payloadBuilder)
* @param dependencyMap the collection of child dependencies
* @return the dependencies structure needed for the npm audit API payload
*/
- private static JsonObject buildDependencies(JsonObject dep, Map dependencyMap) {
+ private static JsonObject buildDependencies(JsonObject dep, MultiValuedMap dependencyMap) {
final JsonObjectBuilder depBuilder = Json.createObjectBuilder();
depBuilder.add("version", dep.getString("version"));
diff --git a/core/src/test/java/org/owasp/dependencycheck/analyzer/AbstractNpmAnalyzerIT.java b/core/src/test/java/org/owasp/dependencycheck/analyzer/AbstractNpmAnalyzerIT.java
new file mode 100644
index 00000000000..93f42c26cca
--- /dev/null
+++ b/core/src/test/java/org/owasp/dependencycheck/analyzer/AbstractNpmAnalyzerIT.java
@@ -0,0 +1,98 @@
+/*
+ * 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) 2021 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.analyzer;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import org.apache.commons.collections4.MultiValuedMap;
+import org.apache.commons.collections4.multimap.HashSetValuedHashMap;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import org.owasp.dependencycheck.Engine;
+import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
+import org.owasp.dependencycheck.data.nodeaudit.Advisory;
+import org.owasp.dependencycheck.data.nodeaudit.NodeAuditSearch;
+import org.owasp.dependencycheck.dependency.Dependency;
+import org.owasp.dependencycheck.dependency.Vulnerability;
+
+/**
+ *
+ * @author jeremy long
+ */
+public class AbstractNpmAnalyzerIT {
+
+
+ /**
+ * Test of determineVersionFromMap method, of class AbstractNpmAnalyzer.
+ */
+ @Test
+ public void testDetermineVersionFromMap() {
+ String versionRange = ">2.1.1 <5.0.1";
+ Collection availableVersions = new ArrayList<>();
+ availableVersions.add("2.0.2");
+ availableVersions.add("5.0.2");
+ availableVersions.add("10.1.0");
+ availableVersions.add("8.1.0");
+ availableVersions.add("5.1.0");
+ availableVersions.add("7.1.0");
+ availableVersions.add("3.0.0");
+ availableVersions.add("2.0.0");
+ AbstractNpmAnalyzer instance = new AbstractNpmAnalyzerImpl();
+ String expResult = "3.0.0";
+ String result = instance.determineVersionFromMap(versionRange, availableVersions);
+ assertEquals(expResult, result);
+ }
+
+ public class AbstractNpmAnalyzerImpl extends AbstractNpmAnalyzer {
+
+ @Override
+ protected FileFilter getFileFilter() {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ protected String getAnalyzerEnabledSettingKey() {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public String getName() {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public AnalysisPhase getAnalysisPhase() {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+ }
+
+}
diff --git a/core/src/test/java/org/owasp/dependencycheck/data/nodeaudit/NpmPayloadBuilderTest.java b/core/src/test/java/org/owasp/dependencycheck/data/nodeaudit/NpmPayloadBuilderTest.java
index d8a7b166d55..75e159ab2b8 100644
--- a/core/src/test/java/org/owasp/dependencycheck/data/nodeaudit/NpmPayloadBuilderTest.java
+++ b/core/src/test/java/org/owasp/dependencycheck/data/nodeaudit/NpmPayloadBuilderTest.java
@@ -28,6 +28,8 @@
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonReader;
+import org.apache.commons.collections4.MultiValuedMap;
+import org.apache.commons.collections4.multimap.HashSetValuedHashMap;
import org.owasp.dependencycheck.BaseTest;
@@ -53,7 +55,7 @@ public void testSanitizer() {
);
JsonObject packageJson = builder.build();
- Map dependencyMap = new HashMap<>();
+ final MultiValuedMap dependencyMap = new HashSetValuedHashMap<>();
JsonObject sanitized = NpmPayloadBuilder.build(packageJson, dependencyMap);
Assert.assertTrue(sanitized.containsKey("name"));
@@ -98,7 +100,7 @@ public void testSkippedDependencies() {
);
JsonObject packageJson = builder.build();
- Map dependencyMap = new HashMap<>();
+ final MultiValuedMap dependencyMap = new HashSetValuedHashMap<>();
JsonObject sanitized = NpmPayloadBuilder.build(packageJson, dependencyMap);
Assert.assertTrue(sanitized.containsKey("name"));
@@ -121,7 +123,7 @@ public void testSkippedDependencies() {
@Test
public void testSanitizePackage() {
InputStream in = BaseTest.getResourceAsStream(this, "nodeaudit/package-lock.json");
- Map dependencyMap = new HashMap<>();
+ final MultiValuedMap dependencyMap = new HashSetValuedHashMap<>();
try (JsonReader jsonReader = Json.createReader(in)) {
JsonObject packageJson = jsonReader.readObject();
JsonObject sanitized = NpmPayloadBuilder.build(packageJson, dependencyMap);
@@ -144,7 +146,7 @@ public void testSanitizePackage() {
public void testPayloadWithLockAndPackage() {
InputStream lock = BaseTest.getResourceAsStream(this, "nodeaudit/package-lock.json");
InputStream json = BaseTest.getResourceAsStream(this, "nodeaudit/package.json");
- Map dependencyMap = new HashMap<>();
+ final MultiValuedMap dependencyMap = new HashSetValuedHashMap<>();
try (JsonReader jsonReader = Json.createReader(json); JsonReader lockReader = Json.createReader(lock)) {
JsonObject packageJson = jsonReader.readObject();
JsonObject lockJson = lockReader.readObject();
@@ -162,8 +164,6 @@ public void testPayloadWithLockAndPackage() {
Assert.assertFalse(sanitized.containsKey("lockfileVersion"));
Assert.assertFalse(sanitized.containsKey("random"));
-
-
Assert.assertTrue(sanitized.containsKey("name"));
Assert.assertTrue(sanitized.containsKey("version"));
Assert.assertTrue(sanitized.containsKey("dependencies"));
diff --git a/pom.xml b/pom.xml
index cf7bc450acc..47ee8f455e4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1167,9 +1167,9 @@ Copyright (c) 2012 - Jeremy Long
${maven-reporting-api.version}
- commons-collections
- commons-collections
- ${commons-collections.version}
+ org.apache.commons
+ commons-collections4
+ 4.4
org.apache.velocity