Audit log

An append-only record of what happened in DFIRe, who did it, and what changed. Open it from the user menu, under Audit Log.

What an entry holds

  • Action, such as CREATE, UPDATE or DELETE.
  • Record type, the kind of thing the action touched. Cases, evidence items, attachments, notes, timeline events, users, API keys, indicators, settings, backups and webhook deliveries all appear here.
  • Description, a readable summary of the change.
  • Timestamp, to the second.
  • Username of whoever acted.
  • IP address, either the client DFIRe saw directly or the value your trusted reverse proxy sent in X-Real-IP. DFIRe never uses X-Forwarded-For for audit identity, because a proxy that appends leaves attacker-supplied entries in it. Entries written without a request, such as license checks and heartbeats, have no IP address.
  • Change data, a structured before-and-after for every modified field.

Some system events carry more in their change data. A heartbeat, for example, records database and Redis latency, queue counts, case and evidence totals, active users, storage use, and the running version and uptime. Together they build a history of the installation's health that you can look back through.

A failed audit write blocks the operation. When DFIRe cannot record an action, it refuses the action rather than completing it unrecorded.

Finding entries

Type in Search entries to search usernames, actions, labels and content. To narrow the list further, select Filter and add a filter row. A row compares one field with a value. User, Record and IP address compare text. Action and Record type take a value from a list, and Time takes a day and an optional time of day. Record type lists the record types you can see in the log.

Rows join with AND, OR or NOT, read from left to right. A NOT row leaves matching entries out: NOT Action equals LICENSE_PING hides the license checks.

Time rows use your display time zone. Without a time of day, a Time row takes the whole day, so Time is after 30 Sep keeps the entries from 1 October on. Add a time of day (24-hour, HH:MM) to narrow the list to the minute. Time is after 30 Sep 14:05 keeps the entries from 14:06. Time is before 30 Sep 14:05 keeps the entries before 14:05. To keep the entries of 14:05 too, use is after 14:04.

Each row shows as a chip under the toolbar. Select a chip to change its row, select its remove control to remove it, or select Clear filters to remove every row. To move a row, drag its chip by the grip at its start. DFIRe reads the rows from left to right, so their order can change the result. The search and the rows are part of the page address, so a reload or a shared link opens the same list. If the list does not load, the page says so instead of showing an empty list.

The audit log shows entries as cards or as a table. Switch between them with Cards and Table above the list, and the browser remembers the choice. The count above the list states how many entries are loaded and how many match the filters, for example 20 of 10,970 entries. Scroll down to load more entries.

The table shows Time, User, Action, Record type, Record and IP address. Columns chooses the columns. Changes, a one-line list of the changed fields, is off by default. Select the Time, User, Action or Record type heading to sort by that column, and select it again to reverse the order. The table opens newest first, and the cards always show the newest entries first.

Select a row, or the arrow at its start, to open the entry's changes under it. The changes have the same Visual and JSON views as on a card.

Who sees what

Reading the log at all requires the View auditlog permission, granted per role under Settings → Access Roles. Without it a role reaches no audit entries anywhere, including the history shown on an evidence item.

With it, entries are filtered down to what that person could already see.

  • Case records. Entries about a case, its evidence, notes, attachments, timeline, compliance timers, custody transfers, indicators and reports appear only for cases the person can reach. A role with global read sees every case's entries.
  • Shared records. Entries about projects, legal entities, runbooks, indicators, playbooks and other shared configuration appear only if the role can read that kind of record. A role that cannot open the Legal Entities directory does not see legal entity history either.
  • Their own account. Everyone sees their own sign-ins and account changes.

Other people's account activity, API key use, role changes and system configuration history reach superusers and any role that holds global case read (core.view_all_cases), which opens the log in full. The shipped Team Lead role holds it, so a Team Lead reads every entry in the installation.

A filtered entry is hidden, not missing.

Append-only storage and retention

DFIRe never edits or deletes an audit record after it is written. No screen, endpoint or administrator function removes one, and the application raises an error on any attempt to modify or delete an entry.

What that protection covers. The application enforces it, so it holds against everything reachable through DFIRe. It cannot hold against someone with direct access to the database or its backups, because they are past the application entirely.

On a system you host yourself that limit is structural rather than a gap to close with database locks, because whoever runs the installation can change how it works. The way to detect tampering is to keep a copy somewhere they do not control. Forward entries to a separate system as they are written, then compare the two.

DFIRe also never purges old entries. The log grows for the life of the installation. If you need entries archived off the DFIRe database, whether for retention rules, storage cost or an off-site copy, forward them.

Forwarding to an external system

DFIRe can send audit entries to a log aggregator or SIEM as they are written. Configure it under Settings → Log Integration.

This is also how you make the trail hold up to scrutiny. Keep a copy on a system the DFIRe administrator does not control, then compare the two. A discrepancy shows even when the local record looks consistent.

PropertyDetail
TransportHTTPS POST to an endpoint you choose. DFIRe rejects a plain HTTP URL.
Payload formatJSON Batch for a generic receiver, NDJSON for Logstash or Fluentd, Elasticsearch Bulk for OpenSearch and ELK, or New Relic.
AuthenticationHTTP Basic, or custom headers such as a bearer token. DFIRe encrypts the credentials and headers at rest.
DeliveryCursor-based, so each entry goes exactly once and in order.
BackfillOn first enabling it, choose whether to send the whole history or start from now.
ReliabilityBatch size, timeout and retry count are configurable. A circuit breaker opens after a set number of consecutive failures, so a broken endpoint does not get hammered.
Delivery logRecent attempts stay visible with their timing, response code and any error.

The audit log carries enough detail to satisfy activity-logging and traceability obligations under frameworks such as GDPR and PCI DSS. Forwarding is how you keep that record beyond the DFIRe database.