Skip to content

Commit

Permalink
feat: Add CVSS V3 results from NPM Audit results
Browse files Browse the repository at this point in the history
Fixes issue #5552
  • Loading branch information
aikebah committed Mar 16, 2023
1 parent d1330dd commit 7187a0d
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,7 @@ protected void processResults(final List<Advisory> advisories, Engine engine,
vuln.setDescription(advisory.getOverview());
vuln.setName(String.valueOf(advisory.getGhsaId()));
vuln.setUnscoredSeverity(advisory.getSeverity());
vuln.setCvssV3(advisory.getCvssV3());
vuln.setSource(Vulnerability.Source.NPM);
for (String cwe : advisory.getCwes()) {
vuln.addCwe(cwe);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
*/
package org.owasp.dependencycheck.data.nodeaudit;

import org.owasp.dependencycheck.dependency.CvssV3;

import java.io.Serializable;
import java.util.List;
import javax.annotation.concurrent.ThreadSafe;
Expand Down Expand Up @@ -122,6 +124,7 @@ public class Advisory implements Serializable {
*/
private List<String> cwes;

private CvssV3 cvssV3;

public String getCreated() {
return created;
Expand Down Expand Up @@ -258,4 +261,12 @@ public String getGhsaId() {
public void setGhsaId(String ghsaId) {
this.ghsaId = ghsaId;
}

public CvssV3 getCvssV3() {
return cvssV3;
}

public void setCvssV3(CvssV3 cvssV3) {
this.cvssV3 = cvssV3;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import org.json.JSONArray;
import org.json.JSONObject;
import org.owasp.dependencycheck.dependency.CvssV3;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
Expand Down Expand Up @@ -115,6 +116,36 @@ private Advisory parseAdvisory(JSONObject object) throws JSONException {
}
advisory.setCves(stringCves);
}
final JSONObject jsonCvss = object.optJSONObject("cvss");
if (jsonCvss != null) {
float baseScore = -1.0f;
final String score = jsonCvss.optString("score");
if (score != null) {
try {
baseScore = Float.parseFloat(score);
} catch (NumberFormatException ignored) {
LOGGER.trace("Swallowed NumberFormatException", ignored);
baseScore = -1.0f;
}
}
if (baseScore >= 0.0) {
final String vector = jsonCvss.optString("vectorString");
if (vector != null) {
if (vector.startsWith("CVSS:3") && baseScore >= 0.0) {
try {
final CvssV3 cvss = new CvssV3(vector, baseScore);
advisory.setCvssV3(cvss);
} catch (IllegalArgumentException iae) {
LOGGER.warn("Invalid CVSS vector format encountered in NPM Audit results '{}' ", vector, iae);
}
} else {
LOGGER.warn("Unsupported CVSS vector format in NPM Audit results, please file a feature " +
"request at https://github.com/jeremylong/DependencyCheck/issues/new/choose to " +
"support vector format '{}' ", vector);
}
}
}
}
return advisory;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@
*/
package org.owasp.dependencycheck.dependency;

import org.sonatype.ossindex.service.api.cvss.Cvss3Severity;

import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

/**
* CVSS V3 scoring information.
Expand All @@ -26,6 +31,7 @@
*/
public class CvssV3 implements Serializable {

public static final List<String> BASE_METRICS = Arrays.asList("AV", "AC", "PR", "UI", "S", "C", "I", "A");
/**
* Serial version UID.
*/
Expand Down Expand Up @@ -142,6 +148,50 @@ public CvssV3(String attackVector, String attackComplexity, String privilegesReq
}
//CSON: ParameterNumber

/**
* Constructs a new CVSS V3 object from a CVSS v3.x Vector String representation and
* a CVSS V3 Base score.
*
* @param vectorString a CVSS v3 Vector String
* @param baseScore the CVSS v3 base score
* @throws IllegalArgumentException when the provided vectorString is not a valid
* <a href="https://www.first.org/cvss/specification-document#Vector-String">CVSS v3.x vector string</a>.
*/
public CvssV3(String vectorString, float baseScore) {
if (!vectorString.startsWith("CVSS:3")) {
throw new IllegalArgumentException("Not a valid CVSSv3 vector string: " + vectorString);
}
this.version = vectorString.substring(5, vectorString.indexOf('/'));
final String[] metricStrings = vectorString.substring(vectorString.indexOf('/') + 1).split("/");
final HashMap<String, String> metrics = new HashMap<>();
for (int i = 0; i < metricStrings.length; i++) {
final String[] metricKeyVal = metricStrings[i].split(":");
if (metricKeyVal.length != 2) {
throw new IllegalArgumentException(
String.format("Not a valid CVSSv3 vector string '%s', invalid metric component '%s'",
vectorString, metricStrings[i]));
}
metrics.put(metricKeyVal[0], metricKeyVal[1]);
}
if (!metrics.keySet().containsAll(BASE_METRICS)) {
throw new IllegalArgumentException(
String.format("Not a valid CVSSv3 vector string '%s'; missing one or more required Base Metrics;",
vectorString));
}
this.attackVector = metrics.get("AV");
this.attackComplexity = metrics.get("AC");
this.privilegesRequired = metrics.get("PR");
this.userInteraction = metrics.get("UI");
this.scope = metrics.get("S");
this.confidentialityImpact = metrics.get("C");
this.integrityImpact = metrics.get("I");
this.availabilityImpact = metrics.get("A");
this.baseScore = baseScore;
this.baseSeverity = Cvss3Severity.of(baseScore).name();
this.exploitabilityScore = null;
this.impactScore = null;
}

/**
* Get the value of attackVector.
*
Expand Down

0 comments on commit 7187a0d

Please sign in to comment.