import { describe, expect, it, vi } from 'vitest'; import { NvdCveClient, NvdCveClientError, parseNvdCveResponse } from '../../server/cve/nvd-cve-client'; const payload = { version: '2.0', vulnerabilities: [{ cve: { id: 'CVE-2012-3037', sourceIdentifier: 'nvd@nist.gov', published: '2012-08-25T10:55:01.000', lastModified: '2025-04-11T00:51:21.963', vulnStatus: 'Deferred', descriptions: [{ lang: 'en', value: 'Synthetic vulnerability description.' }], metrics: { cvssMetricV31: [{ source: 'nvd@nist.gov', type: 'Primary', exploitabilityScore: 3.9, impactScore: 5.9, cvssData: { version: '3.1', vectorString: 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H', baseScore: 9.8, baseSeverity: 'CRITICAL' } }], cvssMetricV2: [{ source: 'nvd@nist.gov', type: 'Primary', baseSeverity: 'MEDIUM', exploitabilityScore: 8.6, impactScore: 2.9, cvssData: { version: '2.0', vectorString: 'AV:N/AC:M/Au:N/C:P/I:N/A:N', baseScore: 4.3 } }] }, weaknesses: [{ source: 'nvd@nist.gov', type: 'Primary', description: [{ lang: 'en', value: 'CWE-119' }] }], references: [{ url: 'https://vendor.example/advisory', source: 'nvd@nist.gov', tags: ['Vendor Advisory', 'Patch'] }], configurations: [{ operator: 'AND', nodes: [ { cpeMatch: [{ vulnerable: true, criteria: 'cpe:2.3:a:vendor:product:*:*:*:*:*:*:*:*', versionEndExcluding: '2.0' }] }, { cpeMatch: [{ vulnerable: false, criteria: 'cpe:2.3:h:vendor:device:*:*:*:*:*:*:*:*' }] } ] }], cisaRequiredAction: 'Apply vendor guidance.' } }] }; describe('NVD CVE enrichment', () => { it('normalizes the bounded NVD 2.0 response into shared CVE knowledge', () => { const record = parseNvdCveResponse(payload, 'CVE-2012-3037', '2026-09-10T08:00:00.000Z'); expect(record).toMatchObject({ cveId: 'CVE-2012-3037', source: 'nvd', description: 'Synthetic vulnerability description.', metrics: [ { version: '3.1', baseScore: 9.8, baseSeverity: 'CRITICAL' }, { version: '2.0', baseScore: 4.3, baseSeverity: 'MEDIUM' } ], weaknesses: [{ id: 'CWE-119' }], references: [{ url: 'https://vendor.example/advisory', tags: ['Vendor Advisory', 'Patch'] }], affectedConfigurations: [{ operator: 'AND', vulnerableMatches: [{ criteria: 'cpe:2.3:a:vendor:product:*:*:*:*:*:*:*:*', versionEndExcluding: '2.0' }], runningOnWith: [{ criteria: 'cpe:2.3:h:vendor:device:*:*:*:*:*:*:*:*' }] }], attributes: { cisaRequiredAction: 'Apply vendor guidance.' } }); }); it('calls only the fixed NVD endpoint with an encoded exact CVE and optional API key', async () => { const fetcher = vi.fn().mockResolvedValue(new Response(JSON.stringify(payload), { status: 200, headers: { 'Content-Type': 'application/json' } })); const client = new NvdCveClient({ fetcher, apiKey: 'test-key', now: () => new Date('2026-09-10T08:00:00.000Z') }); await expect(client.fetchCve('cve-2012-3037')).resolves.toMatchObject({ cveId: 'CVE-2012-3037' }); const url = fetcher.mock.calls[0][0] as URL; expect(url.origin + url.pathname).toBe('https://services.nvd.nist.gov/rest/json/cves/2.0'); expect(url.searchParams.get('cveId')).toBe('CVE-2012-3037'); expect(new Headers(fetcher.mock.calls[0][1]?.headers).get('apiKey')).toBe('test-key'); }); it('rejects invalid identifiers before making a network request', async () => { const fetcher = vi.fn(); const client = new NvdCveClient({ fetcher }); await expect(client.fetchCve('not-a-cve')).rejects.toMatchObject({ code: 'invalid_cve_id' } satisfies Partial); expect(fetcher).not.toHaveBeenCalled(); }); });