SentinelTI Documentation
Real-time threat intelligence. ML-scored. MITRE-mapped. SIEM-ready.
Overview
SentinelTI is a production-ready, multi-tenant Threat Intelligence Platform (TIP) that aggregates Indicators of Compromise (IOCs) from open-source threat feeds, enriches them through a 5-layer intelligence pipeline, scores them with a machine learning ensemble, maps them to MITRE ATT&CK, and pushes actionable alerts to your SIEM — all inside a modern dashboard.
Built as a serious open-source alternative to commercial TIPs like ThreatConnect and Anomali.
Getting Started
SentinelTI is a hosted platform — there's nothing to install or run locally. Three steps from zero to your first scored indicator:
1. Create a free workspace
No card required. Register with a work email — you get an isolated tenant instantly, on the Free plan (50 IOCs/fetch, 500 stored).
2. Fetch your first threat feeds
Click FETCH in the dashboard's command bar. SentinelTI pulls from 9 OSINT feeds in parallel — enrichment and ML scoring run automatically in the background, and the Offense Queue updates in real time.
3. Explore the score
Open any HIGH-risk indicator and check the SHAP Explainability and MITRE ATT&CK pages — every score ships with the evidence behind it, not just a verdict.
README.md — this guide covers the hosted product at sentinelti-product.vercel.app.Architecture
┌──────────────────────────────────────────────────────────────┐ │ SENTINELTI PLATFORM │ │ │ │ ┌────────────────────────────────────────────────────────┐ │ │ │ Next.js 14 Frontend │ │ │ │ /dashboard /intel /lookup /scoring /shap /mitre │ │ │ │ /alerts /siem /analytics /integrations │ │ │ └─────────────────────────┬──────────────────────────────┘ │ │ │ REST API (Bearer token) │ │ ┌─────────────────────────▼──────────────────────────────┐ │ │ │ FastAPI Backend │ │ │ │ Auth · Feeds · Enrichment · ML · MITRE │ │ │ │ Alerts · SIEM · Export · Import │ │ │ └─────────────────────────┬──────────────────────────────┘ │ │ │ │ │ ┌─────────────────────────▼──────────────────────────────┐ │ │ │ MongoDB — indicators · users · tenants · alerts │ │ │ └────────────────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────┘ External feeds: Abuse.ch · CINS Army · OTX · Feodo · ET Enrichment APIs: VirusTotal · AbuseIPDB · ipinfo · GreyNoise · URLhaus SIEM targets: Splunk HEC · Elasticsearch
Tech Stack
| Layer | Technology |
|---|---|
| Framework | Next.js 14 (App Router) |
| Language | TypeScript |
| Styling | Tailwind CSS |
| Charts | Recharts |
| Auth | JWT · sessionStorage + Secure cookie |
| Deploy | Vercel / Railway |
| Layer | Technology |
|---|---|
| Framework | FastAPI (Python) |
| Database | MongoDB 6 (PyMongo) |
| Auth | python-jose + bcrypt |
| ML | scikit-learn · XGBoost · SHAP |
| Brevo API / Resend API (sentinel-mailer microservice) | |
| Deploy | Docker · Railway |
Offense Queue
/dashboardThe main triage view. Shows all active IOCs sorted by ML risk score with live stats, filters, and one-click enrichment controls.
- ·Live UTC + IST clock updated every second
- ·KPI strip — TOTAL · HIGH · MEDIUM · LOW · ENRICHED · ML SCORED
- ·Command bar: FETCH · SCORE · CLEAR · REFRESH · EMAIL REPORT
- ·IOC table with 12 columns: IP, severity, risk score, feed source, domain, domain risk, confidence %, abuse reports, country, ISP, malware family, last seen
- ·Filters: full-text search, risk tier toggles, ENRICHED / PENDING status, sort by score / abuse reports / confidence
- ·Inline error banners with Retry on API failure
Threat Intel
/intelFull paginated IOC table with advanced search and per-indicator detail panel.
- ·Paginated table — up to 200 IOCs per page
- ·Search by IP, domain, source, country, malware family
- ·Click any row to open a full detail panel
- ·Detail panel: all enrichment data, MITRE tactic badges, domain intel cards, SHAP score bar
- ·Export individual IOC as JSON
IP Lookup
/lookupDeep-dive intelligence report for any IPv4 address. Works for IPs already in the database and for any live address.
- ·In-database IPs: full ML score + SHAP breakdown + all enrichment data
- ·Any IP: live PTR → GreyNoise → URLhaus → VirusTotal domain
- ·GreyNoise card: malicious / RIOT / noise-scanner / unknown classification
- ·URLhaus card: malicious URL count, recent malware URLs with status
- ·VirusTotal domain card: detection count, reputation score, categories
- ·MITRE ATT&CK tactic cards per IOC
- ·"Force fresh" toggle bypasses cache for real-time lookup
ML Risk Engine
/scoringML scoring interface showing the stacking ensemble output, score distribution charts, and high-severity offense table.
- ·Run ML scoring on all tenant IOCs with live progress bar
- ·Score distribution histogram (0.0 – 1.0 in 10 bins)
- ·Risk level distribution bar chart (HIGH / MEDIUM / LOW)
- ·High severity offense table: IP · score · RF prob · XGB prob · feeds · confidence · reports · country · ISP · domain
- ·Model architecture cards: Random Forest · XGBoost · Logistic Reg meta · 5-Fold CV
SHAP Explainability
/shapExplains every ML prediction in plain terms — which signals drove the score up or down.
- ·Global view: mean absolute SHAP bar chart across all IOCs
- ·Answers "which features matter most to the model overall"
- ·Per-IP local view: waterfall chart showing base value + per-feature contributions
- ·Direction labels: RED = pushed score up (more dangerous), BLUE = pushed score down
- ·IP search: enter any in-database IP to get its local SHAP explanation
MITRE ATT&CK
/mitreInteractive ATT&CK matrix view showing which tactics are active in your current IOC set.
- ·Tactic heatmap: count of IOCs per tactic with colour intensity
- ·Click any tactic to drill down to matching IOCs
- ·Technique-level breakdown: technique ID, name, tactic, count
- ·Total MITRE-mapped count vs total IOCs
- ·Auto-mapped on enrichment — no manual tagging needed
Analytics
/analyticsVisualisation layer across your full IOC dataset.
- ·Top countries bar chart (horizontal)
- ·Feed breakdown bar chart — IOCs per source
- ·ISP attribution table — top 10 ASNs
- ·Malware family chart (Feodo C2 data)
- ·Ingestion timeline — IOC count per hour
- ·Phase 2 coverage: MITRE mapped · domain intel · GreyNoise malicious · URLhaus hits · Feodo C2
Alert Rules
/alertsRule-based alerting engine. Define conditions and notification channels — rules fire automatically after each enrichment cycle.
- ·Create rules with: name, min risk score (slider), risk tiers, country codes, MITRE tactic
- ·Notification channels: Slack webhook · Teams webhook · PagerDuty routing key · email
- ·Rules fire after every enrichment completion
- ·Active rules list with fired count and channel badges
- ·Alert history log: last 10 fired events with IP · rule name · timestamp
SIEM Export
/siemPush enriched IOCs to Splunk or Elasticsearch, manually or automatically after enrichment.
- ·Supported targets: Splunk HTTP Event Collector (HEC) · Elasticsearch Bulk API
- ·Configure: URL · token/API key · index name · auto-push toggle · minimum tier
- ·Test connection before saving
- ·Manual push: select tier range (HIGH only / HIGH+MEDIUM / All enriched)
- ·Status panel: connected indicator · total pushed · last push timestamp · auto-push state
- ·Field mapping: indicator → src_ip, ml_score → sentinel_risk_score, ml_risk → severity, etc.
Integrations
/integrationsThree IOC import mechanisms for feeding external threat data into your tenant.
- ·S3 Bucket Import: pull CSV or NDJSON from any AWS S3 bucket (row limit up to 1000)
- ·File Upload: drag-and-drop or browse CSV / NDJSON — up to supported file size
- ·Webhook Push: unique per-tenant URL — POST a JSON array of IOCs from Splunk, QRadar, Elastic, Sentinel, XSOAR, or any script
- ·Accepted columns: indicator / ip / ioc / value · sources · risk · country · threat_type · malware_family
- ·S3 credentials sent over HTTPS to backend only — not stored client-side
Feed Sources
| Feed | IOC Type | Base Score | Signal Quality | Notes |
|---|---|---|---|---|
| Abuse.ch Feodo Tracker | C2 IPv4 | 5 | High | Botnet C2 — Emotet, QakBot, Dridex |
| CINS Army | Brute-force / scanners | 2 | Medium | Large volume, lower confidence |
| OTX AlienVault | Community pulses | 4 | High | Requires free OTX API key |
| Feodo Tracker Extended | Banking trojans | 5 | High | Malware family + C2 status tagged |
| Emerging Threats SSH | SSH scanners | 3 | Medium | Proofpoint blocklist |
| Emerging Threats Mail | Spam sources | 2 | Medium | Proofpoint blocklist |
| Emerging Threats Web | Web scanners | 3 | Medium | Proofpoint blocklist |
Enrichment Pipeline
Every IOC runs through 5 sequential enrichment stages in a background thread, isolated per tenant. The score is boosted at each stage when signals confirm malicious behaviour.
Score boosting rules
| Signal | Boost |
|---|---|
| AbuseIPDB confidence > 25 % | +3 (capped at 10) |
| VirusTotal detections > 0 | +3 (capped at 10) |
| Domain risk = HIGH | +2 (capped at 10) |
| Multi-source (2+ feeds) | Boosts ML feature weight |
Risk Score Reference
| Score | Level | Recommended action |
|---|---|---|
| 9 – 10 | HIGH | Block immediately — multi-source, high AbuseIPDB confidence, VT positive |
| 5 – 8 | MEDIUM | Investigate — flagged by 1–2 sources, enrichment suggests malicious |
| 0 – 4 | LOW | Monitor — single low-confidence source or stale report |
Model Architecture
SentinelTI uses a stacking ensemble — two independent base learners whose probability outputs are combined by a linear meta-learner. This consistently outperforms any single model on threat scoring tasks.
Base layer: Random Forest (100 trees · max_depth=8)
XGBoost (150 rounds · lr=0.05 · depth=6)
↓ predictions stacked as features
Meta layer: Linear Regressor
↓
Output: Continuous score 0.0 – 1.0 → scaled to 0 – 10
Bucketed: HIGH (≥9) · MEDIUM (5–8) · LOW (<5)Feature Engineering
| Feature | Source | Description |
|---|---|---|
| abuse_reports | AbuseIPDB | Total abuse reports filed for this IP |
| recency_hrs | AbuseIPDB | Hours since last report — lower = more recent = worse |
| confidence_pct | AbuseIPDB | Abuse confidence score 0 – 100 |
| vt_detections | VirusTotal | Number of AV engines flagging this IP |
| vt_total | VirusTotal | Total AV engines that analysed the IP |
| multi_source | Internal | 1 if IP appears in 2+ feeds, else 0 |
| attack_type_count | AbuseIPDB | Number of distinct attack categories reported |
| geo_risk | ipinfo | 1 if country in HIGH_RISK set (CN, RU, KP, IR, NG …) |
| freshness | Internal | Recency-weighted signal — higher if seen recently |
| source_score | Internal | Combined feed source score / 10 |
SHAP Explainability
SHAP (SHapley Additive exPlanations) decomposes each model prediction into per-feature contributions, so every risk score comes with a plain-language explanation of why it was assigned.
Mean absolute SHAP value per feature across all scored IOCs. Answers: "which signals matter most to the model?" Useful for validating the model is using the right features and for debugging feed quality.
Waterfall chart for a single IP. Shows the base value (average output) and how each feature pushes the score up (red) or down (blue). Answers: "why is 185.220.101.42 scored HIGH?"
MITRE Mapping Logic
Each IOC is automatically tagged with ATT&CK tactics during enrichment Stage 4. Multiple tactics can be assigned to one IOC.
| Signal | Tactic | Technique |
|---|---|---|
| Feed: Feodo / Abuse.ch | TA0011 Command and Control | T1071 App Layer Protocol |
| Feed: CINS Army | TA0043 Reconnaissance | T1595 Active Scanning |
| AbuseIPDB: SSH brute-force (cat. 18) | TA0006 Credential Access | T1110 Brute Force |
| AbuseIPDB: Web attack (cat. 21) | TA0001 Initial Access | T1190 Exploit Public-Facing App |
| AbuseIPDB: Port scan (cat. 14) | TA0043 Reconnaissance | T1046 Network Service Scanning |
| AbuseIPDB: DDoS (cat. 4) | TA0040 Impact | T1498 Network Denial of Service |
| GreyNoise: scanner | TA0007 Discovery | T1046 Network Service Scanning |
| URLhaus: malicious URL | TA0042 Resource Development | T1608 Stage Capabilities |
| VirusTotal: malware detections | TA0011 Command and Control | T1071 App Layer Protocol |
| OTX: pulse tagged phishing | TA0001 Initial Access | T1566 Phishing |
Tactic Reference
| Tactic ID | Name | Trigger in SentinelTI |
|---|---|---|
| TA0001 | Initial Access | Web attacks, phishing, exploit feeds |
| TA0006 | Credential Access | SSH brute-force reports |
| TA0007 | Discovery | GreyNoise scanner classification |
| TA0011 | Command and Control | Feodo C2, botnet IPs, VT malware |
| TA0040 | Impact | DDoS abuse category |
| TA0042 | Resource Development | URLhaus malicious URLs |
| TA0043 | Reconnaissance | CINS Army, port scan categories |
Authentication
All protected endpoints require the header Authorization: Bearer <access_token>. Tokens are issued on login and valid for 30 minutes.
SSO / SAML
MSSP-tier tenants can require single sign-on for their domain. Discovery and callback are unauthenticated (a user hasn’t logged in yet); config is admin-only. SAML assertions are explicitly rejected rather than silently unverified — only OIDC providers (Okta, Azure AD, Google Workspace) perform real ID-token verification (JWKS fetch, signature/audience/issuer checks) today.
provider: "saml" is accepted at config time for completeness but /auth/sso/callback returns 503 for it — SAML assertions are not yet verified, and this API fails closed rather than trusting an unverified assertion.Indicators
ML & SHAP
MITRE ATT&CK
Threat Actor Attribution
Measures TTP overlap between tenant IOCs and the published tradecraft of catalogued threat groups, weighted by how discriminating each technique is (widely-shared techniques like T1071 count for little; named tooling counts heavily). This is a similarity signal, not attribution — the API and UI both surface it as an evidence bundle with a qualitative band, never a confidence percentage.
overlap_band or overlap_strength without it. Bands only reach HIGH on a named-tooling match; generic C2/proxy/scanner signatures are deliberately excluded from scoring.Alerts
SIEM
TAXII / STIX
A native TAXII 2.1 server and a plain STIX 2.1 bundle endpoint, for consumers that pull rather than receive a push — firewalls (Palo Alto EDL, Fortinet), SIEMs with a native TAXII connector, and SOAR platforms. Both authenticate the same way as the Export API: a Bearer token or an ?api_key= query param.
MSSP Client Workspaces
Lets one MSSP-tier tenant manage unlimited client sub-tenants: enroll, create, list, soft-delete, and switch context into a client workspace. Switching mints a token pair whose tenant_id claim is the client’s — the entire rest of the API becomes client-scoped for free, with the parent/child relationship re-verified live on every request rather than only at token-mint time.
/export/pdf honors an optional client_branding.display_name on a client tenant and adds a “Prepared by {MSSP name}” line — set it via the display_name field on POST /mssp/clients.Audit Log
A tamper-evident, append-only record of authentication events, mutations, and reads of sensitive data (exports/pulls) — never routine paginated /indicators views, which is analytics, not audit. Every entry is chained: each stores seq, prev_hash, and entry_hash (a SHA-256 of the previous entry’s hash plus this entry’s own canonical content), per tenant. There is no update or arbitrary delete path on this collection anywhere in the codebase — the only way entries disappear is the bounded retention prune below, which checkpoints the last-deleted entry’s hash first so the surviving chain still roots in real history.
Import & Export
POST a JSON array of IOCs. Compatible with Splunk, IBM QRadar, Elastic SIEM, Microsoft Sentinel, Cortex XSOAR, or any custom script.
curl -X POST "https://sentineltibackend-production.up.railway.app/import/webhook/<your_token>" \
-H "Content-Type: application/json" \
-d '[{"indicator":"1.2.3.4","sources":"splunk-export","risk":"HIGH","country":"CN"}]'HTTP error codes
| Status | Meaning |
|---|---|
| 400 | Bad request or validation error |
| 401 | Invalid or expired token |
| 404 | Resource not found |
| 422 | Request body validation failed (Pydantic) |
| 500 | Internal server error |
All errors return: { "detail": "error message" }
Docker Compose
The easiest way to run the full stack locally — backend, frontend, and MongoDB in one command.
cd sentinel_TI_product cp backend/env.sample backend/.env # Edit backend/.env docker-compose up --build
mongo_data volume and survives container restarts.Railway
Both backend/railway.json and sentinelti-next/railway.json are preconfigured. Connect your repository in Railway, set the environment variables below, and deploy each service independently.
NEXT_PUBLIC_API_URL to the backend Railway URL before deploying the frontend.Vercel
Deploy the Next.js frontend to Vercel for the best edge performance. The backend stays on Railway or Docker.
# In the Vercel dashboard # Root directory: sentinelti-next # Framework: Next.js # Environment variable: NEXT_PUBLIC_API_URL = https://your-backend.up.railway.app
Environment Variables
| Variable | Where | Required | Description |
|---|---|---|---|
| MONGO_URI | backend | Yes | MongoDB connection string |
| JWT_SECRET | backend | Yes | Secret for signing JWT tokens — change in production |
| VIRUSTOTAL_API_KEY | backend | Recommended | VirusTotal v3 API key |
| ABUSEIPDB_API_KEY | backend | Recommended | AbuseIPDB API key |
| OTX_API_KEY | backend | Optional | AlienVault OTX API key |
| GREYNOISE_API_KEY | backend | Optional | GreyNoise Community key |
| BREVO_API_KEY | mailer | Recommended | Brevo API key — no domain verification needed, sends to any address. Free: 300 emails/day. app.brevo.com → Settings → SMTP & API → API Keys |
| BREVO_FROM | mailer | Optional | Sender name/address for Brevo (default: SentinelTI <noreply@net-mon.net>) |
| RESEND_API_KEY | backend + mailer | Optional | Resend API key — fallback if BREVO_API_KEY is not set. Requires verified sending domain for arbitrary recipients |
| RESEND_FROM_EMAIL | backend + mailer | Optional | Sender name/address for Resend (default: SentinelTI <onboarding@resend.dev>) |
| MAILER_URL | backend | Optional | URL of the sentinel-mailer microservice — backend routes email through it when set |
| MAILER_SECRET | backend + mailer | Optional | Shared secret between backend and mailer service for request authentication |
| NEXT_PUBLIC_API_URL | frontend | Yes | Backend API base URL |