Skip to main content

Live triage package

What this page is

The forensic snapshot the sensor takes on operator command. A single JSON document collected from /proc, /sys, and the filesystem in four phases, streamed back over the existing Collector channel.

Why it exists this way

Architecture Section 7.3 names live triage as the second response action after host isolation. The package answers the "what's running, what's it talking to, how is it pinned, and what changed recently" question without forcing an analyst to ssh in.

The package is read-only: triage::collect_triage_package never deletes, modifies, or kills anything on the host. The collected JSON is the only side effect, and it is uploaded through the Collector path, not written to a place where an attacker could read it.

How it works

The implementation lives in edr_linux::triage and runs four phases:

PhaseSourceOutput type
Process tree/proc/[pid]/{stat,cmdline,status,exe,cwd}Vec<ProcessNode>
Network connections/proc/net/{tcp,tcp6,udp,udp6} + per-pid socket inodesVec<NetworkConnection>
Persistence locationscron, systemd, autostart, rc.local, profile.d, init.d, per-user shell rc filesVec<PersistenceItem>
Recent file modificationsfind over forensic-relevant directories (fallback: manual recursive scan)Vec<FileModification>

Each phase is bounded by the constants at the top of the module (MAX_PROCESS_ENTRIES, MAX_CONNECTION_ENTRIES, etc.) so a host with millions of files cannot exhaust sensor memory.

Each phase fails independently. A failure in connection enumeration does not stop process-tree collection; partial results carry per-phase Option<TriageError> fields in the TriagePackage envelope so the analyst sees what worked and what did not.

Network connection rows are cross-referenced with each process's socket inodes under /proc/[pid]/fd, so the process_pid and process_comm fields are populated when the kernel exposes the mapping.

What goes wrong

  • TriageError::ProcessTree, /proc is missing or permission-denied. The phase returns an error but the rest of the package proceeds.
  • find not on the host, the recent-files phase falls back to a manual recursive scan. The scan respects the same depth cap so the fallback's worst case matches the primary path.
  • The package exceeds the gRPC message size limit, split is not yet implemented. The single-package size is bounded by the four phase caps so the worst-case payload (4096 process nodes + 2048 connections + 512 persistence items + 1024 recent files) sits comfortably under the default 4 MiB gRPC frame.