Ngenzipack/intelligent-security-alert-triage-engine
GitHub: Ngenzipack/intelligent-security-alert-triage-engine
Stars: 0 | Forks: 0
# Intelligent Security Alert Triage Engine
Production-style proof-of-concept for reducing SOC alert fatigue using local LLM triage.
## Why this project exists
Security teams often face alert fatigue: high-volume SIEM alerts with limited analyst time. This project demonstrates a practical triage pipeline that takes raw alerts, normalizes them, performs LLM-assisted analysis, enriches results with threat context, and presents analyst-ready outputs.
## Project positioning
This repository is intentionally presented as a **Proof of Concept (POC)** with production-minded design choices:
- typed data contracts
- deterministic fallback when LLM is unavailable
- structured logging
- audit persistence
- unit/integration tests and CI
It is not a certified production SOC platform.
## Validation artifacts
- Project report: [`docs/Intelligent_Security_Alert_Triage_Engine_Project_Report.docx`](docs/Intelligent_Security_Alert_Triage_Engine_Project_Report.docx)
- Before/after patch report: [`REPORT_BEFORE_AFTER_PATCH.md`](REPORT_BEFORE_AFTER_PATCH.md)
- Full-capability dashboard screenshots: `screenshots/full-capability/`
- Patch validation screenshots: `screenshots/report/`
## Production-ready packaging
This repository is prepared as a production-style project package with:
- explicit architecture and data contracts
- defensive runtime behavior and graceful fallback mode
- structured logging and auditable storage
- CI gates (lint + tests) and reproducible validation evidence
- before/after patch report with screenshot proofs
## Showcase screenshots
### Dashboard overview (LLM run)

### Sidebar workflow controls

### Metrics and charts

### Alert detail with enrichment and engine mode

## Core capabilities
1. Ingest alerts from:
- local JSON/CSV simulation files (primary path)
- optional Wazuh API
- optional Elasticsearch index
2. Normalize to canonical schema:
- `timestamp`
- `source`
- `event_type`
- `description`
- `raw_log`
3. Analyze with local LLM (Ollama + `llama3`):
- classification: `true_positive | false_positive | uncertain`
- criticality score: `0-100`
- plain-English summary
- mitigation steps
4. Enrich alerts:
- MITRE ATT&CK technique inference
- frequency in last 24h
- composite risk score
- severity band (`Low|Medium|High|Critical`)
5. Persist and visualize:
- append enriched output to `alerts_log.json`
- interactive Streamlit dashboard with filters, charts, drill-down, and export
## Architecture and data flow
flowchart LR
A["Wazuh API"] --> D["Ingestion Layer"]
B["Elasticsearch"] --> D
C["JSON or CSV Simulation"] --> D
D --> E["Normalization to Canonical Schema"]
E --> F["LLM Analysis Engine via Ollama llama3"]
F --> G["JSON Parser and Validation"]
G --> H["Fallback Classifier if needed"]
H --> I["Enrichment MITRE and Risk"]
I --> J["JSON Audit Store alerts_log.json"]
J --> K["Streamlit Dashboard"]
### Pipeline stages
- **Ingest**: collect records from selected source.
- **Normalize**: convert heterogenous payloads into one schema.
- **Analyze**: query Ollama at `POST /api/generate` with strict JSON prompt.
- **Guardrail parse**: recover JSON from noisy model output, validate required keys.
- **Fallback**: deterministic keyword triage if model is down/malformed.
- **Enrich**: attach MITRE mappings + frequency + composite risk.
- **Persist**: append enriched records to JSON audit log.
- **Visualize**: dashboard table, filters, pie chart, timeline, and exports.
## Repository structure
src/
analysis/ # prompting, parser, Ollama client, fallback logic
ingestion/ # file/wazuh/elk adapters + normalizer
enrichment/ # MITRE mapping + risk scoring
storage/ # JSON append store with file lock support
dashboard/ # Streamlit UI
cli.py # command interface
pipeline.py # orchestration
data/
sample_alerts.json
screenshots/
README.md
tests/
unit + integration tests
.github/workflows/
ci.yml
## Requirements
- Python **3.11+**
- Ollama installed locally
- `llama3` model pulled (`ollama pull llama3`)
## Quick start
1. Clone repo and enter it.
2. Create env and install dependencies:
python3.11 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
3. Configure environment:
cp .env.example .env
4. Ensure Ollama is running:
ollama serve
ollama list | grep llama3
## Commands
### CLI batch (simulation)
python -m src.cli run-batch --source file --path data/sample_alerts.json
### CLI batch (Wazuh)
python -m src.cli run-batch --source wazuh
### CLI batch (ELK)
python -m src.cli run-batch --source elk
### CLI manual alert analysis
python -m src.cli analyze-text --text "Suspicious PowerShell execution from C:\Users\admin\AppData\Local\Temp\payload.ps1"
### Streamlit dashboard
streamlit run src/dashboard/app.py
### Makefile shortcuts
make setup
make lint
make test
make run-cli
make run-ui
make sample
## Environment variables
| Variable | Purpose | Default |
|---|---|---|
| `OLLAMA_BASE_URL` | Ollama endpoint base URL | `http://localhost:11434` |
| `OLLAMA_MODEL` | Local model name | `llama3` |
| `OLLAMA_TIMEOUT_SECONDS` | HTTP timeout for model/API calls | `45` |
| `OLLAMA_MAX_RETRIES` | LLM retry attempts before fallback | `2` |
| `WAZUH_API_URL` | Optional Wazuh alerts endpoint | empty |
| `WAZUH_API_TOKEN` | Optional Wazuh bearer token | empty |
| `ELK_URL` | Optional Elasticsearch URL | empty |
| `ELK_INDEX` | Elasticsearch index pattern | `security-alerts-*` |
| `ELK_API_KEY` | Optional Elasticsearch API key | empty |
| `ALERT_LOG_PATH` | JSON audit log path | `logs/alerts_log.json` |
| `APP_LOG_PATH` | Application log file path | `logs/app.log` |
| `APP_LOG_LEVEL` | Log verbosity | `INFO` |
| `PIPELINE_VERSION` | Enriched record version tag | `1.0.0` |
## Output schema
Each enriched alert includes:
- normalized input fields
- `classification`, `criticality_score`, `summary`, `mitigation`
- `mitre_techniques`
- `frequency_24h`
- `composite_risk_score`
- `severity_band`
- `processed_at`
- `engine_mode` (`llm` or `fallback`)
- `pipeline_version`
## Example behavior
Input:
Expected style of output:
- Classification: `true_positive`
- Criticality: high (90+)
- Summary: likely LOLBin style abuse
- Mitigation: isolate host, block C2, collect forensic artifacts
- MITRE: `T1059.001`
## Design decisions
- **Strict JSON prompt + parser guardrails**: LLM output is constrained and validated before acceptance.
- **Deterministic fallback path**: demo and pipeline stay operational during model outages.
- **Composite risk formula**: combines severity with recent recurrence:
- `min(100, round(0.75 * criticality_score + 0.25 * min(frequency_24h*10, 100)))`
- **JSON append store with lock**: simple and auditable persistence for project scope.
## Testing and CI
Local:
ruff check .
pytest
GitHub Actions (`.github/workflows/ci.yml`):
- Python 3.11
- dependency install
- Ruff linting
- Pytest execution
## Engineering review points
- Why schema normalization is critical before LLM inference.
- How to harden LLM output with validation + retries + fallback.
- Risk scoring tradeoffs and explainability.
- Limitations of keyword MITRE mapping and next improvements.
- Evolution path: queue-based ingestion, DB storage, SOC integrations, RBAC, model eval benchmarks.
## Limitations and roadmap
Current limitations:
- heuristic MITRE mapping
- JSON-file storage instead of database
- no distributed workers or real-time queueing
Next steps:
1. Add async worker queue (Celery/RQ/Kafka).
2. Move persistence to PostgreSQL/Elasticsearch.
3. Add alert de-duplication and suppression policies.
4. Add analyst feedback loop for model tuning.
5. Add evaluation dataset and precision/recall tracking.
## Demo assets
- Sample alerts: `data/sample_alerts.json`
- Screenshot checklist: `screenshots/README.md`
- Posting runbook: `scripts/capture_demo_checklist.md`