Changelog
All notable changes to DFIRe, organized by version. The project follows Semantic Versioning.
1.2.8 — 2026-03-27
Added
- Chain of Custody: Formal custody tracking for evidence items with four transfer types (intake, transfer, correction, released), chain continuity enforcement, and automatic location sync. Custody transfers are immutable records that cannot be edited or deleted. Each transfer records the from/to parties (legal entities or DFIRe users), location, timestamp, purpose, condition, and notes. Transfer and release types enforce chain continuity — the from party must match the current custodian. Corrections require explanatory notes.
- Custody Receipt: Printable chain of custody receipt accessible from the evidence Custody tab. Opens in a clean browser tab for printing with item details, all custody transfers in a two-row-per-entry table format, and a disclaimer that the electronic record in DFIRe is the authoritative document.
- Custody Timeline Events: Custody transfers automatically create
CUSTODY_TRANSFERtimeline events in the associated case, recording transfer type, parties, and location. - Custodian in Sidebar: Evidence item sidebar now shows the current custodian derived from the latest chain of custody entry. Shows “No record” when no custody chain exists, or “Released from custody” when the last transfer was a release. Custodian entities are clickable links to the entity detail.
- Item Runbooks: Evidence items can have procedural runbooks attached as step-by-step checklists. Runbooks are automatically attached based on evidence type defaults when items are created, and can be manually attached or detached from the Runbooks tab. Each attached runbook stores a snapshot of steps with per-step completion tracking.
- Evidence Type Default Runbooks: Evidence types can be configured with default runbooks that are auto-attached when new items of that type are created. Configured in System Settings > Evidence Types via a slug-based dropdown selector.
- 14 Default Runbooks: Comprehensive set of evidence handling and technical operation runbooks shipped as defaults: Hard Drive Acquisition & Handling, Flash Media Acquisition & Handling, Memory Image Verification & Processing, Disk Image Verification & Integrity, Mobile Device Intake & Preservation, Computer Intake & Preservation, Log File Integrity & Processing, Malware Sample Safe Handling, Network Capture Verification & Processing, Account Evidence Preservation, Cloud Resource Evidence Preservation, Endpoint Containment, Evidence Collection – Workstation, and Reset User Password and Sessions.
- Runbook Assignments on Actions: 12 case type actions across 5 case types now have runbooks attached for specific technical procedures (endpoint isolation, credential reset, device seizure, volatile memory capture, malware sample handling).
- Related Evidence: “Add Related Evidence” button on evidence item detail view to create parent or child items directly, with a relationship selector (parent/child) in the modal.
- Tab Count Badges: Evidence item tabs (Notes, Runbooks, Custody, Attachments) now show count badges matching the Case view design pattern, with blue highlighting on the active tab.
- Runbooks Documentation: New
runbooks.htmldocumentation page explaining runbook concepts, evidence type and case type integration, default runbooks, management procedures, and API/MCP access. Runbooks link added to sidebar on all documentation pages. - Message of the Day: Configurable MOTD displayed on the login page. Supports markdown formatting. Administrators can enable and edit the message in System Settings to communicate notices to users before login (e.g., access instructions, maintenance windows, demo credentials).
- Dependency Viewer: SBOM viewer in System Settings showing Python (requirements.txt) and Node.js (package-lock.json) dependency manifests with search filtering. Allows superusers to verify installed package versions and integrity hashes directly from the UI.
Changed
- EULA v1.2: Updated End User License Agreement. Trial period extended from 30 to 90 days. Public IP address added to collected data disclosure (Section 4.2). Liability exclusion and liability cap clauses made mutual (Sections 8.1, 8.2). Assignment clause made mutual with merger/acquisition exception (Section 11.8). Corrected business location from Espoo to Vantaa. EULA version constant bumped to 1.2, triggering re-acceptance on existing installations.
- Third-Party Licenses: Comprehensive update to the public third-party licenses page. Added 16 missing Python dependencies (drf-spectacular, django-cors-headers, django-filter, dj-database-url, channels_redis, gunicorn, django-redis, bleach, whitenoise, python-magic, jira, slack_bolt, litellm, python-whois, python-dotenv, PyYAML) and 4 missing frontend dependencies (PrismJS, react-simple-code-editor, rehype-sanitize, remark-gfm). Added new Integrations section for Jira, Slack Bolt, and LiteLLM. Reorganized transitive dependencies (Twisted, Autobahn, zope.interface, Pydantic, HTTPX) into a dedicated section with parent package attribution. Updated Redis server license from BSD-3-Clause to RSALv2/SSPLv1 (v7.4+). Added callout notes explaining LGPL, MPL-2.0, and Redis license terms for commercial use. Added HPND, BlueOak-1.0.0, and PostgreSQL License to the license summary table.
- Evidence Item Tabs: Tab bar now uses
flex-1styling to span full width evenly, matching the Case detail layout convention. - Ownership Labels: “Ownership & Custody” section in Add Evidence modal renamed to “Ownership & User Information”. “Select Custodian...” placeholder changed to “Select User...” to reflect the distinction between primary user and custodian.
- Add Evidence Modal Simplified: Removed the optional initial custody section from the Add Evidence modal. Custody is now recorded separately in the evidence Custody tab after item creation.
- Settings UI: Evidence Types and Runbooks management pages refactored from card layout to table layout for better information density.
- Evidence Type Editor: Modal narrowed, icon picker made collapsible, JSON editor uses syntax-highlighted editor with line numbers, runbook assignment uses slug-based dropdown.
- Evidence Documentation: Updated
evidence.htmlwith chain of custody section, runbooks tab documentation, custodian role explanation, and related evidence feature.
Fixed
- Sanitization Double-Escaping: Fixed
sanitize_markdown()double-escaping ampersands and other HTML entities in text fields (e.g., “Memory Image Verification & Processing” now correctly stores “Memory Image Verification & Processing”). - Settings Import/Export: Fixed runbooks not appearing in import preview and evidence type default runbook assignments not being exported or imported.
1.2.7 — March 22, 2026
Added
- Runbooks: New global, reusable procedural checklists that can be attached to case actions. Each runbook has a name, description, and an ordered list of steps. When attached to an action, a snapshot of the runbook steps is stored with per-step completion tracking. Runbooks are managed in System Settings alongside case types and evidence types. API:
GET/POST /api/runbooks/,GET/PUT/PATCH/DELETE /api/runbooks/:id/. - Runbook Attachment on Actions: Actions can have a runbook attached via the
runbook_slugfield when creating or updating a todo item. Clicking a runbook-attached action opens a modal showing the step checklist. Steps can be individually toggled as complete. Runbooks work as passive checklists — completing all steps does not auto-complete the parent action. - Workflow Runbook Integration: Workflow decision trees now support an “Attach runbook” result type alongside “Spawn action”, “Complete workflow”, and “Follow-up question”. When a workflow resolves to a runbook-attached terminal, the spawned action automatically has the selected runbook initialized.
- Runbook Status in Timeline: When an action with an attached runbook is marked as completed, the
TODO_COMPLETEDtimeline event includes runbook progress. Fully completed runbooks show “completed”, partial ones show “X out of Y steps completed”. The timeline renders a styled badge (green for complete, amber for partial) below the action description. - Playbook Designer: New full-screen visual editor for case type playbooks, replacing the previous modal-based editor. Features a scrollspy phase index, inline workflow tree editing with hierarchical connector lines, drag-and-drop action reordering, and a Visual/JSON toggle with syntax-highlighted JSON editor supporting line numbers. The JSON editor enables copy-paste workflows for LLM-assisted playbook drafting. Automatically resolves
phase_ordertophase_idwhen pasting JSON from settings exports. - Runbook JSON Editor: Runbook editing in System Settings now includes a Visual/JSON toggle, matching the playbook designer pattern. Enables bulk editing and LLM-generated runbook import via JSON.
- MCP: Runbook Tools: New
manage_runbook_stepsMCP tool for toggling runbook step completion. Theget_reference_datatool now supports therunbooksdata type. Workflow resolution viamanage_workflowhandles runbook-attached terminals. - Settings Export/Import: Runbooks are included in system settings export and import alongside case types, evidence types, and other configuration data.
- Spur.us Enrichment Provider: New IP intelligence enrichment provider (13th total). Spur specializes in unmasking anonymized infrastructure — residential proxy detection, VPN/Tor attribution (1000+ services), bot detection, and deep contextual IP data. Enrichment results are rendered in a structured key-value layout with risk indicators, tunnel details, client intelligence, and direct links to Spur.
- Enrichment History & Change Detection: Re-running enrichments now preserves historical snapshots when meaningful data changes are detected. Each provider defines which fields are transient (counters, timestamps) versus stable intelligence. When a re-enrichment produces different results, the previous data is saved as a snapshot. Investigators can browse revision dates per provider with inline change highlighting (amber left-border markers on changed fields). No history is stored when results are unchanged.
- IOC Search-on-Add: The Add IOC modal now performs a debounced background search as the investigator types. If the IOC already exists in the registry, an info banner shows the case count, classification, confidence, TLP, tags, and first seen date. The classification, confidence, TLP, and tag fields are locked to the existing global values (editable only from the IOC intelligence page). Expired indicators are shown with an expiration notice; revoked indicators are excluded from matches.
- Anonymized Cross-Case IOC Associations: The IOC intelligence page and sidebar now show case associations the investigator cannot access. Restricted cases display only the case number, status, and lead investigator name with a lock icon and “Contact for details” prompt. This surfaces cross-case correlation signals while maintaining case-level separation of duties. The MCP
get_correlated_indicatorstool also returns restricted case data.
Changed
- Case Types Renamed to Playbooks: The System Settings tab for case types is now labeled “Playbooks”. The edit button opens the full-screen Playbook Designer instead of the modal editor. The create button links to the Playbook Designer with the label “Create New Case Type Playbook”. Evidence types retain the existing modal editor.
- Report Editor — Copy Full Report: New “Copy Full Report” button in the report editor sidebar copies all non-excluded sections with content to the clipboard as a single Markdown document, enabling quick export to external platforms.
- Report Editor — QA Workflow Improvements: The “Ready for QA” button has been renamed to “Mark as Ready for QA” for clarity. Sections in the “Ready for QA” state now show a “Return to Draft” button, allowing investigators to revert without completing and then revoking QA.
Security
- Dependency Pinning with Hash Verification: All Python dependencies are now managed via pip-tools with
--generate-hashes. The lockfile (requirements.txt) includes SHA256 hashes for every package, ensuring pip refuses to install packages whose content doesn’t match the verified hashes. This protects against supply-chain attacks where a malicious actor uploads a compromised package under an existing version number. - CI Vulnerability Scanning: Added
pip-auditjob to the CI pipeline. Docker image builds are now blocked if any Python dependency has a known vulnerability with an available fix. This runs automatically on every push and pull request to the main branch.
1.2.6 — March 18, 2026
Added
- Webhook: CAN Report Trigger: New
can_report_updatedwebhook event fires when a CAN (Conditions, Actions, Needs) report is created. Providescan.*template variables (conditions,actions,needs,version,created_by,created_at) for flexible payload formatting. - Webhook: User Notification Trigger: New
user_notificationwebhook event fires when an actionable in-app notification is created (case assignments, IOC correlations, timer warnings, etc.). Toast messages (UI feedback) are excluded. Providesmessage.*template variables (title,body,type,sender_name,target_model,target_id,case_id,created_at). Enables external alerting via email (Mailgun, SendGrid) or messaging (Slack) when users receive important notifications. - Webhook: User Context Variables: New
user.*template variables available across all webhook triggers. On case-scoped events,user.*is populated from the case's lead investigator. On user notification events, it's populated from the notification recipient. Includesid,username,email,first_name,last_name,phone_number,timezone,slack_user_id, andslack_username. - Webhook: Form Data Support: Webhooks can now send payloads as
application/x-www-form-urlencodedinstead of JSON. This enables direct integration with APIs that require form-encoded requests, such as Mailgun's email sending API. Configurable per webhook via a "Send as Form Data" toggle. - Case Import/Export: Full case data can be exported as JSON and imported into the same or another DFIRe instance. Export via
GET /api/cases/<id>/export/with standard authentication and RBAC. Import viaPOST /api/cases/import/(create new case) orPUT /api/cases/<id>/import/(update existing). Includes indicator import for case-associated IOCs. Frontend import modal with file upload, diff preview, and create/update flow. Original case number preserved as a case note on import. - Case Description on Case Report Page: The case description field has been elevated from the collapsed sidebar to the top of the Case Report tab, giving it a prominent position as the opening paragraph for anyone reviewing a case. The description now renders full Markdown (headings, bold, links, tables, code blocks, etc.) via the same
MarkdownDisplaycomponent used for case notes and CAN reports. - API Documentation Summaries: All REST API endpoints now include human-readable
summaryannotations in the OpenAPI schema, improving the ReDoc documentation at/api/docs/with clear, descriptive operation titles. - My Actions Filter: New “My Actions” filter button on the incident Actions tab shows only actions assigned to the current user. Displays a count of open assigned actions in the button label. Filter state is preserved in the URL for deep-linking.
- Open Actions Badge: Incident case cards on the dashboard now display a clickable “My actions” badge when the current user has open actions assigned. Clicking the badge navigates directly to the case’s Actions tab with the My Actions filter pre-selected.
- Server Time Clock: The application header now displays a live server time clock with timezone, visible across all views.
- Organization Logo: Administrators can upload a custom organization logo in Global Settings that replaces the default DFIRe logo in the application header. The same logo is used on printable report title pages. Falls back to the DFIRe logo when no custom logo is uploaded.
- Adversary Activity Timeline Events: Manual timeline entries can now be marked as adversary activity to distinguish attacker actions from IR team actions. Adversary events are visually distinct with a red dashed border, skull icon, and dark background on the timeline. The printable investigation report uses a red background with skull icon for adversary entries. A dedicated “Adversary Activity” filter option is available in the timeline filter dropdown. The adversary flag can be toggled when creating or editing manual entries, and is preserved through case export/import. MCP tool support included.
Improved
- Webhook: Parallel Delivery: Multiple webhooks listening for the same event are now delivered in parallel via separate background tasks, instead of serially. A slow or timed-out webhook no longer blocks delivery to others.
- Webhook: Default Payload Completeness: IOC data (
ioc.*) and compliance timer data (timer.*) are now included in the default payload when no custom template is configured. Previously these were silently dropped. - Webhook: Delivery Record Traceability: The
event_idfield on delivery records now falls back through all context ID types (case, timeline event, indicator, message, CAN report) instead of only case and timeline event. IOC and notification webhook deliveries are now traceable. - Webhook: Test Delivery User Context: The test delivery button now populates
user.*with the logged-in user's real data instead of dummy values, making test emails and messages more predictable. - Incoming Webhooks: Deprecated in favor of outgoing webhook triggers with the new event types. Existing incoming webhook endpoints remain functional but display a deprecation banner in the UI and return a
Deprecationresponse header. - Case Report Page Consistency: All three sections on the Case Report page (Case Description, CAN Report, Case Report) now have consistent amber icons in their headings, improving visual flow and navigation.
- Action Done Button Clarity: The “mark as done” button on in-progress actions now uses a pulsing ring animation instead of a spinning border (which looked like a loading indicator) and includes an explicit “Done” label below the icon.
- Action Completion Modal: The “Dismiss” button on the action completion note modal has been renamed to “Skip note” to clarify that clicking it skips the optional note rather than dismissing the completion.
- OpenAPI Schema: Case Indicators: The
POST /api/cases/{id}/indicators/endpoint now correctly documents the requiredvalueandstix_typefields in the request schema, along with all optional fields (classification,confidence,tlp,tags,context,source,decompose,valid_until,publish). - OpenAPI Schema: Compliance Timers: The
POST /api/cases/{id}/timers/endpoint now documents the requiredtimer_definition_idand optionalstart_timefields in the request schema. - OpenAPI Schema: Action Endpoints: The create, update, and assign action endpoints now document their actual request fields instead of incorrectly showing the full
CaseSerializerschema. - Report Section Template: The “Conclusions and Recommendations” report section is now included in investigation-mode cases (was previously incident-only). Existing investigation reports will pick up the section automatically on next access.
- API Key Expiration: The API key expiration date picker now uses a date-only selector instead of datetime, with the time automatically set to 23:59. API key lifetime is measured in days.
- License Settings: The “Send usage data” toggle is now hidden when an offline license is active, since offline systems never contact the license server. Version upgrade release notes now render as Markdown instead of plain text.
- Tenant Settings: The Identity and Reporting sub-tabs have been consolidated into a single page. The report logo upload has been renamed to “Organization Logo” and is now also used in the application header.
Removed
- Legacy Case Export API: The standalone Case Export API key system (
CaseExportApiKeymodel, dedicated endpoints, and settings UI) has been removed. Case export is now handled by the standard authenticated API at/api/cases/<id>/export/using User API Keys or session authentication with full RBAC enforcement.
Fixed
- Attachment Item Link: Fixed chunked upload silently dropping the
itemparameter when bothcaseanditemwere provided. The upload now correctly links the attachment to the specified evidence item. Additionally, theitemfield on attachments is now writable viaPATCH, with validation ensuring the item belongs to the same case. - Workflow Export/Import: Fixed case export flattening workflow actions to plain todo items, losing the
workflow_definition(decision tree structure) andworkflow_statefields. Both export and import now preserve the full workflow JSON so decision trees survive round-trips between instances. - Webhook: Custom Headers Not Saving: Fixed custom headers being cleared on save due to an asymmetry between how
EncryptedJSONFieldreads (decrypted dict) and writes (expects encrypted input). The serializer now correctly round-trips custom header values. - Webhook: Bulk Notifications Not Triggering: Notifications created via
bulk_create()(e.g., when a user is added to a case team) did not fire theuser_notificationwebhook because Django'spost_savesignal is not emitted for bulk operations. Added explicit webhook event queuing in the notification utility functions. - Case Detail: Current User ID: Fixed the current user ID not being resolved correctly on the case detail page. The stored user object uses
user_idbut the code was readingid, causing user-specific features (action assignments, action filtering) to silently fail. - Backdated Timeline Event Phase: Fixed manual timeline entries always being tagged with the case’s current phase, even when backdated to a time when a different phase was active. Backdated events now resolve their phase by examining phase change history — if the event falls between two phase changes, it is assigned to the phase that was active at that time. Events predating all phase changes are assigned to the first configured phase.
1.2.5 — March 15, 2026
Added
- MCP Server: Built-in Model Context Protocol server that enables AI agents to act as virtual incident responders. Connect any MCP-compatible client (Claude Code, Google Antigravity, or other Streamable HTTP clients) to manage cases, track evidence, triage IOCs, and coordinate incident response through natural language. 48 tools across 9 groups (cases, items, notes, actions, indicators, timeline, timers, reports, search) with full RBAC enforcement, audit logging, and per-group enable/disable controls. See MCP Server documentation.
- MCP Resources: Contextual documentation resources served via MCP for case workflows, IOC management, incident phases, actions & workflows, compliance timers, and reports. Dynamic configuration resources for case types and item types with live schema data.
- MCP Prompt Templates: Pre-built workflow prompts for incident response, IOC triage, and case handoff that MCP clients can use as starting points for common tasks.
- MCP Settings UI: Administration page under Settings > Integrations > MCP Server for enabling/disabling the server and toggling individual tool groups. Displays endpoint URL and connection instructions.
- MCP Server Documentation: New documentation page covering tool groups, resources, prompts, client configuration, authentication, security model, and protocol details.
Improved
- Investigation Report Layout: Sidebar and report key-value layouts changed from two-column to stacked label-above-value to prevent overflow with long values (URLs, hashes).
- Report Status Indicators: Report version and Draft/Final status now displayed on the title page cover. Report sections that have not passed QA review show [DRAFT] or [REVIEW] indicators with background tinting.
- Report Title Page: Lead investigator added to the investigation team list. Fixed tenant organization name not displaying. Removed redundant page break from case details section.
- Print Preview: Added visible page break indicators in browser preview (hidden in print output).
Security
- SSRF Redirect Protection: Disabled HTTP redirects (
allow_redirects=False) on IOC webhook triggers and SIEM log sender to prevent redirect-based SSRF. Added SSRF validation on SIEM sender endpoint URLs and OIDC profile picture URLs. - RBAC Hardening: Enrichment configuration now requires superuser access (was
dfireRolePermission). Case export views enforce Tier 1 capability check (core.view_case). CaseNote creation scopes case lookup viaCase.objects.for_user(). - Timeline Write Protection: Removed admin bypass on timeline events for CLOSED/ARCHIVED cases. Write protection is now absolute regardless of permission level.
- Audit Logging Expansion: API key authentication failures now logged to AuditLog with key prefix, IP, and attempt count. Permission denials create
SECURITY_VIOLATIONaudit entries. Webhook, TAXII, timer, and SIEM sender mutations now audit-logged. System settings audit is fail-closed. - WebSocket Connection Limits: Concurrent WebSocket connections limited to 20 per user using atomic cache counters.
- IOC Extraction Rate Limiting: IOC text extraction endpoint rate-limited to 30 requests per minute.
- API Key Brute-Force Race Safety: Brute-force counter uses atomic
cache.incr()to prevent race conditions under concurrent requests. - Case Export Timing Normalization: Case export API key authentication uses constant-time dummy comparison on hash miss to prevent timing side-channel attacks.
- MCP Security Hardening: Tool error messages no longer expose exception details to clients. MCP registry sanitizes arguments to only schema-declared keys. Prompt arguments validated as numeric to prevent injection. Tool execution enforces permissions via registry before execution.
- XSS Prevention: Applied
sanitize_markdown()to all user-writable text fields across MCP tools (title, name, location, external_id, public_notes, context) to prevent stored XSS. - Case Update Write Protection Fix: Fixed a gap where field updates combined with status changes could bypass write protection. Field updates now always occur while the case is in OPEN state.
1.2.4 — March 14, 2026
Added
- User API Keys: Per-user API keys for programmatic access to the DFIRe REST API. Keys use Bearer token authentication (
Authorization: Bearer dfire_ak_...) and inherit the user's full RBAC permissions. Raw keys are shown once at creation and stored as SHA-256 hashes. Includes enable/disable, regeneration, expiration enforcement, and per-key usage tracking (last used timestamp, IP address, total requests). - Service Accounts: Dedicated user accounts for automated integrations. Service accounts authenticate exclusively via API key — password login and SSO are blocked. Hidden from non-admin user listings.
- API Key Management UI: New API Keys tab in user settings for creating, viewing, enabling/disabling, regenerating, and deleting keys. Administrators can manage any user's keys from the user detail view.
- Admin Key Revocation on Password Change: When an administrator changes another user's password, all of that user's enabled API keys are automatically disabled as a security measure.
- API Key Tenant Policy: Configurable limits in Global Settings for maximum keys per user (default 3) and maximum key lifetime (default 365 days).
- Built-in API Documentation: Interactive API reference at
/api/docs/(ReDoc) and downloadable OpenAPI 3.0 schema at/api/docs/schema/, powered by drf-spectacular. Both endpoints require authentication. Links available in Global Settings. - API Access Documentation: New documentation page covering API key creation, service accounts, authentication examples, and security best practices.
Improved
- OpenAPI Schema Annotations: Added
@extend_schemaannotations to ~70 endpoints including binary downloads, CSV exports, SSE streaming, chunked uploads, IOC bulk operations, search, and statistics for accurate auto-generated API documentation. - Global Settings UI: Added API Key Policy section (max keys per user, max lifetime) and API Documentation links to the tenant settings page.
- Configurable LLM API Endpoints: All LLM providers (OpenAI, Anthropic, Gemini, Azure OpenAI, GitHub Models) now expose an optional API Base URL field in the settings UI. This enables connecting to any OpenAI API-compatible service (e.g. Together AI, Groq, Mistral, DeepSeek, Fireworks, Ollama, vLLM, LM Studio) by setting a custom base URL on the OpenAI provider, or routing through organizational API proxies. Each provider shows the default endpoint as placeholder text and contextual help. All custom URLs are validated against SSRF rules.
Security
- API Key Brute-Force Protection: Cache-based per-IP rate limiting on API key authentication failures. After 10 failed attempts within 5 minutes, further authentication is blocked for 10 minutes. Successful authentication resets the counter.
- Timing Attack Normalization: API key hash comparison uses
hmac.compare_digest()to prevent timing side-channel attacks. Hash miss path performs a dummy comparison to normalize response time.
1.2.3 — March 9, 2026
Added
- Slack IOC Commands: Three new
/dfireslash commands for managing Indicators of Compromise directly from Slack case channels:/dfire ioc— List all IOCs linked to the case with type, value, classification, confidence, TLP, tags, and context notes. Each entry links to the IOC intelligence page in the web UI./dfire ioc add [value]— Open a modal form to add a new IOC to the case. Supports STIX type selection, classification, confidence, TLP, context notes, and comma-separated tags. The value field can be pre-filled from the command argument. UsesIndicatorService.add_to_case()with full auto-decomposition and cross-case correlation./dfire ioc update <n>— Open a modal form to edit an existing IOC's classification, confidence, TLP, tags, and case-private context note. The IOC number corresponds to the list order from/dfire ioc.
Fixed
- Settings Test Connection Field Clearing: Fixed a bug where clicking "Test Connection" in system settings (Slack, LLM, Storage, etc.) would clear all configuration fields, forcing re-entry. Root cause was an unstable React context value in
ToastProviderthat triggered unnecessary re-renders and data re-fetches on every toast notification. Resolved by memoizing the context value. - Slack Enable Toggle Missing: Restored the missing Enable/Disable toggle on the Slack Integration settings page. The
enabledfield existed in state but had no UI control, making it impossible to turn the integration on.
1.2.2 — March 6, 2026
Added
- LLM Backend Configuration: LLM integration with support for OpenAI, Anthropic, Google Gemini, Azure OpenAI, and GitHub Models. Configurable model, API key, base URL, temperature, and max tokens from the Settings UI. Connection testing from settings with real-time status indicator.
- Case Data JSON Export: New
/api/cases/{id}/export/json/endpoint for exporting structured case data as JSON, authenticated via API key. Intended for external integrations and LLM context feeding. - AI-Powered CAN Report Generation: Generate Conditions, Actions, and Needs (CAN) reports using the configured LLM provider. Case data is automatically minified for token efficiency, and the AI returns structured JSON with Markdown content for each section.
- AI-Powered Report Section Generation: Generate content for individual investigation report sections using AI. Each section template can have its own AI prompt with support for
{case_data},{section_title}, and{writing_guide}template variables. - AI Prompt Transparency: CAN report settings expose both the built-in system message (read-only) and the user-editable prompt, so administrators can understand exactly what is sent to the LLM. Additional free-text instructions can be provided per-generation.
- Default Section AI Prompt: Built-in default prompt template for report section AI generation, available via a "Use Default Prompt" button in section template settings. Provides a starting point that administrators can customize per section.
- Case Data Minification for LLM: Post-processing pipeline that optimizes case data before sending to the LLM: strips empty/null values, removes internal UUIDs, filters inactive todo items, simplifies indicator data to analytical essentials (classification, confidence, enrichment conclusions), limits CAN report history, and removes UI-only flags.
Improved
- Report Section Templates UI: Refactored the Report Section Templates settings page from a table-and-modal layout to an expandable card layout. Multiple cards can be open simultaneously for easy comparison. Collapsed cards show a summary of configuration (order, title, type, case modes, page break, AI status). Inline editing with larger text areas for writing guides, default content, and AI prompts.
- LLM Settings UI: Free-text model input (replacing dropdown) for flexibility with any LiteLLM-supported model string, temperature and max tokens controls, and a clear API key button.
Security
- Case Export Fail-Closed Audit: The case data JSON export endpoint follows the project's fail-closed audit pattern — if the audit log write fails, the export is blocked with a 503 response. This ensures every export is traceable, especially for API key-authenticated requests where the audit trail is the primary accountability mechanism.
- Case Export & LLM Rate Limiting: Scoped rate throttles on the case export endpoint (60 req/min) and AI report generation endpoints (10 req/min) to prevent bulk data exfiltration via compromised API keys and limit LLM provider cost exposure from rapid-fire generation requests.
- LLM Endpoint SSRF Validation: Custom LLM
api_baseURLs are validated against the same SSRF rules used for outgoing webhooks, blocking loopback (127.0.0.0/8), link-local (169.254.0.0/16, including cloud metadata at 169.254.169.254), and self-referential addresses. Applied on both configuration save and connection test. - LLM Configuration Audit Logging: All changes to LLM configuration (provider enable/disable, model changes, API key rotations, base URL changes) are recorded in the audit log with field-level detail. API key values are excluded from the audit entry; only a boolean
api_key_changedflag is logged. - Scoped Enrichment Data Export: Case data JSON export includes only enrichment metadata (provider, severity, timestamp) rather than raw provider response payloads, reducing the data surface area and preventing leakage of full threat intelligence reports through the export API.
- Markdown Sanitization Protocol Allowlist: The
sanitize_markdown()function now restricts linkhrefvalues tohttp,https, andmailtoprotocols, blockingjavascript:URIs. This hardens all Markdown output paths including LLM-generated report content. - AI Instruction Length Limit: Free-text
additional_instructionson AI generation requests are capped at 10,000 characters to bound token usage and prevent cost amplification through oversized prompts.
1.2.1 — March 2, 2026
Security
- TLP:RED Enforcement: MISP feed and TAXII collection queries now hard-filter TLP:RED indicators at the database layer, preventing accidental publication regardless of
is_publishedstate - OIDC Issuer Validation: Added
issclaim verification in OIDC token validation using PyJWT'sissuerparameter to prevent token substitution from rogue identity providers - Dead Token Code Removal: Removed unused JWT token generation code (
generate_token/decode_token) that referenced a hardcoded secret key - PKCE Support: OIDC authentication now generates and validates PKCE code challenges (RFC 7636) stored in the session, with graceful fallback for providers that don't support it
- Azure AD Regex Fix: Tightened OIDC issuer URL regex to
^https://login\.microsoftonline\.com/[a-f0-9-]{36}/v2\.0$, preventing open-redirect-style issuer spoofing - Jira SSRF Validation: Added
validate_webhook_url()SSRF check and Jira Cloud URL enforcement (*.atlassian.net) to Jira instance URL validation - IDOR Fixes: Scoped collaboration view and audit log item_context lookups through
Case.objects.for_user(user)to prevent unauthorized access via direct object IDs - WebSocket Protocol Fix: Rate-limited connections now set a
scope['rate_limited']flag and close after ASGI accept, fixing a protocol violation that sentwebsocket.closebefore handshake - WebSocket Message Validation: Added pre-parse size limit (10KB), JSON depth check (max 5), and message type enumeration to all WebSocket consumers
- WebSocket Per-Message Rate Limiting: Added sliding-window rate limiter (30 msg/s) with auto-disconnect after 5 consecutive violations
- WebSocket Permission Re-validation:
report_presenceandediting_lockhandlers now re-check case permissions before processing - Nginx Host Header: Replaced hardcoded
proxy_set_header Host localhostwithproxy_set_header Host $hostacross all proxy locations - Jira Inbound Sanitization: Applied
sanitize_markdown()to inbound Jira summary and assignee display names to prevent stored XSS - Webhook Payload Storage: Webhook delivery logs now store payload hash and size instead of full masked payload to reduce database bloat
- Webhook Regex Safety: Content filter regex execution uses Python 3.12
re.TIMEOUTwhen available, with input truncation fallback (64KB max) - IOC Enrichment Rate Limiting: Added per-provider rate limiting (30 req/min default) via Django cache to prevent API key exhaustion
- Session Key Validation: Added
request.session.save()aftercycle_key()in login and OIDC callback to ensure the new session key is persisted - Profile Picture Size Limit: Profile picture downloads now use streaming with a 32MB hard limit to prevent memory exhaustion
- CORS/CSRF Production Hardening: Production deployments without
CORS_ALLOWED_ORIGINSlog a warning and reject cross-origin requests instead of falling back to localhost.CSRF_TRUSTED_ORIGINSauto-derives fromCORS_ALLOWED_ORIGINSwhen not explicitly set. Non-HTTP services (qcluster, slack-socket) no longer require CORS/CSRF configuration to start - Docker Image Pinning: Added CI/CD digest pinning comments to all
FROMdirectives in both backend and frontend Dockerfiles - Docker File Permissions: Added
chmod 750on/app/mediaand/app/staticfilesin the backend production image - Log Sanitization: Added
SanitizeFilterto the logging pipeline that masks Authorization, Cookie, X-CSRFToken, and X-API-Key header values in log output - sessionStorage Migration: User profile cache moved from
localStoragetosessionStorageto scope data to the browser tab session - Frontend WebSocket Validation: Added type guard for incoming WebSocket messages (validates
typeof message.type === 'string') before dispatch - RBAC Hardening:
GroupViewSetandPermissionViewSetnow usedfireRolePermissioninstead ofDjangoModelPermissions, with a lockout prevention guard that blocks removingchange_groupfrom the last group that has it
Fixed
- CI Key Length: CI environment
SECRET_KEYandCREDENTIAL_ENCRYPTION_KEYvalues lengthened to meet the new 32-character minimum, andALLOWED_HOSTS,CORS_ALLOWED_ORIGINS,CSRF_TRUSTED_ORIGINSadded to CI test environment - Non-HTTP Service Startup:
qclusterandslack-socketservices no longer crash on startup whenCORS_ALLOWED_ORIGINSandCSRF_TRUSTED_ORIGINSare not set, since these services do not serve HTTP requests
1.2.0 — February 26, 2026
Added
- IOC Registry: Full Indicator of Compromise management subsystem for tracking, enriching, and correlating threat intelligence across cases.
- Global tenant-level indicator registry with 17 STIX 2.1 SCO types (IPv4, IPv6, domain, URL, email, file hash, MAC address, AS number, and more)
- Classification (unknown, benign, suspicious, malicious) and confidence (low, medium, high) tracking per indicator
- Automatic deduplication via normalized values with unique constraint on
(value_normalized, stix_type) - Hierarchical decomposition: URLs decompose into domain and apex domain, emails into domain, subdomains into parent domain, IPs into containing CIDR ranges
- Retroactive parent-child adoption when new indicators are added
- PostgreSQL full-text search with GIN index across indicator values, types, notes, and tags
- Tag-based organization with JSON array tags per indicator
- Case-scoped associations with private context notes visible only to the case team
- Cross-case correlation notifications when an IOC appears in multiple cases
- IOC included in global full-text search results
- Custom permissions:
manage_indicators,export_indicators,import_indicators
- IOC Enrichment: Multi-provider threat intelligence enrichment framework with 12 providers.
- Built-in providers (no API key required): DNS lookup, WHOIS lookup
- Threat intelligence providers: VirusTotal, AbuseIPDB, Shodan, GreyNoise, AlienVault OTX, URLScan.io
- Abuse.ch providers (shared API key group): URLhaus, MalwareBazaar, ThreatFox
- Reputation providers: Google Safe Browsing
- Per-provider enable/disable, API key management, and configurable TTL for cache staleness
- Provider connectivity test from settings UI
- Finding severity classification (clean, suspicious, malicious) per enrichment result
- Background enrichment via Django-Q2 with TTL-based re-enrichment
- IOC Import/Export: Multiple format support for bulk IOC management.
- CSV import and export (global and per-case)
- STIX 2.1 bundle import and export with SCO and SDO objects
- Plaintext import with automatic IOC extraction
- IOC extraction from free text using regex patterns for IPv4/IPv6, domains, URLs, emails, file hashes, MAC addresses, and CVE identifiers
- Extraction review modal for selecting which candidates to add
- IOC Frontend: Complete React UI for IOC management.
- Global IOC Dashboard with chained filters (STIX type, classification, confidence, tags, search) and pagination
- Intelligence Page per indicator with sidebar and tabbed layout (Details, Relations, Enrichment, Respond)
- Enrichment panel with multi-provider verdict banners and auto-poll during active enrichment
- Hierarchy tree visualization for IOC decomposition
- Case IOC tab with association management and private context notes
- 6 modals for adding, importing, extracting, and reviewing IOCs
- IOC Enrichment settings panel under System Settings > Integrations
- IOC count shown on dashboard case cards and case detail header
- Automatic STIX type detection from pasted values
- IOC Webhooks: 6 new webhook event types for IOC lifecycle events.
ioc_added,ioc_classification_changed,ioc_classified_malicious,ioc_classified_suspicious,ioc_classified_benign,ioc_correlation- Full IOC context in webhook payloads including STIX 2.1 SCO/SDO export objects for MISP integration
- Webhook Trigger Execution model for manual trigger button tracking with generic scope design (ioc, case, entity)
- Dynamic trigger event types configurable from enrichment settings
- IOC WebSocket Events: Real-time
ioc_added,ioc_removed,ioc_updatedevents on case channels. - IOC Timeline Events:
IOC_ADDEDandIOC_CLASSIFICATION_CHANGEDevent types with full metadata. - IOC Correlation Requests: Workflow for cross-case IOC sharing with pending/accepted/declined/expired states and context messages.
- Webhook Secrets in Custom Headers: Custom header values now support
{{secret.name}}template syntax for referencing webhook secrets, enabling secure header-based authentication (e.g., custom API keys). - Webhook Performance: Signal-level cache check avoids per-model-save database query when no webhooks are configured (60s TTL).
- Webhook Queryset Optimization: Webhook list endpoint now uses annotated delivery counts and prefetched recent deliveries, eliminating 3 separate queries per webhook.
- Incoming Webhook Lead Investigator: Incoming webhook payloads can now include
lead_investigator_idto override the default lead investigator when creating cases. - Timer Breach History: Timer resets now preserve a complete history of previous breaches in an append-only
breach_historyJSON field. Each entry records the breach timestamp, duration, who reset it, and when. - Incoming Webhook Payload Reference: Settings UI now documents all accepted JSON fields with example curl command.
Changed
- Case Queryset Optimization: Case list endpoint now annotates
indicator_countandtotal_attachment_countto avoid N+1 queries. - Search Optimization: Global search uses lazy QuerySet for visible cases instead of materialized ID list for better database query plans.
- EncryptedJSONField Wildcard:
EncryptedJSONFieldnow supports'*'wildcard inencrypted_keysto encrypt all string values in a dict.
Security
- Adversarial Security Review: 14 findings addressed from a comprehensive second-pass security audit.
- (VULN-001) Report ViewSet permission bypass:
InvestigationReportViewSetextendedviewsets.ViewSet(notModelViewSet), causing the Tier 1 capability check to be skipped entirely. Fixed by addingqueryset = InvestigationReport.objects.none()for model discovery. - (VULN-002) Archived case access via nested routes: Nested route permission checks (e.g.,
/api/cases/<id>/timers/) did not verifyview_archived_casespermission for archived cases. Added explicit gate before standard access check. - (VULN-003) todo_checklist direct write:
todo_checklistwas writable via case PATCH, bypassingTodoServicevalidation and audit logging. Added toread_only_fields. - (VULN-004) Timer breach history loss on reset: Resetting a breached timer cleared the
timer_breachedflag with no record of the breach. Timer reset now records breach events in an append-only history field before clearing. - (VULN-005) Timer state fields writable via API:
start_time,completed_time,is_completed,timer_breached, andalerts_sentwere writable via PATCH. Added toread_only_fields. - (VULN-007) Webhook SSRF via HTTP redirect: Webhook delivery followed HTTP 307/308 redirects, allowing SSRF to bypass URL validation done at config time. Added
allow_redirects=Falseto all webhook HTTP requests. - (VULN-009) Webhook content filter ReDoS: Admin-supplied regex for webhook content filtering had no timeout or length limit, allowing catastrophic backtracking to hang the Q-worker. Added serializer-level regex validation (500 char limit), thread-based 2-second timeout, and 10KB input cap.
- (VULN-010) Webhook custom headers stored unencrypted: Custom header values (which may contain API keys) were stored in plaintext. Changed
EncryptedJSONFieldto use wildcard encryption for all values. - (VULN-011) Deprecated file_key persisted in database: The
file_keycolumn inChunkedUploadSessioncontained derived encryption key material. Removed column via data migration (null-out then drop) and replaced with on-demand HKDF derivation. - (VULN-012) Filename injection in Content-Disposition: Upload filenames were not sanitized, allowing path traversal and HTTP header injection. Added
sanitize_filename()applied at upload init, photo upload, and download. - (VULN-013) Hash corruption on decryption failure:
_calculate_file_hash()silently swallowed decryption errors, producing a hash over incomplete data that was stored as correct. Removed the try/except so decryption failures propagate and mark the upload as failed. - (VULN-015) Statistics aggregate data leak:
StatisticsService.calculate()used unscopedCase.objects.filter(), exposing aggregate counts of all cases to any user withview_statisticspermission. Querysets are now scoped throughCase.objects.for_user(user). - (VULN-016) Azure AD multi-tenant token acceptance: Multi-tenant OIDC configuration accepted tokens from any Azure AD tenant. Added tenant ID allowlist validation on the token's
tidclaim. - (VULN-017) OIDC nonce bypass: Tokens missing the nonce claim were silently accepted when DFIRe sent one. Now rejected with a warning log.
- (VULN-001) Report ViewSet permission bypass:
- Cloud metadata SSRF protection: Added
169.254.0.0/16(link-local) to blocked webhook URL ranges, preventing SSRF to AWS/GCP/Azure instance metadata endpoints. - Incoming webhook rate limiting: Redis-based IP rate limiting (30/min, 5/sec burst) added to incoming webhook endpoint, checked before any database work.
- WebSocket session re-validation: WebSocket consumers now re-verify session validity (active account, non-expired session) on each periodic ping.
- WebSocket middleware ordering: Auth middleware now runs before rate limiting so the rate limiter can identify users by ID for per-user limits.
- WebSocket deactivated user blocking: Deactivated users are now rejected during WebSocket authentication.
- Jira comment sanitization: Jira comment author and body are sanitized via
sanitize_markdown()before storage. - Entity and timeline XSS prevention: Added
sanitize_markdown()validation toLegalEntitySerializer(description, contact_info, address) and timeline serializers (subject, details). - SSO config secret masking:
sso_configsecrets (client_secret,private_key,signing_key) are masked with***in API responses. - Startup key validation:
SECRET_KEYandCREDENTIAL_ENCRYPTION_KEYmust each be >= 32 characters and must differ. Validated at startup withValueError. - ngrok production guard:
ALLOW_NGROK=truenow requiresDEBUG=True; ignored in production with a warning log.
1.1.0 — February 18, 2026
Added
- Jira Cloud Integration: Full bidirectional integration with Jira Cloud for case and action management.
- Export cases as Jira Epics with rich metadata (severity, case type, lead investigator, backlink to DFIRe)
- Export actions as configurable Jira issue types (Task, Story, Bug, etc.) linked to parent Epic
- Export evidence items as Jira Tasks
- Bulk export multiple actions in one operation
- Bidirectional status sync for both actions and Epics (case status)
- Bidirectional assignee sync with automatic user mapping
- Bidirectional phase label sync (incident phases as Jira labels)
- Automatic ticket discovery — new tickets created in Jira under a linked Epic are auto-imported as DFIRe actions
- Jira comments fetched and included in closing notes when actions are completed
- Conflict detection with DFIRe-wins resolution when both sides change between syncs
- Circuit breaker pattern prevents hammering Jira when unreachable
- Rate limiting with exponential backoff for Jira API calls
- Batch sync operations for efficient polling
- Jira Automation: Configurable automation options to reduce manual export work.
- Auto-create Jira Epic on case creation (triggered from both REST API and Slack)
- Auto-export action to Jira when started, with automatic In Progress transition push
- Orphan gathering: existing Jira tasks are automatically linked to Epic when it is created
- Jira Status Mapping: Three-tier priority system for DFIRe-to-Jira status mapping.
- Explicit
to_jiraoverrides (highest priority) for admin control - Auto-derived reverse mapping from the Jira-to-DFIRe configuration
- Hardcoded defaults as fallback (including
ignored->Rejected) - Editable Jira-to-DFIRe dropdowns with read-only reverse preview in Settings UI
- Explicit
- Jira User Mapping: Automatic and manual mapping between DFIRe and Jira accounts.
- Auto-map by email address with normalized full name fallback (handles diacritics, word order)
- Hourly polling for new user matches
- Manual mapping via admin UI with Jira user search
- Jira Settings UI: Full admin configuration panel in System Settings.
- Credentials, project key, issue type selection with Discover
- Sync interval, frontend URL for backlinks
- Automation toggles with dependency warnings
- Status mapping editor
- User mappings table with auto-map button
- Slack-Jira Integration: Jira awareness in Slack slash commands and modals.
/dfire jira show— display all Jira items linked to the case/dfire jira create case— create Jira Epic for the case/dfire jira create <n>— create Jira ticket for an action- Jira tags on action lines in
/dfire actions(clickable link to Jira issue) - Jira sync triggers on
/dfire take,/dfire done,/dfire skip,/dfire assign,/dfire unassign - Auto-create Epic when cases are created via Slack modal
- Conditional Jira section in
/dfire help(only shown when Jira is enabled)
- Jira Case Lifecycle Hooks: Jira Epic status mirrors case lifecycle changes.
- Case closed: closure comment added to Epic, Done transition pushed
- Case archived: all Jira links marked stale (sync stops), archive comment added
- Case reopened: stale links reactivated, In Progress transition pushed
- Feedback loop prevention via
source='jira_sync'parameter
- Jira REST API: 7 new endpoints under
/api/jira/for configuration, user mappings, and case operations. - Jira Periodic Tasks: Configurable polling interval (default 15 minutes) for status sync and ticket discovery, plus hourly user auto-mapping.
- Jira WebSocket Events: Real-time
jira_link_updatedevents broadcast to case viewers when Jira links are created, synced, or deleted — frontend auto-refreshes Jira badge state without polling. - Jira Link in Sidebar: Incident Info / Investigation Info sidebar now shows a clickable link to the linked Jira Epic (with external link icon) when Jira integration is enabled.
- Action Reassignment via UI: Clicking the assigned name on an in-progress action now opens the assignment modal for direct reassignment, removing the need to unassign and reassign via Slack commands or action reset.
- User Detail Drawer: Clicking a user row in User Accounts now opens a slide-out detail panel showing account details, active sessions (with browser and IP), recent authentication activity (login/logout/failed events with timestamps), Slack and Jira integration status, and avatar management.
- User Detail API: New
GET /api/users/{id}/detail/endpoint returns comprehensive user data including active sessions, recent auth events, and integration profiles in a single request. Queryset optimized withselect_relatedto avoid N+1 queries. - Admin Avatar Management: New
POST/DELETE /api/users/{id}/profile-picture/endpoint allows admins to upload or remove profile pictures for any user, with PIL image processing (validation, JPEG conversion, 256x256 resize). - Enhanced User List Table: User Accounts table now shows Last Login (relative time), Integrations (Jira/Slack badges), and clickable rows. User list API extended with
date_joined,last_login, andjira_linkedfields. - Settings Sidebar Reorganization: System Settings sidebar tabs reorganized into three categories (System, Integrations, Case Properties) with section headers and dividers. Tabs renamed for clarity: Tenant→Global Settings, Collaboration→Slack Integration, Jira→Jira Integration, Log Sender→Log Integration, Retention→Retention Policy, Workflow→Evidence Workflow, Lifecycle→Incident Lifecycle, Report Sections→Reporting, Flags→Triage Flags.
- Audit Log Sender: Forward audit logs to external log aggregation services (ELK, OpenSearch, Splunk, etc.).
- Multi-format payload support: JSON Batch, NDJSON, and Elasticsearch Bulk API
- HTTP Basic Authentication for endpoint credentials
- Custom HTTP headers for Bearer tokens and other authentication schemes
- Test Connection button with live response preview (status code, headers, body)
- Clear Settings to reset all sender configuration
- Circuit breaker with manual reset for fault tolerance
- Delivery history tracking with batch metadata
- Privacy notice warning about audit log data sensitivity
- Configurable batch size and timeout
- System Heartbeat: Periodic health check entries written to the audit log and forwarded to external log destinations.
- Dead man's switch pattern — distinguishes "system idle" from "system down"
- Business metrics: cases by status, evidence items, total and active users (24h)
- License metrics: status, days remaining, trial/grace period state (enables license expiry alerting)
- Database metrics: PostgreSQL size, query latency, audit log count, pending log count
- Storage metrics: file count, total size, quota usage percentage
- Health checks: Redis connectivity and latency, Django-Q2 task queue status (pending, success, failed)
- System info: application version, process uptime
- Configurable interval (5, 15, 30, or 60 minutes, default 15)
- Enable/disable toggle in Log Integration settings
- Resilient collection — individual metric failures don't block other sections
- Testing: 192 Jira tests across 36 test classes, 20 Slack-Jira integration tests, 17 security regression tests, 55 audit log sender tests, and 31 heartbeat tests (1002 total backend tests).
- Documentation: Comprehensive
docs/JIRA_INTEGRATION.mdtechnical reference covering all Jira features.
Fixed
- Modal overlay alignment: Fixed all modal and drawer backdrop overlays starting at the wrong vertical position. The global CSS rule used
top: 2rem(32px) but the header ish-16(64px). Also fixed overlays inheritingmargin-topfrom parentspace-y-*containers, which added an additional 24px offset. Allbg-black/*opacity variants are now covered by the selector.
Security
- WebSocket information disclosure (SEC-006): Dashboard WebSocket broadcasts no longer contain full serialized case data.
notify_case_updatedandnotify_case_creatednow send only the case ID to the dashboard channel — the frontend refetches via the permission-filtered REST API. Previously, all authenticated users on the dashboard could see titles, descriptions, and team details of cases they did not have access to. - CORS wildcard with credentials (SEC-007): Removed
CORS_ALLOW_ALL_ORIGINS = Truefallback that was active whenDEBUG=Trueand noCORS_ALLOWED_ORIGINSwas set. Even in development, CORS now requires an explicit origin allowlist. The previous configuration combined withCORS_ALLOW_CREDENTIALS = Trueallowed any origin to send credentialed requests. - Case status transition bypass (SEC-008): Added server-side validation for case status transitions in
CaseSerializer. Cases must follow the OPEN → CLOSED → ARCHIVED lifecycle — direct OPEN → ARCHIVED transitions are now rejected with a descriptive error. Previously, any valid status string was accepted regardless of the current state. - Encryption strict mode audit warning (SEC-009):
ENCRYPTION_STRICT_MODE=Falsenow emits a startup warning to thedfire.securitylogger. This makes the non-strict configuration visible in production logs and prevents accidental deployment with silenced decryption failures. - Signal handler race condition (SEC-010): Replaced module-level
_case_previous_statedictionary with instance-level_previous_statusattribute for case pre-save state tracking. The shared dictionary was not thread-safe and could mix up concurrent case updates under load. - API token masking (SEC-011): Jira API token in the config GET response no longer leaks the first 8 characters. Now shows
****...{last 4}instead of{first 8}...{last 4}. - Photo upload write protection:
photo_uploadendpoint now usescase.is_write_protectedinstead of hardcoded status string comparison, ensuring consistency with the centralized write protection logic.
Changed
- Action labels: "Assign" and "Jira" action links renamed to "Assign to team member" and "Create Jira item" for clarity.
- Jira badge sizing: Jira issue badge in the case header now matches the height and padding of the status and severity badges.
- Dashboard WebSocket handler:
handleCaseUpdatednow handles both full case data (from case-specific channel) and minimalcase_idpayloads (from dashboard channel), refetching via REST API for the latter.
Fixed
- Jira issue type not respected in link metadata:
export_todo_as_task(),export_item_as_task(), andexport_case_as_epic()hardcodedjira_issue_type='Task'/'Epic'in theJiraIssueLinkrecord regardless of the configured issue type. Now reads the actual type name fromdiscovered_issue_typesvia newresolve_action_issue_type_name()andresolve_case_issue_type_name()helpers infield_mapping.py. Discovery filter insync.pyalso refactored to use the shared helper. - Slack action unassignment Jira sync:
/dfire action unassignnow calls_sync_todo_to_jira()after resetting the action status, correctly transitioning the linked Jira ticket from "In Progress" back to "To Do". Previously, unassigning an action via Slack reset the DFIRe status to pending but left the Jira ticket stuck in "In Progress".
1.0.8 — February 15, 2026
Added
- Slack: New
/dfire action add [description]command to create workflow actions from Slack with modal form for description and phase selection. - Slack: Workflow action support in
/dfire action take <n>— workflow actions now open a multi-step decision tree modal instead of simple assignment. - Slack: Actions with workflow definitions are now tagged with
[workflow]in action listings (/dfire actions). - Slack: Auto-invite for cases created via
/dfire create— creator and users with global permissions (edit_all_cases,view_all_cases) are now automatically invited to the case channel and added to the case team with appropriate roles. - Slack: Bidirectional archive sync — archiving a case in DFIRe now archives the linked Slack channel, and archiving a Slack channel archives the linked case. Unarchiving (changing status from ARCHIVED to OPEN or CLOSED) unarchives the Slack channel.
- Slack: Bidirectional team membership sync — joining a case Slack channel adds you to the case team (as investigator if you have
change_casepermission, otherwise as viewer), and leaving the channel removes you from the team. Adding/removing team members in DFIRe invites/kicks them from the Slack channel. - Slack: Lead investigator protection — lead investigators cannot leave the case channel. If they try to leave, they are automatically re-invited with an explanation message. To leave, they must first assign a new lead using
/dfire case. - Slack: Note modal now includes "Save to" dropdown allowing notes to be saved to specific evidence items instead of just the case. Dropdown only appears when evidence items exist.
- Slack: New
/dfire archivecommand to archive cases directly from Slack with confirmation modal. Archives both the case and the linked Slack channel. - Slack: Case creation modal (
/dfire create) now includes Severity dropdown (defaults to Medium) and optional External Reference field for ticket IDs. - Slack: Channel intro message and
/dfire statusnow display Severity (with color-coded emoji) and External Reference when set. - Slack: New
/dfire casecommand to edit case information including title, description, severity, external reference, lead investigator, and dynamic case type attributes. - Slack: New
/dfire evidence update <n>command to edit evidence items via modal form — supports name, location, investigation stage, tags, and dynamic item type attributes. - Slack: Evidence listings (
/dfire evidence) now show sequential numbers for easier reference with update command. - Slack: New
/dfire action assign <n> @usersyntax to assign actions directly to tagged Slack users without opening a modal. Also supports/dfire action assign <n> meto assign to yourself. - Testing: Added 20 new unit tests for Slack features: member left channel handling, lead investigator protection, action assign command with @mentions, signal handlers for team sync, and connector remove_user method.
Changed
- Settings: Default command channel name changed from
dfire-commandstodfire. - Slack:
/dfire helpnow shows mode-appropriate commands — investigation channels show a limited subset (evidence, notes, case management) while incident channels show the full command list. - Slack: Incident-only commands (actions, phases, timers, events) are now blocked in investigation mode with a message suggesting
/dfire escalate. - Slack:
/dfire action take <n>now allows reassigning actions that are already in progress — no need to unassign first. Shows "reassigned from X" in the response. - Slack: Workflow actions can no longer be assigned via
/dfire action assign— they must be taken via/dfire action taketo trigger the workflow modal. - Slack: Help text now shows
/dfire status [update]to clarify the optional update parameter for CAN reports. - Slack: Case update notifications now show detailed field changes (e.g., "Severity: High", "Lead Investigator: John Smith") instead of just "Case updated".
- Slack: When lead investigator is changed, the previous lead is automatically added to investigators to preserve their edit access.
- Slack: Viewers cannot be assigned actions — attempting to assign to a viewer now shows a clear error message instead of silently failing.
Fixed
- Settings: "Clear Settings" button in Collaboration Settings now actually saves the cleared configuration to the backend, properly disabling the Slack integration and disconnecting Socket Mode.
- Slack: Prevented direct completion of workflow actions via
/dfire action done <n>— users must use/dfire action take <n>to navigate the workflow decision tree. - Slack: Fixed workflow definitions not being copied when creating cases via
/dfire createor escalating investigations — workflows were incorrectly shown as regular actions. - Slack: Fixed
AttributeError: module 'django.utils.timezone' has no attribute 'utc'when starting compliance timers via Slack modal. - Slack: Fixed multi-stage workflow modals failing silently due to metadata exceeding Slack's 3000 character limit — workflow definition is now retrieved from the case instead of stored in modal metadata.
- Slack: Fixed deep workflow decision trees (3+ levels) failing due to Slack's 3-view modal stack limit — workflow modals now use
updateinstead ofpushto stay within limits. - Slack: Fixed malformed Slack user mentions (e.g.,
<@>) causing errors in action assignment — now shows helpful error message. - Slack: Fixed
_find_team_membernot finding viewers for action assignment — now correctly validates that only investigators can be assigned actions.
1.0.7 — February 12, 2026
Added
- Slack: Enhanced "Case Closed" notifications now include detailed status reports, incident statistics, and the final CAN report.
- Slack: Automatic channel invitation for active users with global access (
edit_all_casesorview_all_cases) when a new case is created. - UX: Added "Access Denied" page with automatic redirect to dashboard for 403/404 errors in Case view to prevent infinite error loops.
- UX: Added warning and automatic redirect in "Edit Case" modal when archiving a case without
view_archived_casespermission.
Changed
- Slack: Made "Case Type" mandatory in
/dfire createmodal. - Slack: Made "Storage Location" mandatory in
/dfire evidence addmodal. - Performance: Implemented TTL caching (5 minutes) for collaboration connectors to reduce database/initialization overhead.
- Backend: Added startup identity check for Slack bot to verify authentication status early.
- Settings: Removed "Auto-create channels" toggle from Collaboration Settings UI (redundant with per-case checkbox).
Fixed
- Slack: Fixed race condition where "Case Closed" notifications were skipped because the collaboration channel was deactivated before the message could be sent.
- Slack: Fixed issue where channel creation failed for Slack-initiated cases due to stale connector tokens.
- Slack: Fixed auto-invite for global users by reordering query filters (moved
is_active=Truebefore permission checks to prevent Django ORM SQL generation issues).
Removed
- Settings: Removed redundant "Auto-create channels" global setting from backend and frontend. Channel creation is now controlled by the "Create Slack channel" checkbox when creating cases via web UI, and is always enabled for Slack-initiated cases (
/dfire create).
1.0.6 — February 10, 2026
Added
- Slack Socket Mode: Complete migration from HTTP webhooks to Socket Mode for Slack integration
- Slack message edit/delete sync: Edits and deletions in Slack are now reflected in DFIRe
- Edited messages show "(edited)" label in the workspace tab
- Deleted messages show "[This message was deleted]" placeholder
- Real-time WebSocket notifications for both edit and delete events
- Slack user info caching: User lookups cached in Redis for 5 minutes, reducing redundant Slack API calls
- Auto-add investigators toggle: New setting to control whether users are automatically added as investigators when they join a case Slack channel (defaults to enabled for backward compatibility)
- Multi-file message support: Messages with multiple files now show "+N more files" indicator instead of silently dropping extra files;
file_countfield tracks total files per message - Compose experience improvements:
- Insert Link modal replaces browser
prompt()dialogs with a proper modal (URL + optional display text) - Emoji picker with search/filter using the existing Slack emoji map
- @mention autocomplete dropdown for team members with linked Slack accounts (filters by name/username, inserts
<@SLACK_USER_ID>format)
- Insert Link modal replaces browser
- Collaboration test coverage: 24 tests covering notifier logic, message edit/delete handlers, API permissions, user caching, and auto-add investigator config
- Block Kit formatting for all
/dfirecommands: All slash command responses now use Slack Block Kit with headers, sections, field layouts, dividers, and context blocks — with plain-text fallback for accessibility/dfire statusshows case details, team, progress, CAN report, and compliance timers in structured fields/dfire show actionsrenders per-phase action lists with progress percentages and status emojis/dfire evidenceshows full evidence detail: type, short UUID, status, location, owner, primary user, flags, and key attributes/dfire recentshows full event content (description, subject, details) with timestamps, actors, and phase context- All action commands (
take,done,skip,assign,unassign) show progress counters
- External select options handler: Added
@app.optionshandler for Slack Bolt to serve dynamic dropdown options in modals (evidence types, legal entities, case types, projects) with search filtering - Compose write-through: Messages sent from the DFIRe Compose box now immediately create a
CollaborationMessagerecord and broadcast via WebSocket, fixing the bug where compose messages appeared in Slack but not in the DFIRe UI - Compliance timer timeline events: Timer lifecycle now creates timeline events:
TIMER_STARTEDwhen a timer is started (via web UI, Slack command, or Slack modal)TIMER_COMPLETEDwhen a timer is completed (shows breach status)TIMER_WARNINGat 50%, 25%, and 10% threshold crossings (created by scheduler)TIMER_BREACHEDwhen compliance deadline is exceeded- All timer events are broadcast to linked Slack channels with Block Kit formatting
- Block Kit formatting for all timeline notifications: All event notifications posted to Slack channels now use Block Kit with headers, section fields, context blocks, and links — replacing the previous plain-text format
- Covers: case lifecycle, phase changes, lead investigator changes, evidence, actions/workflows, notes, attachments, and all timer events
- Lead investigator changes (
LEAD_INVESTIGATOR_CHANGED) now broadcast to Slack (previously silent) - Timer breaches (
TIMER_BREACHED) are always broadcast (critical event)
- Slack timer modal date/time picker: Timer start modal now includes optional date and time pickers for backdating timer start (matching web UI capabilities)
- Slack message attribution: Messages sent from DFIRe Compose box include an italic attribution suffix in Slack (— Name via DFIRe) for auditability
Refactored
- WorkspaceTab component split: Decomposed 1,080-line monolithic component into 7 focused files:
MessageBubble.tsx— Memo'd message rendering with recursive thread supportChannelHeader.tsx— Channel header bar with sync controlsWorkspaceToolbar.tsx— Compose/search toggle panelWorkspaceEmptyStates.tsx— No-connector and no-channel empty statestypes.ts— Shared TypeScript interfacesworkspaceUtils.ts— Pure utility functionsWorkspaceTab.tsxreduced to ~400 lines (state + data fetching + composition)
Fixed
- Slack connection status: Status indicator now works correctly across Docker containers using Redis heartbeat (was stuck on "disconnected" because in-memory state couldn't cross container boundaries)
- Status view bug:
CollaborationStatusViewwas passing the full status dict instead of theconnectedboolean to the serializer - Compose messages not appearing in UI: Messages sent from the Compose box posted to Slack as the bot but were then filtered out by the
bot_messagesubtype skip — fixed with write-through record creation on send - Bot message display: Bot-originated messages now display as bot messages with bot name and icon, not as user messages
- Bot message grouping: Consecutive bot messages are now grouped correctly in the message list
- Thread reply refresh: Thread replies sent from the Compose box now trigger an incremental fetch so they appear immediately
- Command visibility:
/dfirecommand responses now correctly use ephemeral (private) or in-channel posting depending on command type - Socket Mode view handler: Fixed regex pattern matching for Slack view submission/closed handlers
- Evidence add notification format: Changed from
"{type} added: {name} by {user}"to"Evidence added: {type} — {name}"with actor on a new line for clarity - CAN report layout in
/dfire status: Changed Conditions/Actions/Needs from two-column field layout to full-width single-column sections for better readability of long text - Add Evidence modal: Fixed
block_suggestionunhandled request error when opening evidence type dropdown — added missing@app.optionshandler forexternal_selectelements - Encryption test: Retargeted signing secret encryption test to app token field (signing secret removed in Socket Mode migration)
Changed
- Slack integration now requires App-Level Token (
xapp-...) instead of Signing Secret- Generate in Slack app settings: Basic Information → App-Level Tokens → Generate (with
connections:writescope)
- Generate in Slack app settings: Basic Information → App-Level Tokens → Generate (with
- Updated Slack app manifest template for Socket Mode (removed webhook URLs, enabled
socket_mode_enabled) - Frontend Collaboration Settings updated with Socket Mode setup instructions
- Bot user now shows as "always online" in Slack
BlockBuilderextended withadd_section_fields()for side-by-side key-value field layouts in Block Kit messages- Evidence add timeline notification format improved: now shows
"Evidence added: {type} — {name}"instead of"{type} added: {name}"
Removed
- HTTP webhook endpoints deprecated (return helpful error messages for misconfiguration diagnosis)
- Signing secret no longer required (Socket Mode connections are pre-authenticated)
- Webhook URL configuration removed from setup instructions
Migration Notes
- Existing Slack apps must be reconfigured:
- Enable Socket Mode in Slack app settings (Settings → Socket Mode → Enable)
- Generate an App-Level Token (Basic Information → App-Level Tokens → Generate with
connections:write) - Update DFIRe Collaboration Settings with the new App-Level Token
- Ensure the
slack-socketservice is running in your Docker deployment
- Existing bot tokens (
xoxb-...) remain valid and do not need to be regenerated
1.0.5 — February 5, 2026
Added
- Comprehensive case type taxonomy overhaul with 15 incident response case types:
- Consolidated from 16 to 15 types (merged General Forensic Investigation + General Incident Response)
- Renamed case types for clarity (e.g., "DDoS Attack" → "Distributed Denial of Service Attack")
- Added consistent schema fields across all types:
sharing_permissions(renamed fromtlp),affected_department,nis2_essential_service_impact - Added 4-8 case-specific schema fields per type
- Expanded todo templates to 20-40 actions following NIST SP 800-61 phases
- Fixed workflow anti-patterns (max 3-4 options, investigation actions before decision workflows)
- Added EU regulatory workflows (GDPR 72h notification, NIS2 24h early warning)
- Consumer-focused perspective (responding to vulnerabilities in software we use)
- Visual workflow editor for case type todo templates in System Settings:
- Recursive editor supporting nested follow-up questions at any depth
- Three outcome types: spawn new action, mark as completed, or follow-up question
- Expandable workflow preview in todo template list showing full decision tree hierarchy
- Graphical confirmation modal for destructive actions (removing workflows)
- Timeline 3-tier visual hierarchy system for clearer event presentation:
- Tier 1 (Milestone): Phase changes, case lifecycle events — highest prominence with colored borders and large timeline dots
- Tier 2 (Activity): Manual entries, action start/complete — medium prominence with subtle borders and smaller dots
- Tier 3 (System): Evidence, attachments, notes — lowest prominence, inline display without timeline dots
- Expandable/collapsible content for notes and workflow decisions:
- Notes >200 characters show collapsed with "Show more" button
- Workflow completion events show decision tree with expand/collapse for long content
- Clickable resources in timeline events:
- Evidence items link directly to item detail pages
- Case attachments link to attachments tab via hash navigation
- Item attachments link to parent item page
- Workflow decision tree formatting using nested markdown lists for clear hierarchy
Changed
- Widened Edit Case Type modal (max-w-5xl) for better workflow editing experience
- Workflow editor uses multi-line textareas for answer options, spawn actions, and follow-up questions
- New workflow actions no longer auto-open the editor, allowing users to set the question first
- Timeline hover actions now more visible with colored buttons (blue "View", slate "Edit") instead of subtle icons
- Workflow completion events now show formatted decision path with arrows and nested indentation
- Attachment events no longer show redundant filename in both title and description
Fixed
- Compliance timer linebreaks now render correctly in manual timeline events (added
whitespace-pre-wrap) - Workflow decision tree no longer duplicates conclusion in multi-level workflows
- Printable report timeline now renders workflow decision trees with proper markdown formatting
- Printable report timeline now preserves linebreaks in event descriptions (
whitespace-pre-wrap) - Added visual emphasis styling to CASE_CREATED and MANUAL events in printable report timeline
1.0.4 — February 1, 2026
Security
- Fixed information disclosure via browsable API form dropdowns — case titles were visible to unauthorized users in HTML form select elements when using the DRF browsable API
- Added RBAC enforcement to audit log endpoints (
AuditLogViewSetnow requiresdfireRolePermission) - Added database constraint (
attachment_must_have_parent) preventing orphan attachments — attachments must have a case OR item association for RBAC checks to function correctly
Added
- New
core/common/fields.pymodule with reusable RBAC-aware serializer fields:UserFilteredCasePKField— filters case dropdowns by user permissionsUserFilteredItemPKField— filters item dropdowns by user's case permissions
Changed
- Refactored serializers to use custom RBAC-aware
PrimaryKeyRelatedFieldsubclasses instead of__init__queryset filtering (which doesn't work for DRF form rendering):ItemSerializer.casenow usesUserFilteredCasePKFieldItemNoteSerializer.itemnow usesUserFilteredItemPKFieldCaseNoteSerializer.casenow usesUserFilteredCasePKFieldCaseTimerSerializer.casenow usesUserFilteredCasePKField
Fixed
- Improved disabled user account handling in team management:
- Disabled accounts hidden from team assignment dropdowns (prevents new assignments)
- Admins still see all users (including disabled) in User Accounts management
- Disabled users already assigned to cases are shown in team modal with visual indicator
- Existing disabled team members can be removed but cannot be assigned new roles
- Lead investigators remain assigned even when disabled (prevents case exposure)
- Backend validation prevents NEW assignments of disabled users while allowing existing members
1.0.3 — January 31, 2026
Added
- Case retention policy: configurable auto-archive and auto-delete for closed/archived cases
- New "Retention" tab in System Settings (superuser only) for policy configuration
- Daily scheduled task to process retention policy at midnight
archived_attimestamp on Case model to track when cases are archivedAUTO_ARCHIVEandAUTO_DELETEaudit log action types for retention actions- Retention settings included in settings export/import and defaults.json
- Dashboard statistics summary bar showing open/closed/archived counts, case mode split, severity breakdown (donut chart), and MTTR
- Dashboard API endpoint (
/api/cases/dashboard-stats/) for aggregated case statistics - Retention countdown display on case cards showing days until auto-archive or auto-delete
- Team members count (+N) shown on case cards with tooltip listing all team members
- Severity filter in dashboard filter bar for filtering cases by severity/priority level
Changed
- Refactored case deletion logic into
CaseService.delete_case()for code reuse - Completely redesigned case cards with improved visual hierarchy:
- Clear top bar with severity indicator (color + text label for accessibility), case number, and status
- Horizontal progress bar replacing circular progress indicator
- Organized metrics row with lead investigator, progress, items, attachments, and timers
- Footer with phase info (incidents) and retention countdown
- Left border color-coded by severity for quick visual scanning
- Dashboard filter bar now more compact with flexible layout to accommodate severity filter
Fixed
- Report images now render at correct size (small/medium/large) in printable reports instead of all appearing the same size
- Fixed
case.uuidreference error in retention policy (Case model usesid, notuuid) - Fixed tenant info API endpoint URL in dashboard hook (was
tenant/info/, nowtenant-info/) - Fixed dashboard pagination calculating wrong page count (was using 10 items per page instead of 20)
Tests
- Added 24 unit tests for case retention policy covering:
CaseService.delete_case()cascade deletion of cases, items, and attachmentsarchived_attimestamp handling inCaseService.change_status()process_retention_policy()scheduled task for auto-archive and auto-delete
1.0.2 — January 29, 2026
Added
- CSV export endpoints for case data: timeline, evidence items, notes, and actions
- CSV export buttons in UI (Timeline, Evidence, Notes, Actions tabs) with download icon
started_attimestamp for action items (to-do checklist) — records when work began- Offline license time stacking: remaining days from current license are added when renewing early
- Audit logging for license state changes (activation, offline enable/disable)
- Audit logging for failed login attempts (invalid credentials, SSO-only accounts)
- Audit logging for OIDC/SSO logins
- Audit logging for SSO configuration changes (with sensitive field masking)
- Audit logging for case team changes (investigators/viewers added/removed)
- Audit logging for storage configuration changes (S3, SMB settings)
- Audit logging for settings import/export operations
- Audit logging for profile picture changes (upload, refresh from OIDC, delete)
- Database trigger to protect
registration_datefrom modification (prevents trial manipulation) - CI: TypeScript build check for frontend (catches errors before Docker build)
- CAN report duplicate save prevention — warns user and disables save when content matches previous version
Changed
- Notes CSV export now includes detailed evidence item info: type, name, and UUID prefix
- Unified button sizes across Timeline, Evidence, Notes, Actions, and Compliance tabs
- CAN report editor now prepopulates with both ongoing AND completed actions from checklist
Fixed
- Grace period calculation now uses accurate time comparison instead of truncated days
- Grace period banner message now distinguishes between offline license expiration and online license server issues
- CAN report actions now prepopulate correctly on first report creation (restored useEffect-based prop handling)
- Case notes "Send" button renamed to "Add Note" for consistency with evidence item notes
1.0.1 — January 28, 2026
Added
- Update notification system: displays available updates in License & Updates settings page
- Red dot indicator on License & Updates tab when updates are available
- Link to update documentation in update notification
Changed
- Consolidated VERSION file to
dfire_api/VERSION(removed separate mount point) - Renamed "License" settings tab to "License & Updates"
Fixed
- Fixed TypeScript build error in ItemsOverTimeChart formatter type
- Removed unused
formatBreachTimefunction from ComplianceTab - Skip license server pings when offline license mode is enabled
1.0.0 — January 27, 2026
Added
- Custom start time option for compliance timers — allows backdating timer start
- "Evidence over time" chart in Analytics view
- Maximum file size display in Attachments tabs (Case and Evidence views)
Changed
- Renamed "Workspace" tab to "Collaboration" for clarity
- Changed "Evidence Items" to "Evidence" in Analytics
- Changed "Photos" to "Images" throughout the UI for accuracy
- Increased maximum upload size from 100MB to 4GB in nginx configuration
- Improved dark mode styling in Analytics date range selector (colors and fonts)
- Date fields in case creation now use proper date picker
Fixed
- Removed duplicate case type display from report title page
- Empty team members now shows "No team members assigned" message
- "Add to timeline" checkbox in Notes tab now only appears for Incident mode cases
- Required field validation now enforced for case type schema fields (except booleans)
- Write protection now properly enforced on attachments for closed cases
Removed
- Deleted unused CaseSidebar.tsx component (dead code cleanup)