A community fork of DFIR-IRIS v2.5.0-beta.1, with native MISP integration, MISP nomenclature alignment, and an in-tree AI assistant layer. See
FORK.mdfor attribution + the rationale.
A collaborative incident-response platform. Forked from DFIR-IRIS because upstream paused
feature development in late 2024 and stranded v2.5.0-beta.1 in beta.
Everything in this repository is the Community Edition, and everything below is in it:
- Free and open source under LGPL-3.0 — the same license as upstream DFIR-IRIS.
- No feature gates. Nothing here is disabled, trialled, or unlocked by a key. Every feature listed in What's new vs upstream works on a stock install.
- No license server, no activation, no phone-home.
- No telemetry. iris-ng does not report usage anywhere.
- Self-hosted. Your case data, evidence, and AI prompts stay on your infrastructure. If you point the AI layer at a local model (LM Studio, Ollama), nothing leaves your network at all.
iris-ng is community-maintained. Issues and pull requests are welcome.
- Documentation — the iris-ng wiki (Getting Started, Architecture, AI Features, MISP Integration, Scripts Reference, and more).
- Bugs & feature requests — GitHub Issues. Please check the roadmap first.
- Pull requests — see
CONTRIBUTING.mdandCODESTYLE.md. Target themainbranch. - Security issues — please follow
SECURITY.mdrather than opening a public issue. - Support development — Patreon · Buy Me a Coffee. Entirely optional; it does not unlock anything.
- API-compatible with IRIS v2.5.0-beta.1 — existing n8n workflows and IRIS API clients continue to work unchanged.
- Database is not backwards-compatible — iris-ng adds new tables and columns that vanilla DFIR-IRIS does not have. A migration script is provided (see Migrating from vanilla DFIR-IRIS).
- Upstream bugfixes can be cherry-picked into the
upstream-fixesbranch when they land.
- Native MISP sync module (
source/iris_misp_sync_module/) — case ↔ MISP event, IOC ↔ MISP attribute; the IOC's TLP drives distribution + attribute tags. - MISP nomenclature alignment via
IocType.type_taxonomy— every IOC type maps to a MISP attribute type, with an LLM fallback for the few that lack a direct match. - Bundled MISP taxonomy + galaxy catalog (169 taxonomies, 122 galaxies, 66k machine-tag entries) powers tag autocomplete across every object in the UI.
- Async AI request queue —
POSTto any AI endpoint returns202 + task_idimmediately; a dedicatedai_workercontainer runs jobs off anai_queueso long LLM calls never block a web worker. PollGET /api/v2/ai/jobs/<id>for status. - Executive case summary panel — multi-pass map-reduce (4 domain specialists run in parallel, a synthesizer composes the output). Handles large cases without blowing past local-model context limits. Cached; re-runs only the affected specialist when a single object changes.
- Case-scoped chat assistant on six case-detail tabs (Notes / Timeline / Assets / IOC / Tasks / Evidence) with per-tab specialized prompts and full case context.
- Per-event AI analysis right-drawer — click any timeline card body for a 3-paragraph triage analysis; cached per event.
- Running master-timeline AI analysis panel — always-visible prose narrative (What the timeline tells us / What's still uncertain / Where to dig next). Flag-aware: reviewed events contribute with HIGH confidence, flagged events with MEDIUM.
- MITRE ATT&CK + Unified Kill Chain v1.3 suggestions on event create/edit — returns
up to 4 validated ATT&CK technique IDs and a single UKC phase; a
Set Event Categorybutton auto-selects the matching dropdown option. - IOC extraction from note text — type-validated against the live
IocTypetable, per-type regex shape sanity, noise-flag affordance (CDN / public resolver / sinkhole), dedup against existing case IOCs. Available in both the modal and inline note editors. - IOC ↔ Note provenance back-link —
+addin the IOC extractor auto-creates a link; linked notes render as violet pill chips on the edit-IOC modal. - AI-suggested evidence type on upload — auto-fires alongside the hash/size step; auto-applies to the type dropdown with a confidence chip. Analyst override clears it.
- AI-suggested case template on alert escalation — auto-fires when the Escalate modal opens; validated against the full live template catalog. 13/13 match in testing.
- AI tag suggester (MISP taxonomies + galaxies) — ✨ Suggest tags pill on IOC, asset, task, and event modals; output validated against the bundled 66k-entry catalog.
- IOC cluster narrative — AI-generated campaign brief per correlation cluster,
server-cached in
case_ai_artifact, rendered on the Correlation dashboard tab. - Two-slot AI backend — primary + alternate backend configured in
/manage/settingswith a radio to switch active slot; per-feature backend overrides let individual AI surfaces route to a different slot.
- Working timeline — a right-side review panel on the master-timeline page for staging and reviewing forensic events before promoting them to the master timeline.
- Hayabusa import (
POST /api/v2/cases/<cid>/working-timeline/import/hayabusa) — collapses sigma-rule fan-out on(Timestamp, Computer, Channel, EventID, RecordID). - EZ Tools / KAPE import (
…/import/eztools) — auto-detects 11 sub-formats (EvtxECmd, MFT, Prefetch, AppCompat, Amcache, RecycleBin, JumpList, LNK) from column headers; stream-decoded, capped at 25k rows per import. - Master-timeline CSV → working timeline — the existing "Upload CSV of events"
picker now offers a Master / Working destination radio; routes to a new endpoint backed
by
iris_master_csv_parser.py. - Promote-time asset + IOC materialization — promoting a working event auto-creates
CaseAssetsrows (hostname → Windows Computer/Server/DC heuristic; account → Windows Account AD/Local heuristic) and runs the AI IOC extractor (0.7 confidence threshold, noise-filtered). - Optional date-range filter on every import source (From/To inclusive, server-side).
- Per-event ✨ Explain pill — LLM triage explanation, 3-state toggle (reveal / hide
/ re-render from memory without an API call), cached in
case_ai_artifact. - Duplicate detection — on-demand exact + near-duplicate scan across the master and working timelines, with a side-by-side merge editor for near matches.
- Asset ↔ Evidence linking — select2 picker on the asset modal; inverse view as violet pill chips on the evidence modal with deep-link back to the asset.
- IOC ↔ Note provenance — M2M
ioc_note_linktable; back-links as violet chips on the edit-IOC modal; a backfill script handles pre-existing notes. - Jira-style task linking —
blocks/is blocked by,depends_on/is depended on by; advisory cycle-detection warning on the linking POST; dependency-tree view (indented hierarchy) on the Tasks tab with a toggle between flat and tree layouts. - Knowledge map — the per-case Graph tab draws asset, IOC, note, and evidence nodes, with direct relationship edges (not just timeline co-occurrence) and per-layer toggles to show or hide each object type.
- Metrics tab — case throughput, MTTR, sector / incident-type / customer breakdowns, time-tracking summary, all filterable by date range.
- Inventory tab — barcode ↔ physical evidence drive management; lookup resolves a drive to its current case and evidence items; wipe-and-rotate lifecycle support; capacity planning and a configurable retention policy.
- Correlation tab — IOC cross-case correlation engine:
- Cluster cards (union-find by shared
(ioc_value, ioc_type_id)) with decay score (exponential half-life per IOC type × tag-weight multipliers) and IOC confidence (log2 curve, ~40% at threshold, ~95% at 36 shared IOCs). - One-click
Apply campaign tag(tags all cases + all shared IOCs in the cluster). - AI-generated cluster narrative cached per cluster.
- STIX 2.1 bundle export per cluster — campaign + indicators + relationships, deterministic UUIDv5 IDs, TLP:GREEN marking, safe to share externally.
- D3 v7 force-directed graph — drag to pan, scroll to zoom (0.2×–4×); cluster filter redraws the graph to show only the selected cluster's nodes and edges.
- Shared IOC click-through drawer (per-case enrichment, linked notes, IOC tags).
- Per-IOC cross-case panel on the edit-IOC modal ("Check other cases").
- Cluster cards (union-find by shared
- Analyst time tracking — clock icon in the case header; 15-minute increment enforced at the DB level; edit-locked on case close; opt-in "you haven't logged time" nudge; cross-case reporting (by customer / analyst / sector / incident type) + per-case breakdown on the case-edit modal; estimated case cost from per-analyst hourly rates.
- Analyst skills + ad-hoc team building — 34-skill / 8-category catalog seeded on
boot; admin and self-service skill assignment; per-case team assembly with a greedy
set-cover scorer (✨ Suggest);
/manage/teamscoverage + active-case assignment page. - Case export/import — AES-256-GCM encrypted
.iris-caseformat; PBKDF2-HMAC-SHA256 key derivation (260k iterations); password in the request body (not the URL). - Master timeline events default to flagged — new events arrive with a "needs review"
flag; flag-aware timeline analysis uses
MEDIUMconfidence for flagged events. - Event history panel — collapsible color-coded lifecycle log from
CasesEvent.modification_historyJSONB; accessible from the event modal's ⋮ dropdown. - Mandatory sector tag (soft-enforced) — create-case modal requires a DHS CIIP / threatmatch sector selection; server-side warns (not rejects) if missing; customer record carries default sectors that new cases inherit.
- Physical evidence custody fields —
created_byandbarcodeon every evidence record, with a barcode ↔ drive link maintained automatically.physical_locationlives on the drive (EvidenceDrive), not the evidence row.
- Tabbed
/manage/settings— General / Security / AI / Analyst / Storage / System; tab selection persisted inlocalStorage; single form, Save works from any tab. - Two-slot AI backend — primary + alternate backends with a global active-slot radio and per-feature overrides (pin individual AI surfaces to a specific slot).
- Unified Kill Chain v1.3 Event Categories — 7 missing UKC phases added to the
Event Category dropdown via
post_init(Reconnaissance, Resource Development, Delivery, Social Engineering, Exploitation, Pivoting, Objectives).
iris-ng is purely additive over v2.5.0-beta.1 (new tables and columns only — no renames, no removals), but vanilla DFIR-IRIS cannot connect to an iris-ng database without the schema additions in place.
scripts/import_vanilla_db.sh handles the full migration: Postgres dump + restore,
named-volume copy (uploaded evidence, report templates), secret carry-over, and a
post-restore schema sanity check.
# On the OLD host (vanilla DFIR-IRIS)
bash scripts/import_vanilla_db.sh export --project iris-web --out ./iris-export
# Move iris-export/ to the new host, then:
bash scripts/import_vanilla_db.sh import --from ./iris-exportSupported source versions: v2.4.x and v2.5.0-beta.1. The script warns if it detects a partially-committed upstream migration history (a known upstream bug — see the script header for details).
If you are upgrading an existing iris-ng instance (not migrating from vanilla), use:
docker compose -f docker-compose.dev.yml up -d --build --force-recreateThe --force-recreate flag is required — a plain --build leaves the worker and
ai_worker containers on the old image, causing ORM/schema skew.
Upgrading from PostgreSQL 12 (iris-next.3 and earlier): the database image changed
from postgres:12-alpine to postgres:17-alpine in iris-next.4. A plain
up --build --force-recreate will fail if the old pg12 data volume is still present.
Run bash scripts/migrate_postgres_17.sh dump first (while pg12 is still running),
then follow the printed instructions to swap the image and restore. See
Scripts Reference → migrate_postgres_17.sh
for the full procedure.
# 1. Clone
git clone https://github.com/zach115th/iris-ng.git
cd iris-ng
# 2. Generate self-signed dev certs for nginx
bash scripts/generate_dev_certs.sh
# 3. Bootstrap .env (random secrets + first-boot admin password)
bash scripts/iris_helper.sh --init
# 4. Bring up the stack (dev compose)
docker compose -f docker-compose.dev.yml up -d --buildUI on https://localhost (HTTPS, port 443). The browser will warn about the self-signed
cert on first visit — accept the warning (Advanced → Proceed).
The first-boot admin username is administrator. Get the generated password from logs:
docker compose -f docker-compose.dev.yml logs app | grep "Administrator password"Or seed it via IRIS_ADM_PASSWORD in .env before the first start.
No registration, activation, or license key is required at any point.
-
MISP sync — set
MISP_URLandMISP_API_KEYin.env, then enable theiris_misp_syncmodule under/manage/modulesafter first boot. -
AI assistant — configure backend URL / API key / model under
/manage/settings(defaults work with a local LM Studio athttp://<lm-studio-host>:1234/v1). The freeopenai/gpt-oss-20bmodel is what the AI surfaces are tuned against. AI requests are queued through theai_workercontainer — LLM calls never block a web worker. A second backend slot lets you route specific AI surfaces to a different model.The AI layer is entirely optional. iris-ng runs with no backend configured — the AI surfaces simply report that no backend is set, and everything else works normally.
The badge is a referral link — free starting credit for you, and it supports this project. IRIS-NG has no dependency on any particular provider.
A single 4 GB Droplet running the compose stack above is the fastest way to evaluate IRIS-NG, and is the configuration this project tests.
On Kubernetes, a Helm chart lives in deploy/kubernetes/charts.
Chart 0.2.0 brought it forward to the current stack — it defaults to the published
GHCR images, deploys the ai_worker, and requests a normal volume from the cluster
default StorageClass instead of a node-local hostPath one:
helm install iris-ng ./deploy/kubernetes/charts -n iris --create-namespace -f my-values.yamlChange the ingress hostname and every shipped secret before you install. Verified on a
live single-node cluster (kind, Kubernetes 1.34) — 5/5 pods Running, PVC bound,
schema created, HTTP 200 on /login. Not yet tested on a managed multi-node
cluster, where rescheduling and a real CSI driver are what differ.
Full walkthrough, persistence notes and sizing: Kubernetes.
Six containers: app (Flask + SocketIO), db (PostgreSQL 17), rabbitmq,
worker (Celery general worker), ai_worker (Celery AI worker — single-concurrency,
GPU-bound), nginx. See architecture.md for the layered code
design (blueprints → business → datamgmt; cross-layer imports forbidden).
Container images are published to the GitHub Container Registry under
ghcr.io/zach115th.
main— the active development branch. New work lands here, and releases are tagged from it. Pull requests should targetmain.upstream-fixes— created lazily if upstream ships a bugfix worth cherry-picking.
Inherited from upstream (CODESTYLE.md):
[ADD]/[FIX]/[IMP]/[DEL]action prefix.- With issue:
[#123][FIX] message. - Python: f-strings only, one import per line, function names include the module name
(e.g.
iocs_create). - DB schema changes ship an Alembic migration. Define
CHECKconstraints on the ORM model's__table_args__(not just in the migration) — IRIS runsdb.create_all()before alembic, so migration-only constraints are dropped.
LGPL-3.0. See LICENSE.txt. Modifications must remain LGPL.
DFIR-IRIS by Airbus CyberSecurity (SAS) and the open-source community. Original repo at https://github.com/dfir-iris/iris-web. Sponsored historically by Deutsche Telekom Security GmbH.