Repository: dependency-check/DependencyCheck (language: java)

Issue:
Collaborate with dependency-track to use it as NVD proxy endpoint
**Is your feature request related to a problem? Please describe.**

We (like probably many others) used [dependency-track](https://github.com/DependencyTrack/dependency-track/releases/tag/4.9.1)  (prior dependency-check v9+) as proxy for NVD (legacy/non API V2) and other feeds.
This greatly lowers the load on public feed endpoints and makes CI pipelines using dependency-check more robust.

[Dependency-track V4.10.0](https://github.com/DependencyTrack/dependency-track/releases/tag/4.10.0)+ provides NIST NVD API v2 support (with API key etc).

**Describe the solution you'd like**
We would like to use its NVD endpoint for dependency-check (like we used to).

` dependency-check.sh Core  --updateonly  --nvdDatafeed=https://{{ endpoint }}/mirror/nvd`

**Describe alternatives you've considered**
I understand that one can create a proxy with the [vulnz cli](https://github.com/jeremylong/Open-Vulnerability-Project) and I have (as a test) been able to make the cached content from vulnz work via the http endpoint.

However, the dependency-check project collaborating with the dependency-track project would help the community significantly.

Here is what I did to research this a bit more ...


The cached (by dependency-track V4.10.0)  NVD files look like

```
nvdcve-1.1-{{ year }}.json
nvdcve-1.1-{{ year }}.json.gz
nvdcve-1.1-{{ year }}.json.gz.ts
nvdcve-1.1-{{ year }}.meta
(...)
nvdcve-1.1-modified.json
nvdcve-1.1-modified.json.gz
nvdcve-1.1-modified.json.gz.ts
nvdcve-1.1-modified.meta
```

I noted that the `cache.properties` is missing (that I understand you potentially would like to remove as a requirement).

I tested if I can create the cache.property file out of the meta data available.

` $ export p=../nist-orig; export c="${p}/cache.properties"; echo "prefix=nvdcve-1.1-" > "${c}"; for i in $(seq 2002 2023); do echo "lastModifiedDate.${i}=$(grep lastModifiedDate ${p}/nvdcve-1.1-${i}.meta|sed 's#lastModifiedDate:##g'|sed 's#:#\\:#g')" >> "${c}"; done; echo "lastModifiedDate.modified=$(grep lastModifiedDate ${p}/nvdcve-1.1-modified.meta|sed 's#lastModifiedDate:##g'|sed 's#:#\\:#g')" >> "${c}"`

creating this file.

```
prefix=nvdcve-1.1-
lastModifiedDate.2002=2023-11-07T03\:04\:03-05\:00
lastModifiedDate.2003=2023-11-07T03\:03\:59-05\:00
lastModifiedDate.2004=2023-11-07T03\:03\:57-05\:00
lastModifiedDate.2005=2023-11-08T03\:02\:12-05\:00
lastModifiedDate.2006=2023-11-29T03\:01\:23-05\:00
lastModifiedDate.2007=2023-12-08T03\:03\:39-05\:00
lastModifiedDate.2008=2023-12-08T03\:03\:33-05\:00
lastModifiedDate.2009=2023-12-08T03\:03\:26-05\:00
lastModifiedDate.2010=2023-12-08T03\:03\:20-05\:00
lastModifiedDate.2011=2023-12-08T03\:03\:13-05\:00
lastModifiedDate.2012=2023-12-08T03\:03\:06-05\:00
lastModifiedDate.2013=2023-12-09T03\:02\:56-05\:00
lastModifiedDate.2014=2023-12-09T03\:02\:47-05\:00
lastModifiedDate.2015=2023-12-09T03\:02\:40-05\:00
lastModifiedDate.2016=2023-12-09T03\:02\:31-05\:00
lastModifiedDate.2017=2023-12-09T03\:02\:19-05\:00
lastModifiedDate.2018=2023-12-09T03\:01\:55-05\:00
lastModifiedDate.2019=2023-12-09T03\:01\:36-05\:00
lastModifiedDate.2020=2023-12-11T03\:01\:28-05\:00
lastModifiedDate.2021=2023-12-11T03\:01\:03-05\:00
lastModifiedDate.2022=2023-12-11T03\:00\:38-05\:00
lastModifiedDate.2023=2023-12-11T03\:00\:14-05\:00
lastModifiedDate.modified=2023-12-11T06\:00\:01-05\:00
```
but that failed with

$ dependency-check.sh Core  --updateonly  --nvdDatafeed=https://{{ endpoint }}/mirror/nvd



```
[INFO] Checking for updates
[INFO] NVD API Cache requires several updates; this could take a couple of minutes.
[INFO] Download Started for NVD Cache - https://{{ endpoint }}/mirror/nvd/nvdcve-1.1-2012.json.gz
[ERROR] Error downloading NVD CVE - https://{{ endpoint }}/mirror/nvd/nvdcve-1.1-2012.json.gz Reason: Unrecognized field "CVE_data_type" (class io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20), not marked as ignorable (7 known properties: "startIndex", "totalResults", "resultsPerPage", "format", "version", "vulnerabilities", "timestamp"])
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 2, column: 22] (through reference chain: io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20["CVE_data_type"])
[INFO] Download Started for NVD Cache - https://{{ endpoint }}/mirror/nvd/nvdcve-1.1-2023.json.gz
[ERROR] Error downloading NVD CVE - https://{{ endpoint }}/mirror/nvd/nvdcve-1.1-2023.json.gz Reason: Unrecognized field "CVE_data_type" (class io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20), not marked as ignorable (7 known properties: "startIndex", "totalResults", "resultsPerPage", "format", "version", "vulnerabilities", "timestamp"])
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 2, column: 22] (through reference chain: io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20["CVE_data_type"])
[INFO] Download Started for NVD Cache - https://{{ endpoint }}/mirror/nvd/nvdcve-1.1-2011.json.gz
[ERROR] Error downloading NVD CVE - https://{{ endpoint }}/mirror/nvd/nvdcve-1.1-2011.json.gz Reason: Unrecognized field "CVE_data_type" (class io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20), not marked as ignorable (7 known properties: "startIndex", "totalResults", "resultsPerPage", "format", "version", "vulnerabilities", "timestamp"])
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 2, column: 22] (through reference chain: io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20["CVE_data_type"])
[INFO] Download Started for NVD Cache - https://{{ endpoint }}/mirror/nvd/nvdcve-1.1-2022.json.gz
[ERROR] Error downloading NVD CVE - https://{{ endpoint }}/mirror/nvd/nvdcve-1.1-2022.json.gz Reason: Unrecognized field "CVE_data_type" (class io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20), not marked as ignorable (7 known properties: "startIndex", "totalResults", "resultsPerPage", "format", "version", "vulnerabilities", "timestamp"])
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 2, column: 22] (through reference chain: io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20["CVE_data_type"])
[INFO] Download Started for NVD Cache - https://{{ endpoint }}/mirror/nvd/nvdcve-1.1-2010.json.gz
[ERROR] Error downloading NVD CVE - https://{{ endpoint }}/mirror/nvd/nvdcve-1.1-2010.json.gz Reason: Unrecognized field "CVE_data_type" (class io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20), not marked as ignorable (7 known properties: "startIndex", "totalResults", "resultsPerPage", "format", "version", "vulnerabilities", "timestamp"])
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 2, column: 22] (through reference chain: io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20["CVE_data_type"])
[INFO] Download Started for NVD Cache - https://{{ endpoint }}/mirror/nvd/nvdcve-1.1-2021.json.gz
[ERROR] Error downloading NVD CVE - https://{{ endpoint }}/mirror/nvd/nvdcve-1.1-2021.json.gz Reason: Unrecognized field "CVE_data_type" (class io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20), not marked as ignorable (7 known properties: "startIndex", "totalResults", "resultsPerPage", "format", "version", "vulnerabilities", "timestamp"])
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 2, column: 22] (through reference chain: io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20["CVE_data_type"])
[INFO] Download Started for NVD Cache - https://{{ endpoint }}/mirror/nvd/nvdcve-1.1-2020.json.gz
[ERROR] Error downloading NVD CVE - https://{{ endpoint }}/mirror/nvd/nvdcve-1.1-2020.json.gz Reason: Unrecognized field "CVE_data_type" (class io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20), not marked as ignorable (7 known properties: "startIndex", "totalResults", "resultsPerPage", "format", "version", "vulnerabilities", "timestamp"])
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 2, column: 22] (through reference chain: io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20["CVE_data_type"])
[INFO] Download Started for NVD Cache - https://{{ endpoint }}/mirror/nvd/nvdcve-1.1-2009.json.gz
[ERROR] Error downloading NVD CVE - https://{{ endpoint }}/mirror/nvd/nvdcve-1.1-2009.json.gz Reason: Unrecognized field "CVE_data_type" (class io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20), not marked as ignorable (7 known properties: "startIndex", "totalResults", "resultsPerPage", "format", "version", "vulnerabilities", "timestamp"])
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 2, column: 22] (through reference chain: io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20["CVE_data_type"])
[INFO] Download Started for NVD Cache - https://{{ endpoint }}/mirror/nvd/nvdcve-1.1-2008.json.gz
[ERROR] The execution of the download was interrupted
org.owasp.dependencycheck.data.update.exception.UpdateException: The execution of the download was interrupted
	at org.owasp.dependencycheck.data.update.NvdApiDataSource.processDownload(NvdApiDataSource.java:261)
	at org.owasp.dependencycheck.data.update.NvdApiDataSource.processDatafeed(NvdApiDataSource.java:156)
	at org.owasp.dependencycheck.data.update.NvdApiDataSource.update(NvdApiDataSource.java:108)
	at org.owasp.dependencycheck.Engine.doUpdates(Engine.java:906)
	at org.owasp.dependencycheck.Engine.doUpdates(Engine.java:878)
	at org.owasp.dependencycheck.App.runUpdateOnly(App.java:427)
	at org.owasp.dependencycheck.App.run(App.java:172)
	at org.owasp.dependencycheck.App.main(App.java:89)
Caused by: java.util.concurrent.ExecutionException: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "CVE_data_type" (class io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20), not marked as ignorable (7 known properties: "startIndex", "totalResults", "resultsPerPage", "format", "version", "vulnerabilities", "timestamp"])
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 2, column: 22] (through reference chain: io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20["CVE_data_type"])
	at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
	at org.owasp.dependencycheck.data.update.NvdApiDataSource.processDownload(NvdApiDataSource.java:251)
	... 7 common frames omitted
Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "CVE_data_type" (class io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20), not marked as ignorable (7 known properties: "startIndex", "totalResults", "resultsPerPage", "format", "version", "vulnerabilities", "timestamp"])
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 2, column: 22] (through reference chain: io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20["CVE_data_type"])
	at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
	at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:1153)
	at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:2224)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1719)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1697)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:316)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
	at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4899)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3846)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3814)
	at org.owasp.dependencycheck.data.update.nvd.api.DownloadTask.call(DownloadTask.java:95)
	at org.owasp.dependencycheck.data.update.nvd.api.DownloadTask.call(DownloadTask.java:42)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:833)
[INFO] Skipping RetireJS update since last update was within 24 hours.
[INFO] Skipping Hosted Suppressions file update since last update was within 2 hours.
[INFO] Updating CISA Known Exploited Vulnerability list: https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json
[INFO] Begin database defrag
[ERROR] Error downloading NVD CVE - https://{{ endpoint }}/mirror/nvd/nvdcve-1.1-2008.json.gz Reason: Unrecognized field "CVE_data_type" (class io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20), not marked as ignorable (7 known properties: "startIndex", "totalResults", "resultsPerPage", "format", "version", "vulnerabilities", "timestamp"])
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 2, column: 22] (through reference chain: io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20["CVE_data_type"])
[INFO] End database defrag (257 ms)
[ERROR] The execution of the download was interrupted
org.owasp.dependencycheck.data.update.exception.UpdateException: The execution of the download was interrupted
	at org.owasp.dependencycheck.data.update.NvdApiDataSource.processDownload(NvdApiDataSource.java:261)
	at org.owasp.dependencycheck.data.update.NvdApiDataSource.processDatafeed(NvdApiDataSource.java:156)
	at org.owasp.dependencycheck.data.update.NvdApiDataSource.update(NvdApiDataSource.java:108)
	at org.owasp.dependencycheck.Engine.doUpdates(Engine.java:906)
	at org.owasp.dependencycheck.Engine.doUpdates(Engine.java:878)
	at org.owasp.dependencycheck.App.runUpdateOnly(App.java:427)
	at org.owasp.dependencycheck.App.run(App.java:172)
	at org.owasp.dependencycheck.App.main(App.java:89)
Caused by: java.util.concurrent.ExecutionException: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "CVE_data_type" (class io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20), not marked as ignorable (7 known properties: "startIndex", "totalResults", "resultsPerPage", "format", "version", "vulnerabilities", "timestamp"])
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 2, column: 22] (through reference chain: io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20["CVE_data_type"])
	at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
	at org.owasp.dependencycheck.data.update.NvdApiDataSource.processDownload(NvdApiDataSource.java:251)
	... 7 common frames omitted
Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "CVE_data_type" (class io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20), not marked as ignorable (7 known properties: "startIndex", "totalResults", "resultsPerPage", "format", "version", "vulnerabilities", "timestamp"])
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 2, column: 22] (through reference chain: io.github.jeremylong.openvulnerability.client.nvd.CveApiJson20["CVE_data_type"])
	at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
	at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:1153)
	at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:2224)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1719)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1697)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:316)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
	at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4899)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3846)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3814)
	at org.owasp.dependencycheck.data.update.nvd.api.DownloadTask.call(DownloadTask.java:95)
	at org.owasp.dependencycheck.data.update.nvd.api.DownloadTask.call(DownloadTask.java:42)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:833)
```


Discussion / hints:
The other way to create the mirror is with the vulnz CLI - and with 5.1.0 it now produces the meta files as well. I plan on updating ODC to use the meta files.
The URLs provided make it look like the provided cache is using the 1.1 schema as opposed to the 2.0 schema?
@jeremylong I think you're right. The dependencytrack documentation (https://docs.dependencytrack.org/datasources/nvd/) is somewhat vague or confusing after the migration to NVD API, but to my understanding
1. dependencytrack will continue to mirror the NVD data feeds (no updates after 15.12.2023 I guess)
2. and encourage to switch to NVD REST API mirroring

But nowhere is it stated or documented, that dependencytrack will allow other tools - e.g. dependency-check - to utilize the NVD API mirror or proxy.

I guess, I and others are hoping to utilize the dependencytrack NVD API data through some mirror or proxy functionality as opposed to fetching it from NVD API (or through some caching mechanism) for dependency-check.
At least, this is what we used to do, for dependency-check prior to 9.0.0 and dependencytrack prior to 4.10.0, where we pointed the dependency-check update url to dependencytrack's mirror like
```
cve {
   urlModified = 'https://dependencytrack/mirror/nvd/nvdcve-1.1-modified.json.gz'
}
```
The only thing I know of that can create a cache of the NVD API 2.0 data is the [vulnz cli](https://github.com/jeremylong/Open-Vulnerability-Project/tree/main/vulnz#caching-the-nvd-cve-data). If dependency-track has a way to mirror the data in the same schema as available from the NVD API (currently 2.0) then we can likely figure something out.
> The only thing I know of that can create a cache of the NVD API 2.0 data is the [vulnz cli](https://github.com/jeremylong/Open-Vulnerability-Project/tree/main/vulnz#caching-the-nvd-cve-data). If dependency-track has a way to mirror the data in the same schema as available from the NVD API (currently 2.0) then we can likely figure something out.

I believe dependency-track (v4.10.0) already uses a client library from [open-vulnerability-clients](https://github.com/jeremylong/Open-Vulnerability-Project/blob/main/open-vulnerability-clients) to implement the mirroring. Class `org/dependencytrack/tasks/NistApiMirrorTask.java` (https://github.com/DependencyTrack/dependency-track/blob/master/src/main/java/org/dependencytrack/tasks/NistApiMirrorTask.java) has dependencies on `io.github.jeremylong.openvulnerability.client.*`

I don't know how the NVD API 2.0 data is persisted in dependency-track v4.10.0.

It would be really useful to take advantage of the dependency-track NVD mirroring feature in dependency-check. Both projects are related to OWASP. Thank you for your work!
The feeds provided by DT are still the original 1.1 feed files as served by the NVD. DT does not convert the data from the NVD REST API to the feed format.

The problem is that DT itself does not *need* large chunks of the data returned by the NVD. It only persists in its database what it really needs. It's thus not possible to generate the original feed files based on that data alone.

The way the NVD REST API is to be consumed also makes it hard to generate feed files: CVEs are provided based on their last modification date, not their publish date. The latter is how the feed files were organized. If you want to replicate that, you have to keep *all* CVEs in memory, then at the very end group them by publish date, and finally write that to partitioned `nvdcve-1.1-<YEAR>.json` files.

From what I understand, that is [pretty much how `vulnz` is doing it](https://github.com/jeremylong/Open-Vulnerability-Project/blob/c2fb94510a6632748436a9058a75ffa35d04e0b0/vulnz/src/main/java/io/github/jeremylong/vulnz/cli/commands/CveCommand.java#L241). That approach is fine for a short-lived CLI application, but not for DT, which is a long-running application that has many more responsibilities to fulfill concurrently. This type of cache management is _very_ memory and I/O heavy, even more so when the cache is supposed to be updated regularly.

I think it might be the easiest to point both DT and DC to the same, `vulnz`-generated cache.
I am experimenting with dumping the raw data into a Lucene index and have it indexed by CVE ID and last modification timestamp. Theoretically, using this, DT should be able to emulate the REST API responses of the NVD, serving CVEs which have been modified since a given timestamp.
I think the above is a workable solution. @jeremylong as long as users are able to customize the NVD REST API URL in DependencyCheck, DT can act as a cache for it (https://github.com/nscuro/dependency-track/commit/4e63ee94e9d2c132fda4354e4265e07b30dd9761). I already tested with two DT instances, and one is able to pull CVE data from the other's mirror just fine this way.

Are there any other query parameters than `lastModStart` and `lastModEnd` that DependencyCheck might use? The Lucene-based approach gives us more flexibility than static files, but also requires us knowing the fields that clients may filter by.

Fix patch:
diff --git a/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java b/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java
index 72d47e7fca3..8b215d06f55 100644
--- a/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java
+++ b/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java
@@ -21,17 +21,13 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
-import java.lang.reflect.Field;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
 import org.owasp.dependencycheck.Engine;
 import org.owasp.dependencycheck.utils.Settings;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.slf4j.impl.StaticLoggerBinder;
-import org.slf4j.spi.LocationAwareLogger;
 
 /**
  * An Ant task definition to execute dependency-check during an Ant build.
diff --git a/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Update.java b/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Update.java
index 0d998b545ad..b26bb7e16fb 100644
--- a/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Update.java
+++ b/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Update.java
@@ -37,6 +37,10 @@
 @SuppressWarnings("common-java:DuplicatedBlocks")
 public class Update extends Purge {
 
+    /**
+     * The NVD API endpoint.
+     */
+    private String nvdApiEndpoint;
     /**
      * The NVD API Key.
      */
@@ -139,6 +143,24 @@ public Update() {
         StaticLoggerBinder.getSingleton().setTask(this);
     }
 
+    /**
+     * Get the value of nvdApiEndpoint.
+     *
+     * @return the value of nvdApiEndpoint
+     */
+    public String getNvdApiEndpoint() {
+        return nvdApiEndpoint;
+    }
+
+    /**
+     * Set the value of nvdApiEndpoint.
+     *
+     * @param nvdApiEndpoint new value of nvdApiEndpoint
+     */
+    public void setNvdApiEndpoint(String nvdApiEndpoint) {
+        this.nvdApiEndpoint = nvdApiEndpoint;
+    }
+
     /**
      * Get the value of nvdApiKey.
      *
@@ -596,6 +618,7 @@ protected void populateSettings() throws BuildException {
         getSettings().setBooleanIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_ENABLED, hostedSuppressionsEnabled);
 
         getSettings().setStringIfNotEmpty(Settings.KEYS.NVD_API_KEY, nvdApiKey);
+        getSettings().setStringIfNotEmpty(Settings.KEYS.NVD_API_ENDPOINT, nvdApiEndpoint);
         getSettings().setIntIfNotNull(Settings.KEYS.NVD_API_DELAY, nvdApiDelay);
         getSettings().setStringIfNotEmpty(Settings.KEYS.NVD_API_DATAFEED_URL, nvdDatafeedUrl);
         getSettings().setStringIfNotEmpty(Settings.KEYS.NVD_API_DATAFEED_USER, nvdUser);
diff --git a/ant/src/site/markdown/config-update.md b/ant/src/site/markdown/config-update.md
index 6bc83c61d4b..67d63add8d8 100644
--- a/ant/src/site/markdown/config-update.md
+++ b/ant/src/site/markdown/config-update.md
@@ -35,6 +35,7 @@ The following properties can be configured in the plugin. However, they are less
 Property             | Description                                                                                                          | Default Value
 ---------------------|----------------------------------------------------------------------------------------------------------------------|------------------
 nvdApiKey            | The API Key to access the NVD API; obtained from https://nvd.nist.gov/developers/request-an-api-key                  | &nbsp;
+nvdApiEndpoint       | The NVD API endpoint URL; setting this is uncommon.                                                                  | https://services.nvd.nist.gov/rest/json/cves/2.0
 nvdMaxRetryCount     | The maximum number of retry requests for a single call to the NVD API.                                               | 10
 nvdApiDelay          | The number of milliseconds to wait between calls to the NVD API.                                                     | 2000 with an NVD API Key or 8000 without an API Key
 nvdDatafeedUrl       | The URL for the NVD API Data feed that can be generated using https://github.com/jeremylong/Open-Vulnerability-Project/tree/main/vulnz#caching-the-nvd-cve-data - example value `https://internal.server/cache/nvdcve-{0}.json.gz` | &nbsp;
diff --git a/ant/src/site/markdown/configuration.md b/ant/src/site/markdown/configuration.md
index b108f7bff26..4c10ea5afd3 100644
--- a/ant/src/site/markdown/configuration.md
+++ b/ant/src/site/markdown/configuration.md
@@ -144,6 +144,7 @@ The following properties can be configured in the plugin. However, they are less
 Property             | Description                                                                                                  | Default Value
 ---------------------|--------------------------------------------------------------------------------------------------------------|------------------
 nvdApiKey            | The API Key to access the NVD API; obtained from https://nvd.nist.gov/developers/request-an-api-key          | &nbsp;
+nvdApiEndpoint       | The NVD API endpoint URL; setting this is uncommon.                                                          | https://services.nvd.nist.gov/rest/json/cves/2.0
 nvdMaxRetryCount     | The maximum number of retry requests for a single call to the NVD API.                                       | 10
 nvdApiDelay          | The number of milliseconds to wait between calls to the NVD API.                                             | 2000 with an NVD API Key or 8000 without an API Key
 nvdDatafeedUrl       | The URL for the NVD API Data feed that can be generated using https://github.com/jeremylong/Open-Vulnerability-Project/tree/main/vulnz#caching-the-nvd-cve-data - example value `https://internal.server/cache/nvdcve-{0}.json.gz` | &nbsp;
diff --git a/cli/src/main/java/org/owasp/dependencycheck/App.java b/cli/src/main/java/org/owasp/dependencycheck/App.java
index 12ed6ab6db1..dafed884840 100644
--- a/cli/src/main/java/org/owasp/dependencycheck/App.java
+++ b/cli/src/main/java/org/owasp/dependencycheck/App.java
@@ -656,6 +656,8 @@ protected void populateSettings(CliParser cli) throws InvalidSettingException {
             }
             settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_KEY, key);
         }
+        settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_ENDPOINT,
+                cli.getStringArgument(CliParser.ARGUMENT.NVD_API_ENDPOINT));
         settings.setIntIfNotNull(Settings.KEYS.NVD_API_DELAY, cli.getIntegerValue(CliParser.ARGUMENT.NVD_API_DELAY));
         settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_DATAFEED_URL, cli.getStringArgument(CliParser.ARGUMENT.NVD_API_DATAFEED_URL));
         settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_DATAFEED_USER, cli.getStringArgument(CliParser.ARGUMENT.NVD_API_DATAFEED_USER));
diff --git a/cli/src/main/java/org/owasp/dependencycheck/CliParser.java b/cli/src/main/java/org/owasp/dependencycheck/CliParser.java
index ff4acef2b0c..d6bd6596104 100644
--- a/cli/src/main/java/org/owasp/dependencycheck/CliParser.java
+++ b/cli/src/main/java/org/owasp/dependencycheck/CliParser.java
@@ -353,6 +353,8 @@ private void addAdvancedOptions(final Options options) {
                         "Only update the local NVD data cache; no scan will be executed."))
                 .addOption(newOptionWithArg(ARGUMENT.NVD_API_DELAY, "milliseconds",
                         "Time in milliseconds to wait between downloading from the NVD."))
+                .addOption(newOptionWithArg(ARGUMENT.NVD_API_ENDPOINT, "endpoint",
+                        "The NVD API Endpoint - setting this is rare."))
                 .addOption(newOptionWithArg(ARGUMENT.NVD_API_DATAFEED_URL, "url",
                         "The URL to the NVD API Datafeed."))
                 .addOption(newOptionWithArg(ARGUMENT.NVD_API_DATAFEED_USER, "user",
@@ -1128,7 +1130,11 @@ public static class ARGUMENT {
          */
         public static final String DATA_DIRECTORY = "data";
         /**
-         * The CLI argument name for setting the URL for the CVE Data Files.
+         * The CLI argument name for setting the URL for the NVD API Endpoint
+         */
+        public static final String NVD_API_ENDPOINT = "nvdApiEndpoint";
+        /**
+         * The CLI argument name for setting the URL for the NVD API Key.
          */
         public static final String NVD_API_KEY = "nvdApiKey";
         /**
diff --git a/cli/src/site/markdown/arguments.md b/cli/src/site/markdown/arguments.md
index 0c9df36429d..da8ab2a8c44 100644
--- a/cli/src/site/markdown/arguments.md
+++ b/cli/src/site/markdown/arguments.md
@@ -28,6 +28,7 @@ Advanced Options
 | Short | Argument Name                         | Parameter       | Description                                                                                                                                                                                            | Default Value |
 |-------|---------------------------------------|-----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
 |       | \-\-nvdApiKey                         | \<apiKey\>      | The API Key to access the NVD API; obtained from https://nvd.nist.gov/developers/request-an-api-key                                                                                                    | &nbsp;        |
+|       | \-\-nvdApiEndpoint                    | \<endpoint\>    | The NVD API endpoint URL; setting this is uncommon.                                                                                                                                                    | https://services.nvd.nist.gov/rest/json/cves/2.0 |
 |       | \-\-nvdMaxRetryCount                  | \<count\>       | The maximum number of retry requests for a single call to the NVD API.                                                                                                                                 | 10            |
 |       | \-\-nvdApiDelay                       | \<milliseconds\>| The number of milliseconds to wait between calls to the NVD API.                                                                                                                                       | 2000 with an NVD API Key or 8000 without an API Key |
 |       | \-\-nvdDatafeed                       | \<url\>         | The URL for the NVD API Data feed that can be generated using https://github.com/jeremylong/Open-Vulnerability-Project/tree/main/vulnz#caching-the-nvd-cve-data - example value `https://internal.server/cache/nvdcve-{0}.json.gz` | &nbsp; |
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/update/NvdApiDataSource.java b/core/src/main/java/org/owasp/dependencycheck/data/update/NvdApiDataSource.java
index 0e3a67fa4a7..2eb49a00116 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/update/NvdApiDataSource.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/update/NvdApiDataSource.java
@@ -297,6 +297,10 @@ private boolean processApi() throws UpdateException {
 
         ZonedDateTime lastModifiedRequest = dbProperties.getTimestamp(DatabaseProperties.NVD_API_LAST_MODIFIED);
         final NvdCveClientBuilder builder = NvdCveClientBuilder.aNvdCveApi();
+        final String endpoint = settings.getString(Settings.KEYS.NVD_API_ENDPOINT);
+        if (endpoint != null) {
+            builder.withEndpoint(endpoint);
+        }
         if (lastModifiedRequest != null) {
             final ZonedDateTime end = lastModifiedRequest.minusDays(-120);
             builder.withLastModifiedFilter(lastModifiedRequest, end);
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 0ce6cac2bf8..9acc3d70f2a 100644
--- a/maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java
+++ b/maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java
@@ -77,7 +77,6 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
-import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -88,7 +87,6 @@
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
-import java.util.logging.Level;
 import org.apache.maven.artifact.repository.ArtifactRepository;
 
 import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
@@ -109,9 +107,6 @@
 import org.owasp.dependencycheck.utils.SeverityUtil;
 import org.owasp.dependencycheck.xml.pom.Model;
 import org.owasp.dependencycheck.xml.pom.PomUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.slf4j.spi.LocationAwareLogger;
 
 //CSOFF: FileLength
 /**
@@ -941,7 +936,12 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
     @SuppressWarnings("CanBeFinal")
     @Parameter(property = "nvdValidForHours")
     private Integer nvdValidForHours;
-
+    /**
+     * The NVD API Endpoint; setting this is uncommon.
+     */
+    @SuppressWarnings("CanBeFinal")
+    @Parameter(property = "nvdApiEndpoint")
+    private String nvdApiEndpoint;
     /**
      * The NVD API Data Feed URL.
      */
@@ -2334,6 +2334,7 @@ protected void populateSettings() {
         }
         settings.setStringIfNotEmpty(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
         settings.setStringIfNotEmpty(Settings.KEYS.DB_FILE_NAME, dbFilename);
+        settings.setStringIfNotNull(Settings.KEYS.NVD_API_ENDPOINT, nvdApiEndpoint);
         settings.setIntIfNotNull(Settings.KEYS.NVD_API_DELAY, nvdApiDelay);
         settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_DATAFEED_URL, nvdDatafeedUrl);
         settings.setIntIfNotNull(Settings.KEYS.NVD_API_VALID_FOR_HOURS, nvdValidForHours);
diff --git a/maven/src/site/markdown/configuration.md b/maven/src/site/markdown/configuration.md
index d429c11607c..2e7ba72e3e6 100644
--- a/maven/src/site/markdown/configuration.md
+++ b/maven/src/site/markdown/configuration.md
@@ -143,6 +143,7 @@ The following properties can be configured in the plugin. However, they are less
 Property                 | Description                                                                                                                                | Default Value                                                       |
 -------------------------|--------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------|
 nvdApiKey                | The API Key to access the NVD API; obtained from https://nvd.nist.gov/developers/request-an-api-key                                        | &nbsp;                                                              |
+nvdApiEndpoint           | The NVD API endpoint URL; setting this is uncommon.                                                                                        | https://services.nvd.nist.gov/rest/json/cves/2.0                    |
 nvdApiServerId           | The id of a server defined in the settings.xml that configures the credentials (password is used as ApiKey) for accessing the NVD API.     | &nbsp;                                                              |
 nvdMaxRetryCount         | The maximum number of retry requests for a single call to the NVD API.                                                                     | 10                                                                  |
 nvdApiDelay              | The number of milliseconds to wait between calls to the NVD API.                                                                           | 2000 with an NVD API Key or 8000 without an API Key .               |
diff --git a/src/site/markdown/dependency-check-gradle/configuration-aggregate.md b/src/site/markdown/dependency-check-gradle/configuration-aggregate.md
index 88af812a5b3..69d1f3fd77c 100644
--- a/src/site/markdown/dependency-check-gradle/configuration-aggregate.md
+++ b/src/site/markdown/dependency-check-gradle/configuration-aggregate.md
@@ -86,6 +86,7 @@ Note, if ANY of the cve configuration group are set - they should all be set to
 Config Group | Property          | Description                                                                                                  | Default Value                                                       |
 -------------|-------------------|--------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------|
 nvd          | apiKey            | The API Key to access the NVD API; obtained from https://nvd.nist.gov/developers/request-an-api-key          | &nbsp;                                                              |
+nvd          | endpoint          | The NVD API endpoint URL; setting this is uncommon.                                                          | https://services.nvd.nist.gov/rest/json/cves/2.0                    |
 nvd          | maxRetryCount     | The maximum number of retry requests for a single call to the NVD API.                                       | 10                                                                  |
 nvd          | delay             | The number of milliseconds to wait between calls to the NVD API.                                             | 2000 with an NVD API Key or 8000 without an API Key                 |
 nvd          | datafeedUrl       | The URL for the NVD API Data feed that can be generated using https://github.com/jeremylong/Open-Vulnerability-Project/tree/main/vulnz#caching-the-nvd-cve-data | &nbsp;           |
diff --git a/src/site/markdown/dependency-check-gradle/configuration-update.md b/src/site/markdown/dependency-check-gradle/configuration-update.md
index 6df0c67e554..301adc90d8a 100644
--- a/src/site/markdown/dependency-check-gradle/configuration-update.md
+++ b/src/site/markdown/dependency-check-gradle/configuration-update.md
@@ -63,6 +63,7 @@ The following properties can be configured in the dependencyCheck task. However,
 Config Group | Property          | Description                                                                                                  | Default Value                                                       |
 -------------|-------------------|--------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------|
 nvd          | apiKey            | The API Key to access the NVD API; obtained from https://nvd.nist.gov/developers/request-an-api-key          | &nbsp;                                                              |
+nvd          | endpoint          | The NVD API endpoint URL; setting this is uncommon.                                                          | https://services.nvd.nist.gov/rest/json/cves/2.0                    |
 nvd          | maxRetryCount     | The maximum number of retry requests for a single call to the NVD API.                                       | 10                                                                  |
 nvd          | delay             | The number of milliseconds to wait between calls to the NVD API.                                             | 2000 with an NVD API Key or 8000 without an API Key .               |
 nvd          | datafeedUrl       | The URL for the NVD API Data feed that can be generated using https://github.com/jeremylong/Open-Vulnerability-Project/tree/main/vulnz#caching-the-nvd-cve-data | &nbsp;           |
diff --git a/src/site/markdown/dependency-check-gradle/configuration.md b/src/site/markdown/dependency-check-gradle/configuration.md
index eafb42ec431..8115828ebee 100644
--- a/src/site/markdown/dependency-check-gradle/configuration.md
+++ b/src/site/markdown/dependency-check-gradle/configuration.md
@@ -68,6 +68,7 @@ The following properties can be configured in the dependencyCheck task. However,
 Config Group | Property          | Description                                                                                                          | Default Value
 -------------|-------------------|----------------------------------------------------------------------------------------------------------------------|------------------
 nvd          | apiKey            | The API Key to access the NVD API; obtained from https://nvd.nist.gov/developers/request-an-api-key                  | &nbsp;                                                              |
+nvd          | endpoint          | The NVD API endpoint URL; setting this is uncommon.                                                          | https://services.nvd.nist.gov/rest/json/cves/2.0                            |
 nvd          | maxRetryCount     | The maximum number of retry requests for a single call to the NVD API.                                               | 10                                                                  |
 nvd          | delay             | The number of milliseconds to wait between calls to the NVD API.                                                     | 2000 with an NVD API Key or 8000 without an API Key                 |
 nvd          | datafeedUrl       | The URL for the NVD API Data feed that can be generated using https://github.com/jeremylong/Open-Vulnerability-Project/tree/main/vulnz#caching-the-nvd-cve-data | &nbsp;                   |
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 7141acf6d8f..7fda5772208 100644
--- a/utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java
+++ b/utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java
@@ -161,7 +161,10 @@ public static final class KEYS {
          * be imported.
          */
         public static final String CVE_CPE_STARTS_WITH_FILTER = "cve.cpe.startswith.filter";
-
+        /**
+         * The NVD API Endpoint.
+         */
+        public static final String NVD_API_ENDPOINT = "nvd.api.endpoint";
         /**
          * API Key for the NVD API.
          */


Test patch: