UNPKG

mcp-cve-intelligence-server-lite-test

Version:

Lite Model Context Protocol server for comprehensive CVE intelligence gathering with multi-source exploit discovery, designed for security professionals and cybersecurity researchers - Alpha Release

219 lines 8.64 kB
import { BaseCVESourceImplementation } from './base.js'; import { normalizeDescriptions } from '../utils/cve-utils.js'; import { safeString, safeNumber, isNonEmptyArray } from '../utils/validation.js'; // Generic implementation for unknown source types export class GenericSourceImplementation extends BaseCVESourceImplementation { buildSearchRequest(filters) { const params = new URLSearchParams(); // Generic parameter mapping - may not work for all APIs if (filters.keyword) { params.append('q', filters.keyword); } if (filters.cveId) { params.append('cve', filters.cveId); } if (filters.cvssV3Severity) { params.append('severity', filters.cvssV3Severity); } if (filters.pubStartDate) { params.append('start_date', filters.pubStartDate); } if (filters.pubEndDate) { params.append('end_date', filters.pubEndDate); } if (filters.resultsPerPage) { params.append('limit', filters.resultsPerPage.toString()); } if (filters.startIndex) { params.append('offset', filters.startIndex.toString()); } const url = `${this.getBaseUrl()}?${params.toString()}`; return { url, options: this.getRequestOptions() }; } buildDetailsRequest(cveId) { // Generic approach - append CVE ID to base URL const url = `${this.getBaseUrl()}/${cveId}`; return { url, options: this.getRequestOptions() }; } normalizeSearchResults(data) { // Generic normalization - try to handle common response formats let cves = []; let totalResults = 0; if (Array.isArray(data)) { // Response is directly an array cves = data.map((item) => this.normalizeCVEData(item)); totalResults = data.length; } else if (data && typeof data === 'object') { // Try common property names for arrays const items = data.items || data.results || data.data || data.vulnerabilities || data.cves; if (isNonEmptyArray(items)) { cves = items.map((item) => this.normalizeCVEData(item)); totalResults = safeNumber(data.total ?? data.totalResults ?? data.count, items.length); } else { // Single object response const cve = this.normalizeCVEData(data); if (cve.id !== 'unknown') { cves = [cve]; totalResults = 1; } } } return { cves, totalResults, startIndex: 0, resultsPerPage: cves.length, format: 'Generic', version: '1.0', timestamp: new Date().toISOString(), }; } normalizeCVEData(data) { const item = data; // Try to extract CVE data from common property names with proper type handling const id = safeString(item.id ?? item.cve_id ?? item.cveId ?? item.identifier, 'unknown'); const published = safeString(item.published ?? item.published_at ?? item.publishedDate ?? item.date, new Date().toISOString()); const lastModified = safeString(item.lastModified ?? item.last_modified ?? item.updated_at ?? item.modified, published); const description = safeString(item.description ?? item.summary ?? item.title, 'No description found'); const normalizedReferences = this.normalizeGenericReferences(item); return { id, sourceIdentifier: this.config.name || 'generic', published, lastModified, vulnStatus: this.normalizeStatus(safeString(item.status ?? item.state, 'PUBLISHED')), cveTags: Array.isArray(item.cveTags) ? item.cveTags : Array.isArray(item.tags) ? item.tags : [], descriptions: normalizeDescriptions([{ lang: 'en', value: description, }]), metrics: this.normalizeGenericMetrics(item), weaknesses: this.normalizeGenericWeaknesses(item), configurations: [], references: normalizedReferences, // Calculate exploit indicators during normalization exploitIndicators: this.calculateExploitIndicators(normalizedReferences), dataSource: { name: this.config.name || 'generic', version: '1.0', lastUpdated: new Date().toISOString(), url: this.getBaseUrl(), }, processingInfo: { extractedAt: new Date().toISOString(), normalizedBy: 'generic_source', rawDataAvailable: true, }, }; } normalizeStatus(status) { if (!status) { return 'PUBLISHED'; } const statusLower = status.toLowerCase(); if (statusLower.includes('publish') || statusLower === 'active') { return 'PUBLISHED'; } if (statusLower.includes('reject') || statusLower === 'withdrawn') { return 'REJECTED'; } if (statusLower.includes('reserve') || statusLower === 'draft') { return 'RESERVED'; } return 'PUBLISHED'; } normalizeGenericMetrics(item) { // Try to extract CVSS information const cvss = item.cvss || item.cvssV3 || item.cvss_v3 || item.metrics; if (!cvss) { return undefined; } // Type-safe property access const cvssData = cvss; const score = safeNumber(cvssData.score ?? cvssData.baseScore ?? cvssData.base_score, 0); const severity = safeString(cvssData.severity ?? cvssData.baseSeverity ?? cvssData.base_severity, 'UNKNOWN'); const vectorString = safeString(cvssData.vectorString ?? cvssData.vector_string ?? cvssData.vector, ''); return { cvssMetricV31: [{ source: this.config.name || 'generic', type: 'Primary', cvssData: { version: '3.1', vectorString, baseScore: score, baseSeverity: severity.toUpperCase(), attackVector: 'UNKNOWN', attackComplexity: 'UNKNOWN', privilegesRequired: 'UNKNOWN', userInteraction: 'UNKNOWN', scope: 'UNKNOWN', confidentialityImpact: 'UNKNOWN', integrityImpact: 'UNKNOWN', availabilityImpact: 'UNKNOWN', }, }], }; } normalizeGenericWeaknesses(item) { const weaknesses = item.weaknesses ?? item.cwe ?? item.cwes ?? item.cwe_ids ?? []; if (!isNonEmptyArray(weaknesses)) { return []; } return weaknesses.map(weakness => ({ source: this.config.name || 'generic', type: 'Primary', description: [{ lang: 'en', value: typeof weakness === 'string' ? weakness : safeString(weakness.value ?? weakness.description, 'Unknown weakness'), }], })); } normalizeGenericReferences(item) { const references = item.references ?? item.links ?? item.urls ?? []; if (!isNonEmptyArray(references)) { return []; } return references.map(ref => ({ url: typeof ref === 'string' ? ref : safeString(ref.url ?? ref.link, ''), source: this.config.name || 'generic', tags: Array.isArray(ref.tags) ? ref.tags : [], name: safeString(ref.name ?? ref.title) || undefined, refsource: safeString(ref.refsource ?? ref.source, 'MISC'), })); } getRequestOptions() { const headers = { 'Accept': 'application/json', 'User-Agent': this.getUserAgent(), ...this.getAuthHeaders(), }; return { headers, timeout: this.getTimeout(), }; } } //# sourceMappingURL=generic.js.map