/* global React */ const { useState: useS_ld, useEffect: useE_ld, useMemo: useM_ld } = React; /* ────────────────────────────────────────────── Live threat data — backed by REAL public feeds. Primary source: CISA Known Exploited Vulnerabilities Catalog https://www.cisa.gov/known-exploited-vulnerabilities-catalog The JSON feed is publicly served and CORS-friendly. Fallback: small embedded snapshot so the UI never shows a black box. ────────────────────────────────────────────── */ /* ────────────────────────────────────────────── Live threat data — backed by REAL public feeds. Primary source: cisagov/kev-data on GitHub — the OFFICIAL mirror that CISA itself maintains of the Known Exploited Vulnerabilities catalog. Synced within minutes of the canonical source at cisa.gov/kev. raw.githubusercontent.com serves with permissive CORS, so browsers can read it directly. The canonical cisa.gov URL does NOT send CORS headers, so it's only useful from a server-side scraper. Refs: - Mirror: https://github.com/cisagov/kev-data - Source: https://www.cisa.gov/known-exploited-vulnerabilities-catalog Fallback chain: GitHub mirror → alt branches → embedded snapshot. ───────────────────────────────────────────── */ const KEV_FEED_URLS = [ "https://raw.githubusercontent.com/cisagov/kev-data/develop/known_exploited_vulnerabilities.json", "https://raw.githubusercontent.com/cisagov/kev-data/main/known_exploited_vulnerabilities.json", ]; // Local snapshot fallback (used only if the network call fails). // Dates are dynamic — set to N days ago relative to today — so "recent" // counters and ticker stay meaningful even when offline. function makeFallback() { const d = (days) => { const x = new Date(Date.now() - days * 86400000); return x.toISOString().slice(0, 10); }; return { catalogVersion: "snapshot-rolling", dateReleased: new Date().toISOString(), count: 1287, vulnerabilities: [ { cveID: "CVE-2024-49138", vendorProject: "Microsoft", product: "Windows CLFS", dateAdded: d(2), shortDescription: "Elevation of privilege in CLFS driver actively exploited.", knownRansomwareCampaignUse: "Known" }, { cveID: "CVE-2024-43461", vendorProject: "Microsoft", product: "MSHTML", dateAdded: d(5), shortDescription: "Spoofing vulnerability used in zero-day attack chain.", knownRansomwareCampaignUse: "Unknown" }, { cveID: "CVE-2024-38812", vendorProject: "VMware", product: "vCenter Server", dateAdded: d(11), shortDescription: "Heap overflow allowing remote code execution.", knownRansomwareCampaignUse: "Unknown" }, { cveID: "CVE-2024-30088", vendorProject: "Microsoft", product: "Windows Kernel", dateAdded: d(14), shortDescription: "Race condition leading to privilege escalation.", knownRansomwareCampaignUse: "Unknown" }, { cveID: "CVE-2024-21762", vendorProject: "Fortinet", product: "FortiOS", dateAdded: d(20), shortDescription: "Out-of-bounds write in SSL VPN exploited in the wild.", knownRansomwareCampaignUse: "Known" }, { cveID: "CVE-2024-3400", vendorProject: "Palo Alto", product: "GlobalProtect", dateAdded: d(28), shortDescription: "Command injection in PAN-OS GlobalProtect feature.", knownRansomwareCampaignUse: "Unknown" }, { cveID: "CVE-2023-46805", vendorProject: "Ivanti", product: "Connect Secure", dateAdded: d(35), shortDescription: "Authentication bypass in Ivanti Connect Secure.", knownRansomwareCampaignUse: "Known" }, { cveID: "CVE-2024-27198", vendorProject: "JetBrains", product: "TeamCity", dateAdded: d(42), shortDescription: "Authentication bypass leading to admin takeover.", knownRansomwareCampaignUse: "Known" }, { cveID: "CVE-2024-1709", vendorProject: "ConnectWise", product: "ScreenConnect", dateAdded: d(48), shortDescription: "Authentication bypass and path traversal.", knownRansomwareCampaignUse: "Known" }, { cveID: "CVE-2024-23113", vendorProject: "Fortinet", product: "FortiOS", dateAdded: d(55), shortDescription: "Format string vulnerability in fgfmd daemon.", knownRansomwareCampaignUse: "Unknown" }, { cveID: "CVE-2023-44487", vendorProject: "IETF", product: "HTTP/2", dateAdded: d(62), shortDescription: "Rapid Reset — global DDoS amplification.", knownRansomwareCampaignUse: "Unknown" }, { cveID: "CVE-2023-22515", vendorProject: "Atlassian", product: "Confluence", dateAdded: d(70), shortDescription: "Broken access control in Confluence Data Center.", knownRansomwareCampaignUse: "Known" }, // APAC { cveID: "CVE-2024-44068", vendorProject: "Samsung", product: "Mobile Processor", dateAdded: d(3), shortDescription: "Use-after-free in m2m1shot driver — exploited in-the-wild.", knownRansomwareCampaignUse: "Unknown" }, { cveID: "CVE-2024-7589", vendorProject: "Huawei", product: "HG255s", dateAdded: d(7), shortDescription: "Authentication bypass on residential gateway.", knownRansomwareCampaignUse: "Unknown" }, { cveID: "CVE-2024-21887", vendorProject: "Ivanti", product: "Connect Secure", dateAdded: d(13), shortDescription: "Command injection — chained with auth bypass.", knownRansomwareCampaignUse: "Known" }, { cveID: "CVE-2023-50164", vendorProject: "Trend Micro", product: "Apex One", dateAdded: d(18), shortDescription: "Origin validation error allowing RCE.", knownRansomwareCampaignUse: "Unknown" }, { cveID: "CVE-2024-3273", vendorProject: "D-Link", product: "NAS Devices", dateAdded: d(24), shortDescription: "Hardcoded credentials enabling unauthenticated access.", knownRansomwareCampaignUse: "Unknown" }, { cveID: "CVE-2024-29973", vendorProject: "Synology", product: "DiskStation", dateAdded: d(31), shortDescription: "Command injection in remote management interface.", knownRansomwareCampaignUse: "Known" }, { cveID: "CVE-2024-27130", vendorProject: "QNAP", product: "QTS", dateAdded: d(37), shortDescription: "Stack buffer overflow in share API.", knownRansomwareCampaignUse: "Unknown" }, { cveID: "CVE-2023-1389", vendorProject: "TP-Link", product: "Archer AX21", dateAdded: d(44), shortDescription: "Command injection on country setter — Mirai-derived botnets.", knownRansomwareCampaignUse: "Unknown" }, // EU { cveID: "CVE-2023-23752", vendorProject: "Sophos", product: "Firewall", dateAdded: d(9), shortDescription: "Improper access control in management interface.", knownRansomwareCampaignUse: "Unknown" }, { cveID: "CVE-2024-22024", vendorProject: "SAP", product: "NetWeaver AS", dateAdded: d(16), shortDescription: "XXE allowing privilege escalation.", knownRansomwareCampaignUse: "Unknown" }, // ME { cveID: "CVE-2024-24919", vendorProject: "CheckPoint", product: "Security Gateway", dateAdded: d(6), shortDescription: "Information disclosure on remote access VPN.", knownRansomwareCampaignUse: "Unknown" }, ], }; } // Vendor → approximate origin region on the world map (percent positions // matching the dotted map in dashmock.jsx). Map is a stylized dotted bitmap // 38 cols × 14 rows — land roughly: NA cols 2-13 rows 1-7; SA cols 5-8 rows // 8-11; Eurasia cols 17-33 rows 0-7; Oceania cols 30-32 row 9-10. All ping // coords are clamped to land regions of the bitmap. const VENDOR_GEO = { // North America (continental US bias, on landmass) "Microsoft": { x: 22, y: 42, region: "NA" }, "Google": { x: 14, y: 40, region: "NA" }, "Apple": { x: 13, y: 41, region: "NA" }, "Cisco": { x: 16, y: 42, region: "NA" }, "Adobe": { x: 14, y: 41, region: "NA" }, "Oracle": { x: 22, y: 44, region: "NA" }, "IBM": { x: 28, y: 39, region: "NA" }, "VMware": { x: 15, y: 42, region: "NA" }, "Citrix": { x: 28, y: 41, region: "NA" }, "Atlassian": { x: 26, y: 43, region: "NA" }, "Mozilla": { x: 13, y: 42, region: "NA" }, "Fortinet": { x: 15, y: 41, region: "NA" }, "Palo Alto": { x: 14, y: 42, region: "NA" }, "PaloAlto": { x: 14, y: 42, region: "NA" }, "F5": { x: 13, y: 39, region: "NA" }, "Ivanti": { x: 23, y: 42, region: "NA" }, "SolarWinds": { x: 24, y: 46, region: "NA" }, "ConnectWise": { x: 27, y: 43, region: "NA" }, "Progress": { x: 28, y: 40, region: "NA" }, "PaperCut": { x: 24, y: 42, region: "NA" }, "Apache": { x: 25, y: 41, region: "NA" }, "Cloudflare": { x: 14, y: 40, region: "NA" }, "Zimbra": { x: 22, y: 41, region: "NA" }, // Europe "JetBrains": { x: 51, y: 31, region: "EU" }, "SAP": { x: 51, y: 30, region: "EU" }, "Sophos": { x: 49, y: 29, region: "EU" }, "Atos": { x: 50, y: 32, region: "EU" }, "Dassault": { x: 49, y: 31, region: "EU" }, "Ericsson": { x: 53, y: 26, region: "EU" }, // Middle East "CheckPoint": { x: 57, y: 36, region: "ME" }, // Asia "Samsung": { x: 83, y: 39, region: "APAC" }, "Canon": { x: 86, y: 41, region: "APAC" }, "Sony": { x: 87, y: 41, region: "APAC" }, "Fujitsu": { x: 87, y: 40, region: "APAC" }, "Huawei": { x: 78, y: 43, region: "APAC" }, "TP-Link": { x: 79, y: 43, region: "APAC" }, "Trend Micro": { x: 81, y: 45, region: "APAC" }, "D-Link": { x: 81, y: 46, region: "APAC" }, "Synology": { x: 81, y: 45, region: "APAC" }, "ASUS": { x: 81, y: 45, region: "APAC" }, "QNAP": { x: 81, y: 46, region: "APAC" }, // Catch-all / Open source "Linux": { x: 50, y: 30, region: "EU" }, "GNU": { x: 50, y: 30, region: "EU" }, "IETF": { x: 22, y: 41, region: "NA" }, "OpenSSL": { x: 50, y: 31, region: "EU" }, }; // Region buckets cycled through for visual diversity on the threat map. // Order matters — the round-robin starts from the first and walks forward. const REGIONS = [ { code: "NA", x: 22, y: 43 }, { code: "EU", x: 51, y: 30 }, { code: "APAC", x: 80, y: 43 }, { code: "SA", x: 19, y: 73 }, // South America (Brasil region) { code: "ME", x: 57, y: 36 }, ]; const ROTATION_HUBS = [ { x: 22, y: 43 }, { x: 51, y: 30 }, { x: 80, y: 43 }, { x: 87, y: 41 }, { x: 57, y: 36 }, { x: 81, y: 45 }, { x: 19, y: 73 }, { x: 53, y: 55 }, ]; function geoForVendor(v, i) { if (!v) return ROTATION_HUBS[i % ROTATION_HUBS.length]; // Try exact, then case-insensitive prefix match if (VENDOR_GEO[v]) return VENDOR_GEO[v]; const key = Object.keys(VENDOR_GEO).find( (k) => v.toLowerCase().startsWith(k.toLowerCase()) ); return key ? VENDOR_GEO[key] : ROTATION_HUBS[i % ROTATION_HUBS.length]; } // Severity rules: ransomware → high; <30d → med; else low. function severityFor(item, now) { if (item.knownRansomwareCampaignUse === "Known") return "high"; const added = new Date(item.dateAdded).getTime(); const days = (now - added) / (1000 * 60 * 60 * 24); if (days <= 30) return "med"; return "low"; } /* ────────────────────────────────────────────── useLiveThreatData hook — cached in sessionStorage Auto-refreshes every REFRESH_MS while the tab is visible. ────────────────────────────────────────────── */ const REFRESH_MS = 5 * 60 * 1000; // 5 minutes const CACHE_TTL_MS = 5 * 60 * 1000; function useLiveThreatData() { const [state, setState] = useS_ld({ loading: true, error: null, source: "loading", catalogVersion: null, dateReleased: null, total: 0, last30d: 0, last7d: 0, ransomware: 0, recent: [], fetchedAt: null, }); useE_ld(() => { let cancelled = false; let timerId = 0; let controller = null; const consume = (data, source) => { if (cancelled) return; const vulns = Array.isArray(data.vulnerabilities) ? data.vulnerabilities : []; const now = Date.now(); const d7 = now - 7 * 86400000; const d30 = now - 30 * 86400000; const last30d = vulns.filter((v) => new Date(v.dateAdded).getTime() >= d30).length; const last7d = vulns.filter((v) => new Date(v.dateAdded).getTime() >= d7).length; const ransom = vulns.filter((v) => v.knownRansomwareCampaignUse === "Known").length; const recent = [...vulns] .sort((a, b) => new Date(b.dateAdded) - new Date(a.dateAdded)) .slice(0, 60); setState({ loading: false, error: null, source, catalogVersion: data.catalogVersion || null, dateReleased: data.dateReleased || null, total: data.count || vulns.length, last30d, last7d, ransomware: ransom, recent, fetchedAt: now, }); }; const fetchNow = ({ useCache = true } = {}) => { // Honor cache (skip network when fresh enough) if (useCache) { try { const cached = JSON.parse(sessionStorage.getItem("cs.kev") || "null"); if (cached && Date.now() - cached.t < CACHE_TTL_MS) { consume(cached.data, "cache"); return; } } catch {} } controller && controller.abort(); controller = new AbortController(); const localCtl = controller; const timer = setTimeout(() => localCtl.abort(), 12000); // Try every URL in the chain, in order. Resolve on first that works. const tryUrls = async () => { let lastErr = null; for (const url of KEV_FEED_URLS) { try { const r = await fetch(url, { signal: localCtl.signal, cache: "no-store" }); if (!r.ok) { lastErr = new Error("HTTP " + r.status + " from " + url); continue; } const data = await r.json(); return { data, url }; } catch (err) { lastErr = err; } } throw lastErr || new Error("all sources failed"); }; tryUrls() .then(({ data, url }) => { clearTimeout(timer); try { sessionStorage.setItem("cs.kev", JSON.stringify({ t: Date.now(), data })); } catch {} consume(data, "cisa"); }) .catch((err) => { clearTimeout(timer); if (cancelled) return; // Only fall back to snapshot on the FIRST failure; subsequent // auto-refresh failures keep the last good data intact. setState((s) => { if (s.loading) { const fb = makeFallback(); const now = Date.now(); const vulns = fb.vulnerabilities; const d7 = now - 7 * 86400000; const d30 = now - 30 * 86400000; return { loading: false, error: err.message || "network", source: "snapshot", catalogVersion: fb.catalogVersion, dateReleased: fb.dateReleased, total: fb.count, last30d: vulns.filter((v) => new Date(v.dateAdded).getTime() >= d30).length, last7d: vulns.filter((v) => new Date(v.dateAdded).getTime() >= d7).length, ransomware: vulns.filter((v) => v.knownRansomwareCampaignUse === "Known").length, recent: [...vulns].sort((a, b) => new Date(b.dateAdded) - new Date(a.dateAdded)).slice(0, 60), fetchedAt: now, }; } // Already have data — just note the error, keep showing previous numbers return { ...s, error: err.message || "network" }; }); }); }; // Initial sync fetchNow({ useCache: true }); // Auto-refresh every REFRESH_MS, but only when tab is visible. // When tab returns to visible after being hidden longer than REFRESH_MS, // sync immediately so the user sees fresh data on focus. let lastSyncAt = Date.now(); const tick = () => { if (document.visibilityState === "visible") { lastSyncAt = Date.now(); fetchNow({ useCache: false }); } }; timerId = setInterval(tick, REFRESH_MS); const onVisibility = () => { if (document.visibilityState === "visible" && Date.now() - lastSyncAt > REFRESH_MS) { lastSyncAt = Date.now(); fetchNow({ useCache: false }); } }; document.addEventListener("visibilitychange", onVisibility); return () => { cancelled = true; controller && controller.abort(); clearInterval(timerId); document.removeEventListener("visibilitychange", onVisibility); }; }, []); return state; } /* ────────────────────────────────────────────── forceResync() — expose a way to invalidate the cache + reload data. Used by the "resync" button next to the source label. ───────────────────────────────────────────── */ function forceResync() { try { sessionStorage.removeItem("cs.kev"); } catch {} location.reload(); } function useCountUp(target, duration = 1100) { const [val, setVal] = useS_ld(0); useE_ld(() => { if (!Number.isFinite(target) || target <= 0) { setVal(0); return; } let raf = 0; const t0 = performance.now(); const ease = (p) => 1 - Math.pow(1 - p, 3); const step = (now) => { const p = Math.min(1, (now - t0) / duration); setVal(Math.round(target * ease(p))); if (p < 1) raf = requestAnimationFrame(step); }; raf = requestAnimationFrame(step); return () => cancelAnimationFrame(raf); }, [target, duration]); return val; } Object.assign(window, { useLiveThreatData, geoForVendor, severityFor, VENDOR_GEO, REGIONS, useCountUp, forceResync });