Skip to content

Commit 180dc00

Browse files
authored
refactor(database/NVD)!: implement all parameters and minimal timeout (#322)
1 parent 228147c commit 180dc00

3 files changed

Lines changed: 704 additions & 44 deletions

File tree

docs/database/nvd.md

Lines changed: 96 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,31 @@
11
# NVD
22

3-
NVD stand for <kbd>National Vulnerability Database</kbd>, which is the U.S. government repository of standards-based vulnerability management data. This database is maintained by NIST (National Institute of Standards and Technology).
3+
NVD stands for <kbd>National Vulnerability Database</kbd>, which is the U.S. government repository of standards-based vulnerability management data. This database is maintained by NIST (National Institute of Standards and Technology).
44

55
## Implementation Notes
66

77
The NVD integration uses the REST API (v2.0) available at [services.nvd.nist.gov](https://services.nvd.nist.gov/rest/json/cves/2.0).
88

99
### Search Parameters
1010

11-
While the NVD API supports CPE matching via the `cpeMatchString` parameter, we've chosen to use only keyword search for NPM packages. This decision was made because:
11+
While the NVD API supports CPE matching via parameters like `cpeName` and `virtualMatchString`, we've chosen not to use them for NPM packages. This decision was made because:
1212

1313
1. The CPE format for npm packages is not standardized in NVD
1414
2. Attempted CPE patterns (like `cpe:2.3:a:*:package-name:*:*:*:*:*:node.js:*:*`) resulted in 404 errors
1515
3. Keyword search provides more flexible results for JavaScript/NPM packages
1616

1717
The implementation might be enhanced in the future if NVD provides clearer guidelines for CPE matching of npm packages.
1818

19+
### Parameter Constraints
20+
21+
Some parameters have mutual exclusivity constraints enforced by the NVD API:
22+
23+
- `cvssV2Severity`, `cvssV3Severity`, and `cvssV4Severity` cannot be combined with each other.
24+
- `cvssV2Metrics`, `cvssV3Metrics`, and `cvssV4Metrics` cannot be combined with each other.
25+
- `keywordExactMatch` requires `keywordSearch` to be set.
26+
- `pubStartDate` and `pubEndDate` must be used together; the maximum range is 120 days.
27+
- `lastModStartDate` and `lastModEndDate` must be used together; the maximum range is 120 days.
28+
1929
## Format
2030

2131
The NVD API returns detailed vulnerability information.
@@ -46,35 +56,109 @@ const db = new vulnera.Database.NVD({
4656

4757
```ts
4858
export interface NVDOptions {
49-
credential?: ApiCredential;
59+
credential: ApiCredential;
60+
/**
61+
* Delay in milliseconds between consecutive requests in findMany.
62+
*
63+
* The NVD API enforces rate limits:
64+
* - Without API key: 5 requests per 30-second window → set ~6 000 ms
65+
* - With API key: 50 requests per 30-second window → set ~600 ms
66+
*
67+
* @default 6000
68+
*/
69+
requestDelay?: number;
5070
}
5171
```
5272

53-
### `findOne(parameters: NVDApiParameter): Promise<NVD[]>`
54-
Find the vulnerabilities of a given package using available NVD API parameters.
73+
> **Rate limiting:** The NVD API enforces strict rate limits (see [NVD developer docs](https://nvd.nist.gov/developers/start-here)). `findMany` sends requests sequentially with a `requestDelay` pause between each one to avoid being throttled. The default of 6 000 ms is safe for unauthenticated use. If you supply an API key you can safely lower it to ~600 ms.
74+
75+
### `find(parameters: NVDApiParameter): Promise<NVD[]>`
76+
Find vulnerabilities using any combination of available NVD API parameters.
5577

5678
```ts
5779
export type NVDApiParameter = {
80+
// Keyword search
5881
keywordSearch?: string;
82+
keywordExactMatch?: boolean;
83+
84+
// Convenience fields (used by findBySpec / findMany)
85+
packageName?: string;
86+
ecosystem?: string; // default: "npm"
87+
88+
// CVE identification
89+
cveId?: string;
90+
cveTag?: "disputed" | "unsupported-when-assigned" | "exclusively-hosted-service";
5991
cweId?: string;
92+
sourceIdentifier?: string;
93+
94+
// CVSS severity (mutually exclusive across versions)
95+
cvssV2Severity?: "LOW" | "MEDIUM" | "HIGH";
6096
cvssV3Severity?: "CRITICAL" | "HIGH" | "MEDIUM" | "LOW";
61-
packageName?: string;
62-
ecosystem?: string;
97+
cvssV4Severity?: "CRITICAL" | "HIGH" | "MEDIUM" | "LOW";
98+
99+
// CVSS vector strings (mutually exclusive across versions)
100+
cvssV2Metrics?: string;
101+
cvssV3Metrics?: string;
102+
cvssV4Metrics?: string;
103+
104+
// Boolean flags
105+
noRejected?: boolean;
106+
hasKev?: boolean;
107+
hasCertAlerts?: boolean;
108+
hasCertNotes?: boolean;
109+
hasOval?: boolean;
110+
111+
// Date ranges (ISO-8601, max 120-day window per pair)
112+
pubStartDate?: string;
113+
pubEndDate?: string;
114+
lastModStartDate?: string;
115+
lastModEndDate?: string;
116+
117+
// Pagination
118+
resultsPerPage?: number; // default and max: 2000
119+
startIndex?: number; // default: 0
63120
};
64121
```
65122

66-
### `findOneBySpec(spec: string): Promise<NVD[]>`
67-
Find the vulnerabilities of a given package using the NPM spec format like `packageName@version`.
123+
**Examples:**
124+
125+
```ts
126+
// Filter by CVSSv3 severity
127+
const vulns = await db.find({ keywordSearch: "express", cvssV3Severity: "CRITICAL" });
128+
129+
// Return only CVEs in the CISA Known Exploited Vulnerabilities catalog
130+
const kevVulns = await db.find({ keywordSearch: "log4j", hasKev: true });
131+
132+
// Paginate results
133+
const page2 = await db.find({ keywordSearch: "lodash", resultsPerPage: 100, startIndex: 100 });
134+
135+
// Filter by publication date range
136+
const recent = await db.find({
137+
pubStartDate: "2024-01-01T00:00:00.000Z",
138+
pubEndDate: "2024-04-30T23:59:59.000Z"
139+
});
140+
```
141+
142+
### `findByCveId(cveId: string): Promise<NVD[]>`
143+
Find a specific vulnerability by its CVE identifier.
144+
145+
```ts
146+
const vuln = await db.findByCveId("CVE-2021-44228");
147+
console.log(vuln);
148+
```
149+
150+
### `findBySpec(spec: string): Promise<NVD[]>`
151+
Find vulnerabilities of a given package using the NPM spec format `packageName@version`.
68152

69153
```ts
70-
const vulns = await db.findOneBySpec("express@4.0.0");
154+
const vulns = await db.findBySpec("express@4.0.0");
71155
console.log(vulns);
72156
```
73157

74158
### `findMany<T extends string>(specs: T[]): Promise<Record<T, NVD[]>>`
75-
Find the vulnerabilities of many packages using the spec format.
159+
Find vulnerabilities for many packages using the spec format.
76160

77-
Returns a Record where keys are equals to the provided specs.
161+
Returns a Record where keys are equal to the provided specs.
78162

79163
```ts
80164
const vulns = await db.findMany(["express@4.0.0", "lodash@4.17.0"]);

0 commit comments

Comments
 (0)