admin / SAynapse-Horizon
publicSelf Hosted Cyber Threat Intelligence Hub
SAynapse-Horizon / Synapse-Horizon / README.md
6424 B · main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | # Synapse-Horizon A modern, dark-mode-first **Cyber Threat Intelligence (CTI) dashboard** for Tier-3 SOC analysts, threat hunters, and security architects. Synapse-Horizon ingests **live** telemetry from multiple CTI sources with divergent schemas, **normalizes** each indicator into a single scannable headline, and surfaces the most critical events on an executive triage radar. Built with **React 18 + Vite + Tailwind CSS + Lucide** on the frontend and a **Node/Express ingestion backend**, packaged for a **Docker Compose** environment. ## Live data architecture Browsers cannot call these CTI APIs directly (CORS blocks them, and several require secret API keys). So the stack runs two services: ``` ┌────────────────────┐ /api ┌────────────────────────┐ HTTPS ┌─────────────┐ │ horizon (nginx) │ ───proxy───▶ │ api (Node ingestion) │ ───fetch───▶ │ Live CTI │ │ React SPA :8080 │ │ normalize + cache │ │ APIs │ └────────────────────┘ ◀── JSON ── └────────────────────────┘ └─────────────┘ ``` The backend holds the API keys (never the browser), fetches each source on demand, normalizes every record into one uniform IOC schema, and exposes `GET /api/feeds` + `POST /api/sync`. --- ## Feature overview | Area | What it does | |------|--------------| | **Global key metrics** | Active feeds (`7 / 12`-style), latest feed-pull timestamp (`DD-MMM-YYYY HH:mm:ss UTC`), and total aggregated IOCs held in state. | | **Feed Control Panel** (left) | Per-source toggles for URLhaus, ThreatFox, Feodo Tracker, PhishTank, CISA KEV, Blocklist.de, AlienVault OTX, and an RSS parser — toggling instantly filters metrics, radar and feed. | | **Lifecycle controls** | Independent **Auto-Refresh Interval** (display polling: Manual/30s/1m/5m/15m) and **Feed Pull Cadence** (ingestion: On-Demand/1h/6h/24h), plus a prominent **Manual Force Sync**. | | **Critical Priority Triage** | Max 5 highest-severity events, auto-resorting when a lifecycle completes. | | **Normalized CTI Feed** | Full-width uniform rows: UTC time · source tag · normalized headline · **View Details**. | | **Drill-down drawer** | STIX/TAXII attributes, MITRE ATT&CK mappings, raw JSON payload, and a confidence meter. | | **Loading states** | Skeletons + spinners during force sync / cadence changes. | ## SOC alerting palette Restrained by design: **Emerald** = stable/active, **Amber** = suspicious/high, **Rose/Red** = critical / active exploitation, **Sky/Slate** = informational structure. --- ## Live sources & API keys | Source | Key required | Notes | |--------|:---:|-------| | **CISA KEV** | — | Public JSON. Live out of the box. | | **Blocklist.de** | — | Public IP lists. Live out of the box. | | **RSS Parser** | — | Public advisory feeds. Live out of the box. | | **URLhaus** | `ABUSE_CH_AUTH_KEY` | Free [abuse.ch](https://auth.abuse.ch/) account. | | **ThreatFox** | `ABUSE_CH_AUTH_KEY` | Same abuse.ch key. | | **Feodo Tracker** | `ABUSE_CH_AUTH_KEY` | Same abuse.ch key. | | **AlienVault OTX** | `OTX_API_KEY` | From your OTX account. | | **PhishTank** | `PHISHTANK_APP_KEY` | Registered application key. | Copy `.env.example` → `.env` and fill in the keys you have. Sources without a key report as **"needs API key"** in the sidebar instead of failing. Set `HORIZON_DEMO=1` to serve synthetic data for any un-keyed source so the dashboard is populated out of the box. ## Running it ### Production (nginx SPA + ingestion backend) ```bash cp .env.example .env # add any API keys you have (optional) docker compose up -d --build # open http://localhost:8080 (API on http://localhost:4000/api/feeds) ``` ### Hot-reloading dev stack ```bash docker compose --profile dev up # frontend http://localhost:5190 · backend http://localhost:4000 ``` ### Local (no Docker) ```bash # terminal 1 — ingestion backend cd backend && npm install && npm start # http://localhost:4000 # terminal 2 — frontend (Vite proxies /api → :4000) npm install && npm run dev # http://localhost:5190 npm run build # emits ./dist ``` --- ## Architecture ``` backend/ # Node/Express ingestion service ├── src/server.js # routes, in-memory cache, background warm-up sync ├── src/normalize.js # IOC contract + fetch/timeout helpers + severity model └── src/sources/ ├── index.js # registry + concurrent, failure-isolated orchestration ├── cisakev.js blocklistde.js rss.js # no-key live sources ├── urlhaus.js threatfox.js feodo.js # abuse.ch (Auth-Key) ├── otx.js phishtank.js # OTX / PhishTank (keys) └── demo.js # synthetic fallback (HORIZON_DEMO=1) src/ # React frontend ├── App.jsx # layout shell + error banner ├── api/client.js # GET /api/feeds · POST /api/sync ├── hooks/useFeeds.js # single source of truth: toggles, store, cadences, lifecycle ├── data/sources.js # source registry + refresh/cadence option sets ├── utils/{format,theme}.js # UTC formatting · severity/accent/confidence styling └── components/ ├── Header.jsx Sidebar.jsx MetricsRow.jsx ├── CriticalTriagePanel.jsx CTIFeed.jsx DetailsDrawer.jsx └── ToggleSwitch.jsx ``` ### Data normalization Each source fetcher pulls its native schema live and compresses every record into one uniform IOC object (`backend/src/normalize.js → makeIoc`): ```js { id, source, detectedAt, ingestedAt, severity, category, indicator, indicatorType, target, confidence, mitre[], headline, raw, stix } ``` The UI only ever consumes this normalized shape, so URLhaus URLs, ThreatFox C2 IPs, and CISA KEV CVEs all render through the same components. Fetch failures are isolated per source — one API being down never sinks the rest of the pull. |