staatik/fragchain-core

GitHub: staatik/fragchain-core

Stars: 0 | Forks: 0

# FragChain FragChain helps detection engineers and SOC analysts answer the question every coverage program eventually asks: *"Given a fresh CVE, what's the realistic attack chain — and do our Sigma rules actually detect it?"* It pairs an analyst-driven **assessment workspace** with an **LLM-synthesized attack chain**, maps the result onto MITRE ATT&CK, surfaces the coverage gaps in your Sigma library, and drafts candidate detection rules for human review. Validated chains contribute back to a shared **intelligence commons** so the next team that sees the same CVE doesn't have to start from scratch. ![FragChain dashboard — ATT&CK coverage heatmap with per-tactic Sigma rule counts and recent activity](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/d31431b6ab095833.png) ## Why this exists Detection engineering today is a treadmill: FragChain bets that two ingredients change the shape of that work: 1. **An LLM that drafts structured attack chains** — ordered TTPs, each grounded in cited sources, with explicit detection opportunities — turns the "read three blogs and guess" stage into something reviewable. 2. **A shared, versioned commons** — chains, ATT&CK mappings, and EPSS snapshots — so a new deployment bootstraps from pre-validated content instead of running expensive LLM synthesis from a cold start. Everything in between is plumbing to make those two things safe: TLP propagation, per-rule provenance, a mandatory human gate before any rule lands in a Sigma repo, multi-target routing, and a coverage scorer that knows the difference between "matched by tag" and "matched by semantic search." ## What it looks like ### Finding what to assess The CVE explorer lists known vulnerabilities with filters for date range, CVSS, KEV-only, processing status, and source. This is where an analyst picks a target before opening an assessment.

CVE explorer — filterable list with CVSS, KEV, mode, status, and confidence columns

### The assessment workspace (active workflow) An analyst opens a coverage assessment for a CVE — pasted from a ticket, a PSIRT advisory, or a vendor blog — and walks the platform through three loops: - **Loop 1 — Vulnerability Analysis.** What kind of vuln is this, and what detection questions does it raise? - **Loop 2 — Threat Intel.** Behavioral indicators per observable category (process, command line, network, file, registry, parent/child, API call), grounded in the pasted sources via RAG. - **Loop 3 — Detection Engineering.** Sigma rule drafts per enabled logsource profile, validated by pySigma before they reach the review queue. A deterministic gate sits between Loop 2 and Loop 3 — if you don't have indicators across enough observable categories, synthesis stops and the analyst is told why. ### The chain viewer Every chain — whether LLM-synthesized or imported from the commons — is rendered as an ordered TTP graph with per-step sources, preconditions, detection opportunities, and a per-step confidence score. Nothing makes it into a chain without a cited source.

Attack chain viewer — ordered ATT&CK TTPs for CVE-2025-32433 with confidence and TLP

### The review queue Drafted Sigma rules land in a priority-scored queue (KEV, EPSS, CVSS, novelty, position-in-chain). Each rule is tagged with TLP and the originating chain.

Review queue listing — rules grouped by CVE with TLP and level badges

A human approves, edits, or rejects each rule with the full Sigma YAML, source chain, and detection metadata side by side. Approved rules are routed via configurable rules to one or more Sigma target repositories as PRs — **never auto-merged**.

Rule editor — full Sigma YAML with technique tags, references, and TLP

### The Sigma library Every Sigma rule the platform knows about — both the existing upstream content pulled from configured sources and the FragChain-generated rules that landed in the library — is searchable, filterable, and tagged with logsource, technique, status, and TLP. This is where coverage decisions actually get made.

Sigma library — table of rules with logsource, technique, level, CVE, and status

### Tunable LLM prompts Every prompt the platform sends to the LLM lives in the database, not in code. Operators version, A/B test, and tune prompts per task (chain generation, rule generation, coverage verification, vuln analysis, threat intel) without redeploying the service. Each prompt records token cost, latency, and hallucination scores against a benchmark set.

Prompts management — versioned chat templates with system/user editors and benchmark metrics

## How it fits together ┌─────────────────────┐ ┌────────────────────────┐ │ Analyst opens │ │ Intelligence commons │ │ assessment (CVE) │◀───────│ (chains, mappings, │ └──────────┬──────────┘ │ EPSS snapshots) │ │ └────────────▲────────────┘ ▼ │ ┌──────────────────────────┐ │ │ Loop 1 → Loop 2 → gate │ │ │ → chain bridge → │ │ │ Loop 3 (Sigma drafts) │ │ └──────────┬───────────────┘ │ ▼ │ ┌──────────────────────────┐ │ │ Review queue │ │ │ (priority-scored, │ │ │ TLP-tagged) │ │ └──────────┬───────────────┘ │ ▼ │ ┌──────────────────────────┐ │ │ Human approve / edit / │ │ │ reject → PR to Sigma │ │ │ target repo(s) │ │ └──────────┬───────────────┘ │ ▼ │ ┌──────────────────────────┐ │ │ Validated chain │────────────────┘ │ contributes back │ └──────────────────────────┘ The original push-driven pipeline (connector → enrichment → synthesis → coverage → rules) is preserved in tree but **dormant by design** — it'll come back when the connector ecosystem (OpenCTI, AttackerKB, vendor PSIRT, etc.) is dense enough to justify it. See [`CLAUDE.md`](CLAUDE.md) §12 / §12.2 for the dormant-allowlist. ### Where to read - **[`CLAUDE.md`](CLAUDE.md)** — operational contract. Architecture, schemas, TLP propagation rules, the Never-Do list, the dormant-allowlist. Read this before touching code. - **[`docs/architecture/`](docs/architecture/)** — active design notes (assessment-centric architecture, coverage verification, frontend design). - **[`docs/superpowers/plans/`](docs/superpowers/plans/)** — per-feature TDD task lists for in-flight work. - **[`docs/historical/`](docs/historical/)** — the M1–M24 build log and the original pre-pivot design corpus, preserved for context (not active scope). ### Code conventions - Python 3.12, async/await throughout (FastAPI, SQLAlchemy 2.0 async, asyncpg, structlog) - React 18 + TypeScript + Vite + the DarkOps v3 design system ([`frontend/src/styles/darkops.css`](frontend/src/styles/darkops.css)) - pySigma validation on every generated rule (mandatory) - Every LLM call logged to `llm_interactions` + full I/O to MinIO - All Celery tasks idempotent ## Quickstart FragChain runs as a Docker Compose stack on a single host (the "Server 3" role below). You bring the LLM (Server 1, via [LiteLLM](https://github.com/BerriAI/litellm)); OpenCTI (Server 2) is optional. ### Prerequisites - Docker 24+ with the Compose v2 plugin - A reachable **LiteLLM** endpoint (URL + API key) — see below - `openssl` for the one-time self-signed TLS cert - ~4 GB RAM headroom ### 1. Bring up a LiteLLM proxy (Server 1) FragChain talks to a single LiteLLM endpoint via the OpenAI-compatible API. Point it at whatever chat + embedding models you want — Anthropic, OpenAI, Bedrock, Azure, or local Ollama. Recommended pairing: **Claude Sonnet for chat + nomic-embed-text on Ollama for embeddings** (open-source, 768-d, matches Qdrant exactly). # litellm_config.yaml on Server 1 model_list: - model_name: claude-sonnet litellm_params: model: anthropic/claude-sonnet-4-6 api_key: os.environ/ANTHROPIC_API_KEY - model_name: nomic-embed-text litellm_params: model: ollama/nomic-embed-text api_base: http://ollama.internal:11434 ollama pull nomic-embed-text # one-time litellm --config litellm_config.yaml --port 4000 See [`docs/litellm-setup.md`](docs/litellm-setup.md) for worked examples against OpenAI, Bedrock, and local Ollama. ### 2. Configure FragChain cp .env.example .env # At minimum set: # APP_SECRET_KEY, JWT_SECRET (32+ byte random) # POSTGRES_PASSWORD, REDIS_PASSWORD, MINIO_ROOT_PASSWORD, QDRANT_API_KEY # LITELLM_BASE_URL, LITELLM_API_KEY # LITELLM_CHAT_MODEL, LITELLM_EMBEDDING_MODEL # ADMIN_PASSWORD (admin/admin is REFUSED at boot) Generate strong secrets: python -c "import secrets; print(secrets.token_urlsafe(48))" ### 3. Generate a self-signed TLS cert nginx serves HTTPS only. mkdir -p nginx/certs openssl req -x509 -nodes -days 365 \ -newkey rsa:2048 \ -keyout nginx/certs/fragchain.key \ -out nginx/certs/fragchain.crt \ -subj "/CN=localhost" \ -addext "subjectAltName=DNS:localhost,IP:127.0.0.1" chmod 600 nginx/certs/fragchain.key For production, replace with a real cert. Filenames must remain `fragchain.crt` / `fragchain.key`. ### 4. Boot the stack docker compose up --build -d docker compose ps # wait for healthy ./setup.sh # seed prompts, profiles, presets, ATT&CK ./setup.sh --with-fixture # optionally also import Dirty Frag (CVE-2026-43284) The seed script is idempotent and runs ATT&CK technique embeddings through LiteLLM (~700 rows), so make sure your embedding model is reachable from the API container before running it. ### 5. Verify curl -k https://localhost/api/v1/readyz # public curl -k https://localhost/api/v1/version | jq curl -k -X POST https://localhost/api/v1/auth/login \ -H "Content-Type: application/json" \ -d '{"username":"admin","password":""}' | jq Then open in a browser (accept the self-signed cert warning). ## Operational reference ### Service layout | Service | Port (internal) | Exposed via nginx | Purpose | |---|---|---|---| | nginx | 80 / 443 | yes — only public ports | Terminates TLS, proxies API + UI | | fragchain-api | 8000 | `/api/`, `/ws/` | FastAPI | | fragchain-ui | 3000 | `/` | Static SPA bundle via `nginxinc/nginx-unprivileged` | | fragchain-worker | — | no | Celery worker | | fragchain-beat | — | no | Celery beat scheduler | | flower | 5555 | no | Celery monitoring (internal) | | postgres | 5432 | no | App database | | redis | 6379 | no | Broker + cache | | minio | 9000 / 9001 | no | Object store (LLM I/O + artifacts) | | qdrant | 6333 | no | Vector store (local to Server 3) | Only nginx publishes ports. Everything else stays on the internal Docker networks. ### Common commands docker compose logs -f # tail all services docker compose exec fragchain-api alembic upgrade head docker compose exec fragchain-api python # API shell docker compose down -v # DEV ONLY — destroys all data ### Local frontend development cd frontend npm install npm run dev # Vite dev server on http://localhost:3000 npm run build # Production build → frontend/dist/ npm run lint # tsc --noEmit ## Status, security, license **Status.** Pre-1.0. Published as a portfolio / reference project under the four-repo ecosystem described above. The assessment workspace and three-loop content engine are the active workflow; the push-driven pipeline is preserved in tree but dormant pending a denser connector ecosystem. **Security posture.** An F-001..F-008 pre-public hardening pass landed before this repo was opened — production secret validation, per-row authorization on assessments, single-use WebSocket tickets, `/docs` and `/openapi.json` disabled in production, non-root frontend image, hardened nginx + CSP. Full posture and residual risk are documented in: - [`SECURITY.md`](SECURITY.md) — reporting process - [`docs/threat-model.md`](docs/threat-model.md) — actors, trust boundaries, STRIDE table - [`docs/security-review-2026-05-20.md`](docs/security-review-2026-05-20.md) — findings inventory + methodology - [`docs/remediation-log.md`](docs/remediation-log.md) — per-finding remediation with test coverage - [`docs/reviews/security_architecture_poc/`](docs/reviews/security_architecture_poc/) — independent 11-part security architecture review **License.** Apache 2.0 for the engine + connectors. CC0 1.0 for the intelligence commons data (once the commons publishes). **Disclosure.** Report security issues via GitHub Security Advisories on this repository. See [`SECURITY.md`](SECURITY.md). ## Project layout fragchain/ Python package (API, workers, db, modules) frontend/ React + TypeScript + Vite + DarkOps v3 nginx/ Reverse-proxy config + TLS certs (not committed) chains/ Ground-truth attack chain fixtures prompts/ Seed prompts (loaded into DB by setup.sh) scripts/ Setup + seed scripts benchmarks/ Coverage benchmark ground-truth tests/ Pytest suite (unit + integration) docs/ ├── architecture/ Active design notes ├── reviews/ Independent security/architecture reviews ├── superpowers/ In-flight plans ├── historical/ M1–M24 build log + original design corpus ├── images/ README screenshots ├── threat-model.md ├── security-review-2026-05-20.md ├── remediation-log.md └── public-readiness-checklist.md See [`CLAUDE.md`](CLAUDE.md) §17 for the canonical Python / frontend tree.