Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #931 : Support for Google OSV #1703

Merged
merged 28 commits into from
Jul 24, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
bcbddff
draft for using google OSV
sahibamittal Jun 10, 2022
ee624bc
ConfigProperties test fix
sahibamittal Jun 10, 2022
594af37
Vulnerability mapping done
sahibamittal Jun 14, 2022
7b6ea43
unit test for osv task
sahibamittal Jun 15, 2022
a9a0783
osv enabled default to true
sahibamittal Jun 16, 2022
a8adf36
fixes and tests
sahibamittal Jun 17, 2022
eeb1372
fix http client
sahibamittal Jun 17, 2022
dba49b5
update source of vulnerability
sahibamittal Jun 23, 2022
0fb6ad1
map credits
sahibamittal Jun 23, 2022
6f725af
minor changes
sahibamittal Jun 24, 2022
b987030
close reader
sahibamittal Jun 24, 2022
cca6c9f
update severity calculation and prioritize
sahibamittal Jun 28, 2022
cdf1e90
handle vulnerability mapping to avoid whole task
sahibamittal Jun 28, 2022
7fe4c5d
fix out of bound exception
sahibamittal Jun 28, 2022
2edf945
changes to avoid clashing with github or nvd
sahibamittal Jun 29, 2022
7fb3b42
fix for commit hash ranges and small changes requested
sahibamittal Jun 30, 2022
d8f836a
handle purl parsing
sahibamittal Jul 1, 2022
985a58f
handle version range types, disable default osv
sahibamittal Jul 1, 2022
94072d5
fix de duplication of vulnerable softwares
sahibamittal Jul 1, 2022
7b0afee
small test fix
sahibamittal Jul 1, 2022
d66e211
Merge branch 'master' into google-osv-support
sahibamittal Jul 1, 2022
0477ecd
Perform `null` check before parsing PURLs
nscuro Jul 2, 2022
a8aba45
Adjust class names to rest of the code base
nscuro Jul 2, 2022
da1d059
Remove redundant QueryManager method; Test more mapped vulnerability …
nscuro Jul 2, 2022
bb57600
Refactor OSV range parsing to avoid infinite loops
nscuro Jul 2, 2022
c6c687e
Fetch `Vulnerability#vulnerableSoftware` lazily
nscuro Jul 3, 2022
d855040
change OSV label from Google
sahibamittal Jul 21, 2022
0c23fac
Merge remote-tracking branch 'upstream/master' into google-osv-support
sahibamittal Jul 21, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.dependencytrack.tasks.EpssMirrorTask;
import org.dependencytrack.tasks.FortifySscUploadTask;
import org.dependencytrack.tasks.GitHubAdvisoryMirrorTask;
import org.dependencytrack.tasks.OSVDownloadTask;
import org.dependencytrack.tasks.IndexTask;
import org.dependencytrack.tasks.InternalComponentIdentificationTask;
import org.dependencytrack.tasks.KennaSecurityUploadTask;
Expand Down Expand Up @@ -80,6 +81,7 @@ public void contextInitialized(final ServletContextEvent event) {
EVENT_SERVICE.subscribe(InternalAnalysisEvent.class, InternalAnalysisTask.class);
EVENT_SERVICE.subscribe(OssIndexAnalysisEvent.class, OssIndexAnalysisTask.class);
EVENT_SERVICE.subscribe(GitHubAdvisoryMirrorEvent.class, GitHubAdvisoryMirrorTask.class);
EVENT_SERVICE.subscribe(GoogleOSVMirrorEvent.class, OSVDownloadTask.class);
EVENT_SERVICE.subscribe(VulnDbSyncEvent.class, VulnDbSyncTask.class);
EVENT_SERVICE.subscribe(VulnDbAnalysisEvent.class, VulnDbAnalysisTask.class);
EVENT_SERVICE.subscribe(VulnerabilityAnalysisEvent.class, VulnerabilityAnalysisTask.class);
Expand Down Expand Up @@ -114,6 +116,7 @@ public void contextDestroyed(final ServletContextEvent event) {
EVENT_SERVICE.unsubscribe(InternalAnalysisTask.class);
EVENT_SERVICE.unsubscribe(OssIndexAnalysisTask.class);
EVENT_SERVICE.unsubscribe(GitHubAdvisoryMirrorTask.class);
EVENT_SERVICE.unsubscribe(OSVDownloadTask.class);
EVENT_SERVICE.unsubscribe(VulnDbSyncTask.class);
EVENT_SERVICE.unsubscribe(VulnDbAnalysisTask.class);
EVENT_SERVICE.unsubscribe(VulnerabilityAnalysisTask.class);
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/org/dependencytrack/event/GoogleOSVMirrorEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.dependencytrack.event;

import alpine.event.framework.Event;

/**
* Defines an event used to start a mirror of Google OSV.
*/
public class GoogleOSVMirrorEvent implements Event {

}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public enum ConfigPropertyConstants {
VULNERABILITY_SOURCE_NVD_FEEDS_URL("vuln-source", "nvd.feeds.url", "https://nvd.nist.gov/feeds", PropertyType.URL, "A base URL pointing to the hostname and path of the NVD feeds"),
VULNERABILITY_SOURCE_GITHUB_ADVISORIES_ENABLED("vuln-source", "github.advisories.enabled", "false", PropertyType.BOOLEAN, "Flag to enable/disable GitHub Advisories"),
VULNERABILITY_SOURCE_GITHUB_ADVISORIES_ACCESS_TOKEN("vuln-source", "github.advisories.access.token", null, PropertyType.STRING, "The access token used for GitHub API authentication"),
VULNERABILITY_SOURCE_GOOGLE_OSV_ENABLED("vuln-source", "google.osv.enabled", "true", PropertyType.BOOLEAN, "Flag to enable/disable Google OSV"),
VULNERABILITY_SOURCE_EPSS_ENABLED("vuln-source", "epss.enabled", "true", PropertyType.BOOLEAN, "Flag to enable/disable Exploit Prediction Scoring System"),
VULNERABILITY_SOURCE_EPSS_FEEDS_URL("vuln-source", "epss.feeds.url", "https://epss.cyentia.com", PropertyType.URL, "A base URL pointing to the hostname and path of the EPSS feeds"),
ACCEPT_ARTIFACT_CYCLONEDX("artifact", "cyclonedx.enabled", "true", PropertyType.BOOLEAN, "Flag to enable/disable the systems ability to accept CycloneDX uploads"),
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/org/dependencytrack/model/Vulnerability.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ public enum Source {
VULNDB, // VulnDB from Risk Based Security
OSSINDEX, // Sonatype OSS Index
RETIREJS, // Retire.js
INTERNAL // Internally-managed (and manually entered) vulnerability
INTERNAL, // Internally-managed (and manually entered) vulnerability
GOOGLE // Google OSV Advisories
}

@PrimaryKey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,11 @@
import org.dependencytrack.parser.github.graphql.model.GitHubSecurityAdvisory;
import org.dependencytrack.parser.github.graphql.model.GitHubVulnerability;
import org.dependencytrack.parser.github.graphql.model.PageableList;

import java.time.ZonedDateTime;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.List;

import static org.dependencytrack.util.JsonUtil.jsonStringToTimestamp;

public class GitHubSecurityAdvisoryParser {

public PageableList parse(final JSONObject object) {
Expand Down Expand Up @@ -102,7 +101,7 @@ private GitHubSecurityAdvisory parseSecurityAdvisory(final JSONObject object) {
final JSONObject cvss = object.optJSONObject("cvss");
if (cvss != null) {
advisory.setCvssScore(cvss.optInt("score", 0));
advisory.setCvssVector(cvss.optString("vectorString", null));
advisory.setCvssVector(cvss.optString("score", null));
}

final JSONObject cwes = object.optJSONObject("cwes");
Expand Down Expand Up @@ -162,15 +161,4 @@ private GitHubVulnerability parseVulnerability(final JSONObject object) {
}
return vulnerability;
}

private ZonedDateTime jsonStringToTimestamp(final String s) {
if (s == null) {
return null;
}
try {
return ZonedDateTime.parse(s);
} catch (DateTimeParseException e) {
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package org.dependencytrack.parser.osv;

import kong.unirest.json.JSONArray;
import kong.unirest.json.JSONObject;
import org.dependencytrack.parser.osv.model.OSVAdvisory;
import org.dependencytrack.parser.osv.model.OSVVulnerability;

import java.util.ArrayList;
import java.util.List;

import static org.dependencytrack.util.JsonUtil.jsonStringToTimestamp;

/*
Parser for Google OSV, an aggregator of vulnerability databases including GitHub Security Advisories, PyPA, RustSec, and Global Security Database, and more.
*/
public class GoogleOSVAdvisoryParser {

public OSVAdvisory parse(final JSONObject object) {

final OSVAdvisory advisory = new OSVAdvisory();
if(object != null) {
advisory.setId(object.optString("id", null));
advisory.setSummary(object.optString("summary", null));
advisory.setDetails(object.optString("details", null));
advisory.setPublished(jsonStringToTimestamp(object.optString("published", null)));
advisory.setModified(jsonStringToTimestamp(object.optString("modified", null)));
advisory.setSchema_version(object.optString("schema_version", null));

final JSONArray references = object.optJSONArray("references");
if (references != null) {
for (int i=0; i<references.length(); i++) {
final JSONObject reference = references.getJSONObject(i);
final String url = reference.optString("url", null);
advisory.addReference(url);
}
}

final JSONArray aliases = object.optJSONArray("aliases");
if(aliases != null) {
for (int i=0; i<aliases.length(); i++) {
advisory.addAlias(aliases.optString(i));
}
}

final JSONObject databaseSpecific = object.optJSONObject("database_specific");
if (databaseSpecific != null) {
advisory.setSeverity(databaseSpecific.optString("severity", null));
final JSONArray cweIds = databaseSpecific.optJSONArray("cwe_ids");
if(cweIds != null) {
for (int i=0; i<cweIds.length(); i++) {
advisory.addCweId(cweIds.optString(i));
}
}
}

final JSONObject cvss = object.optJSONObject("severity");
if (cvss != null) {
advisory.setCvssVector(cvss.optString("vectorString", null));
}

final List<OSVVulnerability> vulnerabilities = parseVulnerabilities(object);
advisory.setVulnerabilities(vulnerabilities);
}
return advisory;
}

private List<OSVVulnerability> parseVulnerabilities(JSONObject object) {

List<OSVVulnerability> osvVulnerabilityList = new ArrayList<>();
final JSONArray vulnerabilities = object.optJSONArray("affected");
if (vulnerabilities != null) {
for(int i=0; i<vulnerabilities.length(); i++) {

final JSONObject vulnerability = vulnerabilities.getJSONObject(i);
final JSONObject affectedPackageJson = vulnerability.optJSONObject("package");
final JSONArray ranges = vulnerability.optJSONArray("ranges");

if (ranges != null) {
for (int j=0; j<ranges.length(); j++) {
final JSONObject range = ranges.getJSONObject(i);
sahibamittal marked this conversation as resolved.
Show resolved Hide resolved
if(range.optString("type").equalsIgnoreCase("ECOSYSTEM")){
osvVulnerabilityList = parseVersionRanges(affectedPackageJson, range);
}

}
}
}
}
return osvVulnerabilityList;
}

private List<OSVVulnerability> parseVersionRanges(JSONObject affectedPackageJson, JSONObject range) {

final List<OSVVulnerability> osvVulnerabilityList = new ArrayList<>();
final JSONArray rangeEvents = range.optJSONArray("events");
if(rangeEvents != null) {
int k = 0;
while (k < rangeEvents.length()) {

OSVVulnerability osvVulnerability = new OSVVulnerability();
osvVulnerability.setPackageName(affectedPackageJson.optString("name", null));
osvVulnerability.setPackageEcosystem(affectedPackageJson.optString("ecosystem", null));
osvVulnerability.setPurl(affectedPackageJson.optString("purl", null));

JSONObject event = rangeEvents.getJSONObject(k);
String lower = event.optString("introduced", null);
if(lower != null) {
osvVulnerability.setLowerVersionRange(lower);
k += 1;
}
event = rangeEvents.getJSONObject(k);
String upper = event.optString("fixed", null);
if(upper != null) {
osvVulnerability.setUpperVersionRange(upper);
k += 1;
sahibamittal marked this conversation as resolved.
Show resolved Hide resolved
}
osvVulnerabilityList.add(osvVulnerability);
}
}
return osvVulnerabilityList;
}
}
31 changes: 31 additions & 0 deletions src/main/java/org/dependencytrack/parser/osv/model/Ecosystem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.dependencytrack.parser.osv.model;

public enum Ecosystem {

ANDROID("Android"),
GSD("GSD"),
GO("Go"),
ERLANG("Hex"),
JAVASCRIPT("JavaScript"),
LINUX("Linux"),
MAVEN("Maven"),
NUGET("NuGet"),
OSSFUZZ("OSS-Fuzz"),
PACKAGIST("Packagist"),
PYPI("PyPI"),
RUBYGEMS("RubyGems"),
UVI("UVI"),
RUST("crates.io"),
NPM("npm"),
DWF("DWF");

private final String value;

Ecosystem(final String value) {
this.value = value;
}

public String getValue() {
return value;
}
}
Loading