Files
wehub-resource-sync 9b395f5cc3
E2E Headed Chrome / e2e-headed (macos-15) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (ubuntu-latest) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (windows-latest) (push) Has been cancelled
CI / build (macos-latest) (push) Has been cancelled
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
CI / unit-test (push) Has been cancelled
CI / bun-test (push) Has been cancelled
CI / adapter-test (push) Has been cancelled
CI / smoke-test (macos-latest) (push) Has been cancelled
CI / smoke-test (ubuntu-latest) (push) Has been cancelled
Security Audit / audit (push) Has been cancelled
Build Chrome Extension / build (push) Has been cancelled
Trigger Website Rebuild (Docs Updated) / dispatch (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:39:48 +08:00

122 lines
4.9 KiB
JavaScript

// nvd cve — fetch a single CVE from the NIST National Vulnerability Database.
//
// Hits the CVE API 2.0 (`services.nvd.nist.gov/rest/json/cves/2.0?cveId=…`).
// Returns the agent-useful projection: id, published / last-modified dates,
// vuln status, English description, CVSS v3.1 base score / severity / vector,
// CWE id(s), CISA KEV flag.
import { cli, Strategy } from '@jackwener/opencli/registry';
import { ArgumentError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';
const NVD_BASE = 'https://services.nvd.nist.gov/rest/json/cves/2.0';
const UA = 'opencli-nvd-adapter (+https://github.com/jackwener/opencli)';
const CVE_ID = /^CVE-\d{4}-\d{4,}$/i;
function requireCveId(value) {
const s = String(value ?? '').trim().toUpperCase();
if (!s) throw new ArgumentError('nvd CVE id is required (e.g. "CVE-2021-44228")');
if (!CVE_ID.test(s)) {
throw new ArgumentError(
`nvd CVE id "${value}" is not a valid CVE identifier`,
'Expected the form "CVE-YYYY-N..." with at least 4 sequence digits.',
);
}
return s;
}
function pickEnglishDescription(descriptions) {
if (!Array.isArray(descriptions)) return '';
const en = descriptions.find((d) => d?.lang === 'en');
return String(en?.value ?? descriptions[0]?.value ?? '').trim();
}
function pickPrimaryCvss(metrics) {
if (!metrics || typeof metrics !== 'object') return null;
const candidates = [
...(Array.isArray(metrics.cvssMetricV31) ? metrics.cvssMetricV31 : []),
...(Array.isArray(metrics.cvssMetricV30) ? metrics.cvssMetricV30 : []),
...(Array.isArray(metrics.cvssMetricV2) ? metrics.cvssMetricV2 : []),
];
return candidates.find((m) => m?.type === 'Primary') || candidates[0] || null;
}
function joinCwes(weaknesses) {
if (!Array.isArray(weaknesses)) return '';
const ids = new Set();
for (const w of weaknesses) {
for (const desc of w?.description ?? []) {
if (desc?.value) ids.add(String(desc.value));
}
}
return [...ids].join(', ');
}
cli({
site: 'nvd',
name: 'cve',
access: 'read',
description: 'NIST NVD CVE detail (description, CVSS, CWE, KEV flag)',
domain: 'services.nvd.nist.gov',
strategy: Strategy.PUBLIC,
browser: false,
args: [
{ name: 'id', positional: true, required: true, help: 'CVE identifier (e.g. "CVE-2021-44228")' },
],
columns: [
'id', 'published', 'lastModified', 'vulnStatus', 'baseScore', 'severity',
'attackVector', 'cwe', 'kevAdded', 'description', 'url',
],
func: async (args) => {
const id = requireCveId(args.id);
const url = `${NVD_BASE}?cveId=${encodeURIComponent(id)}`;
let resp;
try {
resp = await fetch(url, { headers: { 'user-agent': UA, accept: 'application/json' } });
}
catch (err) {
throw new CommandExecutionError(`nvd cve request failed: ${err?.message ?? err}`);
}
if (resp.status === 403) {
throw new CommandExecutionError(
'nvd cve returned HTTP 403',
'NVD enforces aggressive rate limits without an API key. Wait, then retry or set NVD_API_KEY (not yet wired).',
);
}
if (resp.status === 429) {
throw new CommandExecutionError(
'nvd cve returned HTTP 429 (rate limited)',
'NVD throttles unauthenticated traffic; wait several seconds before retry.',
);
}
if (!resp.ok) {
throw new CommandExecutionError(`nvd cve returned HTTP ${resp.status}`);
}
let body;
try {
body = await resp.json();
}
catch (err) {
throw new CommandExecutionError(`nvd cve returned malformed JSON: ${err?.message ?? err}`);
}
const list = Array.isArray(body?.vulnerabilities) ? body.vulnerabilities : [];
const cve = list[0]?.cve;
if (!cve || !cve.id) {
throw new EmptyResultError('nvd cve', `NVD has no record for "${id}".`);
}
const cvss = pickPrimaryCvss(cve.metrics);
const cvssData = cvss?.cvssData ?? {};
return [{
id: String(cve.id),
published: String(cve.published ?? '').slice(0, 10),
lastModified: String(cve.lastModified ?? '').slice(0, 10),
vulnStatus: String(cve.vulnStatus ?? ''),
baseScore: cvssData.baseScore != null ? Number(cvssData.baseScore) : null,
severity: String(cvssData.baseSeverity ?? cvss?.baseSeverity ?? ''),
attackVector: String(cvssData.attackVector ?? ''),
cwe: joinCwes(cve.weaknesses),
kevAdded: cve.cisaExploitAdd ? String(cve.cisaExploitAdd).slice(0, 10) : '',
description: pickEnglishDescription(cve.descriptions),
url: `https://nvd.nist.gov/vuln/detail/${cve.id}`,
}];
},
});