AI-powered security operations platform. SentraX connects to your Splunk instance, automatically investigates alerts using a 9-node LangGraph pipeline, scores severity deterministically, generates plain-English AI summaries with precautions, proposes ranked playbook actions, and learns from analyst feedback over time.
flowchart TD
SYS["Sysmon\nProcess · Network · DNS"]
WEVT["Windows Event Logs\n4624 Login · 4672 Privilege · 4688 Process"]
UF["Splunk Universal Forwarder"]
SYS --> UF
WEVT --> UF
UF -->|"TCP 9997"| IDX
subgraph Splunk
IDX[("windows_logs · botsv3\nincident_memory · sentinel_feedback")]
SAVED["Saved Search Alerts"]
IDX --> SAVED
end
SAVED -->|"POST /webhook/alert"| API
subgraph Backend ["FastAPI Backend :8001"]
API["Webhook Ingest"]
P1["Node 1 · Ingest"] --> P2["Node 2 · Investigate\nSPL queries"]
P2 --> P3["Node 3 · Score\n0-10 rule engine"]
P3 --> P4["Node 4 · Memory Lookup"]
P4 --> P5["Node 5 · Draft Summary\nGroq call 1"]
P5 --> P6["Node 6 · Counter Evidence"]
P6 --> P7["Node 7 · Critique\nGroq call 2"]
P7 --> P8["Node 8 · Playbook\nGroq call 3"]
P8 --> P9["Node 9 · Save to Splunk"]
API --> P1
HUNT["POST /hunt"]
DRILL["POST /drilldown"]
FEED["POST /feedback"]
CALIB["GET /calibration"]
end
P2 <-->|"REST API"| IDX
P4 <-->|"lookup"| IDX
P9 -->|"write"| IDX
HUNT <--> IDX
DRILL <--> IDX
FEED -->|"write"| IDX
CALIB <--> IDX
subgraph Groq ["Groq API · llama-3.1-8b-instant"]
G1["Summary · what happened\nwhy suspicious · precautions"]
G2["Critique · counter-evidence check"]
G3["Playbook rationale · 1 sentence per action"]
G4["Drill-down · conversational answers"]
end
P5 <--> G1
P7 <--> G2
P8 <--> G3
DRILL <--> G4
subgraph Frontend ["React Frontend :5173"]
DASH["Dashboard\nAlert Feed · Incident Detail"]
HTPG["Threat Hunt"]
CPAG["Calibration"]
DASH --> T1["Summary · AI analysis + precautions"]
DASH --> T2["Playbook · Approve / Reject"]
DASH --> T3["Drill-down · Chat"]
DASH --> T4["Raw Data · SPL tables"]
end
P9 -->|"SSE stream"| DASH
HUNT --> HTPG
CALIB --> CPAG
FEED <--> T2
DRILL <--> T3
Orchestration code makes ALL decisions. The Groq LLM is used ONLY for:
- Converting SPL results → plain-English summary with severity explanation and precautions (Node 5)
- Revising summary given counter-evidence (Node 7)
- Writing 1-sentence rationale per playbook action (Node 8)
- Phrasing conversational drill-down answers (Node 10)
The LLM never selects tools, writes SPL queries, scores severity, or controls branching logic. All of that is deterministic Python.
| # | Name | Description |
|---|---|---|
| 1 | Severity Calibration Dashboard | Tracks true positive vs false positive rate over time from sentinel_feedback. Demonstrates responsible AI monitoring — accuracy trends without model retraining. |
| 2 | Explain-the-Score Breakdown | Clickable severity badge expands to show every contributing factor (+3 off-hours, +2 bad IP, etc.). Pure deterministic logic — no LLM. |
| 3 | Proactive Threat Hunt | Hunt any entity on-demand to surface near-miss anomalies that scored below the alert threshold. Proactive security posture. |
| 4 | Live Windows Telemetry | Sysmon + Universal Forwarder pipeline for real-time process, network, and DNS event collection from Windows endpoints. |
| 5 | AI-Powered Precautions | LLM summaries explicitly include what happened, why it is suspicious, severity context, and specific recommended actions based on score level. |
| Layer | Technology |
|---|---|
| SIEM | Splunk Enterprise (free dev license) |
| Endpoint telemetry | Sysmon + Splunk Universal Forwarder |
| Pipeline orchestration | LangGraph (StateGraph) |
| Backend API | FastAPI + Uvicorn |
| LLM | Groq API — llama-3.1-8b-instant (free tier) |
| Frontend | React + Vite + Recharts |
| HTTP client | httpx (async) |
| State | In-memory dict (session) + Splunk indexes (persistent) |
- Splunk Enterprise — free dev license, running locally
- Splunk Universal Forwarder — for live Windows telemetry
- Sysmon — for process, network, DNS events
- Python 3.11+
- Node.js 18+
- Groq API key — free, no credit card required
- (Optional) BOTSv3 dataset — for testing with pre-built security data
Create these indexes in Splunk web (http://your-splunk-host:8000 → Settings → Indexes):
| Index name | Purpose |
|---|---|
incident_memory |
SentraX stores investigated incidents |
sentinel_feedback |
Analyst feedback for calibration |
windows_logs |
Live Windows/Sysmon events from forwarder |
Upload the threat intel lookup:
- Settings → Lookups → Lookup table files → Upload
splunk_config/threat_intel.csv - Name:
sentrax_threat_intel.csv - Settings → Lookups → Lookup definitions → Add new → Name:
sentrax_threat_intel
Enable receiving on port 9997:
- Settings → Forwarding and receiving → Configure receiving → New →
9997
# Run as Administrator
# Download Sysmon from https://learn.microsoft.com/en-us/sysinternals/downloads/sysmon
# Extract to D:\Sysmon\ then:
D:\Sysmon\Sysmon64.exe -accepteula -i splunk_config/sysmon_config.xmlDownload from https://www.splunk.com/en_us/download/universal-forwarder.html and install to D:\SplunkUniversalForwarder.
Deploy the SentraX forwarder config:
# Run as Administrator
Copy-Item splunk_config/uf_inputs.conf "D:\SplunkUniversalForwarder\etc\system\local\inputs.conf" -Force
Copy-Item splunk_config/uf_outputs.conf "D:\SplunkUniversalForwarder\etc\system\local\outputs.conf" -Force
& "D:\SplunkUniversalForwarder\bin\splunk.exe" restartcd backend
# Copy and fill in credentials
cp .env.example .env
# Edit .env — set SPLUNK_HOST, SPLUNK_PASSWORD/TOKEN, GROQ_API_KEY
# Create virtual environment
python -m venv venv
.\venv\Scripts\activate # Windows
# source venv/bin/activate # Linux/Mac
pip install -r requirements.txt
python main.py
# API runs at http://localhost:8001
# Swagger docs at http://localhost:8001/docscd frontend
npm install
npm run dev
# UI at http://localhost:5173Create these two alerts in Splunk web (Settings → Searches, reports, and alerts → New Alert):
Alert 1 — Suspicious Process Creation
index=windows_logs EventCode=4688
(NewProcessName="*powershell*" OR NewProcessName="*wscript*" OR NewProcessName="*mshta*")
| stats count
- Type: Real-time | Trigger: count > 0 | Throttle: 30 min
- Action: Webhook →
http://localhost:8001/webhook/alert
Alert 2 — Suspicious Domain Lookup (Sysmon)
index=windows_logs EventCode=22
(Image="*msedge*" OR Image="*chrome*" OR Image="*powershell*")
(QueryName="*.ru" OR QueryName="*.xyz" OR QueryName="*.tk" OR QueryName="*pastebin*")
| stats count by Image, QueryName
- Type: Real-time | Trigger: count > 0 | Throttle: 30 min
- Action: Webhook →
http://localhost:8001/webhook/alert
| Method | Path | Description |
|---|---|---|
POST |
/webhook/alert |
Receive Splunk alert, start 9-node pipeline |
GET |
/incidents |
List all incidents (sorted by severity) |
GET |
/incidents/{id} |
Full incident detail with all pipeline outputs |
GET |
/incidents/{id}/stream |
SSE stream of live pipeline node progress |
POST |
/feedback |
Submit analyst disposition + approved/rejected actions |
GET |
/calibration |
TP/FP accuracy trend data for calibration dashboard |
POST |
/drilldown |
Conversational Q&A about a specific incident |
POST |
/hunt |
Proactive entity hunt (no alert required) |
GET |
/health |
Backend + LLM health check |
Full interactive docs: http://localhost:8001/docs
Trigger a manual alert:
curl -X POST http://localhost:8001/webhook/alert \
-H "Content-Type: application/json" \
-d '{"entity": "your-username@domain.com", "entity_type": "user",
"search_name": "Test Alert", "result": {"user": "your-username@domain.com"}}'Simulate suspicious activity (Windows):
# Triggers process creation alert
powershell -EncodedCommand dGVzdA==
# Triggers DNS alert (visit in browser)
# http://test.ru or http://google.ruProactive threat hunt:
- Go to
http://localhost:5173/hunt - Enter any entity that has events in your Splunk index
- Get full investigation + score + AI summary without needing an alert
SentraX/
├── backend/
│ ├── main.py # FastAPI app + startup health check
│ ├── config.py # Environment config loader
│ ├── splunk_client.py # Async Splunk REST API wrapper
│ ├── ollama_client.py # Groq API client + all LLM prompt templates
│ ├── store.py # In-memory incident store (session)
│ ├── pipeline/
│ │ ├── state.py # LangGraph TypedDict state definition
│ │ ├── nodes.py # All 9 pipeline nodes + drilldown + feedback
│ │ ├── graph.py # StateGraph compilation
│ │ └── playbook_library.py # Deterministic playbook action catalog + ranking
│ ├── spl_templates/
│ │ ├── user_queries.py # SPL templates for user entity type
│ │ ├── ip_queries.py # SPL templates for IP entity type
│ │ ├── host_queries.py # SPL templates for host entity type
│ │ └── dns_queries.py # Sysmon DNS query templates
│ ├── routers/
│ │ ├── alerts.py # Webhook receiver + incident CRUD + SSE
│ │ ├── feedback.py # Analyst feedback + calibration data
│ │ ├── drilldown.py # Conversational drill-down endpoint
│ │ └── hunting.py # Proactive threat hunt endpoint
│ ├── requirements.txt
│ └── .env.example # Template — copy to .env and fill in
├── frontend/
│ └── src/
│ ├── App.jsx # Router + health status
│ ├── components/
│ │ ├── AlertFeed.jsx # Live incident list with pipeline progress
│ │ ├── IncidentPanel.jsx # 4-tab incident detail view
│ │ ├── SeverityBreakdown.jsx # Innovation 2 — score factor breakdown
│ │ ├── PlaybookActions.jsx # Ranked actions + approve/reject + feedback
│ │ ├── ChatDrilldown.jsx # Conversational analyst Q&A
│ │ ├── SimilarIncidents.jsx # Cross-incident memory display
│ │ ├── CalibrationDashboard.jsx # Innovation 1 — accuracy trend charts
│ │ ├── HuntingPanel.jsx # Innovation 3 — proactive threat hunt
│ │ └── Navbar.jsx # Navigation + LLM/Splunk status dots
│ └── services/api.js # Backend API client
├── splunk_config/
│ ├── indexes.conf # Custom Splunk index definitions
│ ├── savedsearches.conf # Alert saved search definitions
│ ├── threat_intel.csv # Sample threat intelligence lookup data
│ ├── sysmon_config.xml # Sysmon event filter configuration
│ ├── uf_inputs.conf # Universal Forwarder inputs configuration
│ └── uf_outputs.conf # Universal Forwarder outputs configuration
├── ARCHITECTURE.md # Architecture diagram
├── .gitignore
└── README.md
| Variable | Default | Description |
|---|---|---|
SPLUNK_HOST |
localhost |
Splunk server hostname |
SPLUNK_PORT |
8089 |
Splunk REST API port |
SPLUNK_USERNAME |
admin |
Splunk username |
SPLUNK_PASSWORD |
changeme |
Splunk password |
SPLUNK_TOKEN |
(empty) | Bearer token — preferred over password |
SPLUNK_VERIFY_SSL |
false |
Verify Splunk TLS certificate |
INDEX_BOTS |
botsv3 |
BOTSv3 dataset index |
INDEX_LIVE |
windows_logs |
Live Windows telemetry index |
INDEX_INCIDENT_MEMORY |
incident_memory |
SentraX incident store |
INDEX_SENTINEL_FEEDBACK |
sentinel_feedback |
Analyst feedback store |
THREAT_INTEL_LOOKUP |
sentrax_threat_intel |
Splunk lookup table name |
GROQ_API_KEY |
(required) | Groq API key — get free at console.groq.com |
GROQ_MODEL |
llama-3.1-8b-instant |
Groq model name |
APP_PORT |
8001 |
FastAPI server port |
SEVERITY_ALERT_THRESHOLD |
5.0 |
Minimum score to show alert banner |
SEVERITY_CRITICAL_THRESHOLD |
8.0 |
Score threshold for CRITICAL label |
- 🔒 Configurable data residency — swap Groq for a local Ollama model to run fully air-gapped with zero data egress. Suitable for HIPAA, SOX, FedRAMP environments.
- 🔍 Fully auditable scoring — every severity score shows its exact component breakdown. No black-box AI decisions.
- 📊 Model accountability — calibration dashboard tracks whether scores predict real threats over time without retraining.
- ✅ Human in the loop — every playbook action requires explicit analyst approval. The AI proposes, the analyst decides.
- 🧠 LLM scope limited by design — the LLM only generates text. All orchestration, tool selection, SPL construction, and scoring is deterministic Python code.
MIT — see LICENSE
