|
1 | 1 | # NVD |
2 | 2 |
|
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). |
4 | 4 |
|
5 | 5 | ## Implementation Notes |
6 | 6 |
|
7 | 7 | 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). |
8 | 8 |
|
9 | 9 | ### Search Parameters |
10 | 10 |
|
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: |
12 | 12 |
|
13 | 13 | 1. The CPE format for npm packages is not standardized in NVD |
14 | 14 | 2. Attempted CPE patterns (like `cpe:2.3:a:*:package-name:*:*:*:*:*:node.js:*:*`) resulted in 404 errors |
15 | 15 | 3. Keyword search provides more flexible results for JavaScript/NPM packages |
16 | 16 |
|
17 | 17 | The implementation might be enhanced in the future if NVD provides clearer guidelines for CPE matching of npm packages. |
18 | 18 |
|
| 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 | + |
19 | 29 | ## Format |
20 | 30 |
|
21 | 31 | The NVD API returns detailed vulnerability information. |
@@ -46,35 +56,109 @@ const db = new vulnera.Database.NVD({ |
46 | 56 |
|
47 | 57 | ```ts |
48 | 58 | 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; |
50 | 70 | } |
51 | 71 | ``` |
52 | 72 |
|
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. |
55 | 77 |
|
56 | 78 | ```ts |
57 | 79 | export type NVDApiParameter = { |
| 80 | + // Keyword search |
58 | 81 | 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"; |
59 | 91 | cweId?: string; |
| 92 | + sourceIdentifier?: string; |
| 93 | + |
| 94 | + // CVSS severity (mutually exclusive across versions) |
| 95 | + cvssV2Severity?: "LOW" | "MEDIUM" | "HIGH"; |
60 | 96 | 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 |
63 | 120 | }; |
64 | 121 | ``` |
65 | 122 |
|
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`. |
68 | 152 |
|
69 | 153 | ```ts |
70 | | -const vulns = await db.findOneBySpec("express@4.0.0"); |
| 154 | +const vulns = await db.findBySpec("express@4.0.0"); |
71 | 155 | console.log(vulns); |
72 | 156 | ``` |
73 | 157 |
|
74 | 158 | ### `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. |
76 | 160 |
|
77 | | -Returns a Record where keys are equals to the provided specs. |
| 161 | +Returns a Record where keys are equal to the provided specs. |
78 | 162 |
|
79 | 163 | ```ts |
80 | 164 | const vulns = await db.findMany(["express@4.0.0", "lodash@4.17.0"]); |
|
0 commit comments