Skip to content
/ snowl Public

LLM-Powered Cyber Threat Intelligence from RSS Feeds

License

Notifications You must be signed in to change notification settings

bitsalv/snowl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Snowl

Snowl

Local-first Cyber Threat Intelligence platform for security analysts.

Status Python License

Snowl automates the collection, extraction, enrichment, and reporting of threat intelligence from RSS feeds. It combines LLM-powered structured extraction with a Zettelkasten knowledge graph for campaign detection and CTI framework analysis.


Installation from Scratch

Prerequisites

Requirement Version Check
Python 3.10+ python3 --version
Docker 20+ docker --version
Docker Compose v2+ docker compose version
Git any git --version
OpenRouter API Key - openrouter.ai

Step 1: Clone the Repository

git clone https://github.com/bitsalv/snowl.git
cd snowl

Step 2: Initialize Python Environment

make init

This creates a virtual environment (.venv/), installs all Python dependencies from requirements.txt, copies env.template to .env, and creates the snowl/data/ and snowl/logs/ directories.

If make is not available:

python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip setuptools wheel
pip install -r requirements.txt
cp env.template .env
mkdir -p snowl/data snowl/logs

Step 3: Configure Environment Variables

Edit the .env file at the project root:

nano .env

Required settings:

# REQUIRED - Get your key at https://openrouter.ai/
OPENROUTER_API_KEY=sk-or-v1-your-key-here
OPENROUTER_MODEL=anthropic/claude-3.5-sonnet

All other settings have working defaults. See the full env.template for optional configuration (MCP endpoints, VirusTotal API key, PDF export, etc.).

Step 4: Initialize the Database

make db

Or manually:

source .venv/bin/activate
python snowl/src/db/migrate.py

This creates the SQLite database at snowl/data/snowl.db with all required tables, indexes, and FTS5 full-text search.

Step 5: Start TT-RSS (RSS Feed Aggregator)

Important: You must cd into the TT-RSS directory first so Docker Compose can find the .env file.

First, review and configure the TT-RSS environment:

nano snowl/docker/tt-rss/.env
# TT-RSS Docker Configuration
TTRSS_DB_HOST=db
TTRSS_DB_PORT=5432
TTRSS_DB_USER=ttrss
TTRSS_DB_PASS=ttrss_secure_password_changeme    # Change this!
TTRSS_DB_NAME=ttrss

TTRSS_PLUGINS=auth_internal,snowl_bridge
ADMIN_USER_PASS=password                         # Change this!
HTTP_PORT=8280

Then start the containers:

cd snowl/docker/tt-rss
docker compose up -d
cd ../../..

Do NOT use docker compose -f snowl/docker/tt-rss/docker-compose.yml up -d from the project root. Docker Compose resolves the .env file relative to the current working directory, not the docker-compose.yml location, so the TT-RSS environment variables (TTRSS_DB_USER, TTRSS_DB_PASS, etc.) will not be found.

Wait for the containers to be healthy:

docker compose -f snowl/docker/tt-rss/docker-compose.yml ps

You should see 4 containers running: db, app, web-nginx, updater.

TT-RSS will be available at http://localhost:8280

Default credentials:

  • Username: admin
  • Password: password (change immediately!)

Step 6: Install TT-RSS Plugin & Triggers

# Install the snowl_bridge plugin and auto-labeling trigger
make ttrss-install-trigger

# Install CTI framework content filters (MITRE, Kill Chain, Diamond Model)
make ttrss-install-filters

Step 7: Start Snowl

make run

Or manually:

source .venv/bin/activate
streamlit run snowl/src/Home.py

Snowl runs at http://localhost:8501

Step 8: (Optional) Start MCP Servers

MCP servers provide AI-powered enrichment (CVE lookup, MITRE ATT&CK, vulnerability search, etc.). Snowl works without them but with reduced functionality.

cd snowl/docker/mcp
docker compose build --no-cache    # First time only (downloads repos, compiles)
docker compose up -d
cd ../../..

Then configure the endpoints in your .env:

MCP_CVE_SEARCH_ENDPOINT=http://localhost:8081
MCP_OSV_ENDPOINT=http://localhost:8082
MCP_NIST_ENDPOINT=http://localhost:8083
MCP_ATTACK_ENDPOINT=http://localhost:8084
MCP_SQLITE_EXPLORER_ENDPOINT=http://localhost:8085
MCP_LOCAL_RAG_ENDPOINT=http://localhost:8086
MCP_MARKMAP_ENDPOINT=http://localhost:8087
MCP Server Port Source Description
cve-search 8081 CIRCL.lu CVE search and vendor/product lookup
osv 8082 Google OSV Open source vulnerability database
nist-nvd 8083 NIST NVD National Vulnerability Database, KEV catalog
mitre-attack 8084 MITRE ATT&CK Tactics, techniques, groups, software
sqlite-explorer 8085 Local Direct SQL queries on Snowl database
local-rag 8086 Local Semantic search with vector embeddings
markmap 8087 Local Mind map generation from Markdown

Quick Reference

# Everything in order (copy-paste)
git clone https://github.com/bitsalv/snowl.git
cd snowl
make init
nano .env                                    # Add OPENROUTER_API_KEY
make db
cd snowl/docker/tt-rss && docker compose up -d && cd ../../..
make ttrss-install-trigger
make ttrss-install-filters
make run                                     # http://localhost:8501

Troubleshooting

"WARN: variable TTRSS_DB_USER is not set"

You ran docker compose from the wrong directory. The .env file must be in the same directory where you run docker compose:

# Wrong
docker compose -f snowl/docker/tt-rss/docker-compose.yml up -d

# Correct
cd snowl/docker/tt-rss
docker compose up -d

"ModuleNotFoundError" when running Snowl

Virtual environment not activated:

source .venv/bin/activate
make run

TT-RSS containers not starting

Check if ports are available:

# TT-RSS uses port 8280 (web) and 5433 (PostgreSQL)
lsof -i :8280
lsof -i :5433

MCP servers build fails

MCP servers clone from GitHub during build. Ensure internet access and try:

cd snowl/docker/mcp
docker compose build --no-cache

Features

Intelligence Analysis

Feature Description
Structured LLM Extraction Single-pass extraction of entities, IOCs, TTPs, and CTI categories via OpenRouter
11 CTI Categories From CVEs to Geopolitical threats, with auto-classification
IOC Extraction IPs, domains, hashes, CVEs, MITRE ATT&CK TTPs
Automatic Enrichment NIST NVD + MITRE ATT&CK mapping via MCP servers
Semantic Search TF-IDF based article similarity

Knowledge Graph (Zettelkasten)

Feature Description
Atomic Notes One note per intelligence entity, auto-generated from analysis
Auto-Backlinks Bidirectional links between related notes
Hierarchical Tags Diamond Model, Kill Chain, severity, temporal tags
Campaign Detection Cluster related articles via shared entities and relationships

CTI Frameworks

Framework Implementation
Diamond Model Automatic 4-vertex identification (Adversary, Capability, Infrastructure, Victim)
Cyber Kill Chain MITRE TTPs mapped to 7 Kill Chain phases
MITRE ATT&CK Tactic and technique extraction with enrichment

Reporting & Export

Feature Description
5 Report Types Executive, Technical, Threat Landscape, IOC, Campaign
PDF Export Professional reports via WeasyPrint + Jinja2
STIX 2.1 Export Standards-compliant threat intelligence bundles
CSV Export Filtered data export

Platform

Feature Description
CTI Assistant LLM-powered chatbot with MCP tool integration and session persistence
Interactive Dashboard Plotly charts for framework analytics and KPIs
TT-RSS Integration Full Tiny Tiny RSS integration with custom plugin, theme, and content filters

Architecture

                    +------------------+
                    |     TT-RSS       |
                    |  RSS aggregation |
                    |  (Docker stack)  |
                    +--------+---------+
                             |
                     snowl_bridge API
                             |
+----------------------------v----------------------------+
|                        Snowl                            |
|                                                         |
|  Ingest ─> Extract ─> Enrich ─> Classify ─> Store      |
|    │          │          │          │          │         |
|  RSS/API   LLM pass   NVD/ATT&CK  11 cats   SQLite    |
|            IOC regex   MCP servers            FTS5      |
|                                                         |
|  Pipeline output:                                       |
|  ├── Zettelkasten notes (atomic, backlinked)            |
|  ├── Tags (Diamond Model, Kill Chain, severity)         |
|  ├── Reports (PDF, 5 types)                             |
|  └── Export (STIX 2.1, CSV)                             |
|                                                         |
|  Interactive:                                           |
|  ├── Dashboard (Plotly analytics)                       |
|  ├── Assistant (LLM + MCP tools)                        |
|  └── IOC search & validation                            |
+----------------------------------------------------------+

Streamlit Pages

Page Description
Home Platform status, pending articles, pipeline trigger
Analytics KPI dashboard with timeline, category distribution, top threats
Assistant CTI chatbot with MCP tool integration
Notes Zettelkasten knowledge base with backlinks and graph
Reports Generate and preview CTI reports
Archive Browse and manage generated reports
IOC Search and validate indicators by type
Export CSV and STIX 2.1 export with filters
Settings API keys, model selection, connection tests

TT-RSS Integration

Snowl uses Tiny Tiny RSS (GPL-3.0) as its feed aggregation backend.

Component Description
snowl_bridge plugin Exposes articles to Snowl via JSON API
Custom theme Dark theme optimized for CTI triage
Content filters Auto-highlight MITRE ATT&CK, Kill Chain, Diamond Model terms
Auto-labeling trigger PostgreSQL trigger assigns "Pending Analysis" to new articles
Docker Compose Pre-configured TT-RSS + PostgreSQL stack

License: The snowl_bridge plugin (AGPL-3.0) runs inside TT-RSS (GPL-3.0) -- these licenses are compatible. The main Snowl platform communicates with TT-RSS via HTTP API as separate programs.


Configuration

All settings are in the .env file (copied from env.template):

# Required
OPENROUTER_API_KEY=sk-or-v1-...
OPENROUTER_MODEL=anthropic/claude-3.5-sonnet

# Database
DB_PATH=data/snowl.db

# Features
USE_LLM_CLASSIFY=true
USE_EMBEDDINGS=false
ENABLE_PDF=true

# MCP Servers (optional, see Step 8)
MCP_CVE_SEARCH_ENDPOINT=
MCP_NIST_ENDPOINT=
MCP_ATTACK_ENDPOINT=

# Logging
LOG_LEVEL=INFO

Feeds

53 curated CTI feeds ship in snowl/data/default_feeds.yaml across categories: CVE, Malware, Threat Intel, CERT, Cloud, ICS, and more. Add custom feeds via the Settings page or by editing the YAML.


Development

make help           # All available commands
make test           # Run test suite
make test-cov       # Tests with coverage report
make format         # Format code (black)
make lint           # Run linters
make clean          # Clean caches

Project Layout

snowl/
├── src/
│   ├── Home.py                # Streamlit entry point
│   ├── config.py              # Pydantic config + .env
│   ├── pages/                 # 8 Streamlit pages
│   ├── pipeline/              # LLM analysis + Zettelkasten
│   ├── ingest/                # RSS/TT-RSS ingestion
│   ├── extract/               # LLM + IOC extraction
│   ├── enrich/                # NVD, ATT&CK, MCP enrichment
│   ├── export/                # CSV, STIX 2.1, PDF
│   ├── reports/               # Report generation (5 types)
│   ├── chat/                  # CTI Assistant (LLM + MCP)
│   ├── search/                # TF-IDF semantic search
│   ├── zettelkasten/          # Knowledge graph operations
│   ├── integrations/          # TT-RSS client (5 modules)
│   ├── db/                    # SQLite + APSW + FTS5 + migrations
│   └── ui/                    # Streamlit components + theming
├── data/
│   ├── snowl.db               # SQLite database
│   └── default_feeds.yaml     # 53 curated CTI feeds
├── docker/
│   ├── tt-rss/                # TT-RSS Docker stack + plugin
│   │   ├── docker-compose.yml
│   │   ├── .env               # TT-RSS environment variables
│   │   └── config.d/          # TT-RSS PHP config overrides
│   └── mcp/                   # MCP server containers
│       ├── docker-compose.yml
│       ├── dockerfiles/       # Dockerfiles for each MCP server
│       └── repos/             # Cloned MCP server repositories
├── tests/                     # Test suite
└── config/                    # Configuration files

License

GNU Affero General Public License v3.0 (AGPL-3.0) -- see LICENSE.

Built for security analysts, by security analysts.

About

LLM-Powered Cyber Threat Intelligence from RSS Feeds

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •