useract-forensic 0.1.0

User-activity correlation layer — merges shell-history and peripheral-device events into one per-user timeline and emits cross-source forensic findings. Single meta crate, no unsafe, panic-free.
Documentation

useract-forensic

useract-forensic Docs.rs Rust 1.81+ License: Apache-2.0 Sponsor

CI unsafe forbidden Security advisories

One per-user timeline from many artifacts — useract-forensic merges shell history, device connections, and (soon) LNK / shellbags / SRUM / registry MRU into a single UserActivity stream and surfaces the cross-source signals no one artifact can show: a command run while a USB stick was mounted, history wiped right after a payload ran.

It is the correlation layer, not another parser. It consumes the forensic fleet's already-built reader crates and normalizes their output into one uniform event — so "who did what, when, to which file / program / folder / device" reads off a single sorted list, with graded findings attached.

30 seconds: merge two sources, get cross-source findings

use useract_forensic::{build_timeline, audit, ShellHistorySource, DeviceSource};

// Decode each source with its own published reader crate …
let entries = shellhist_core::parse_auto(history_bytes, Some(".bash_history"));
let devices = peripheral_core::setupapi::parse(setupapi_bytes);

// … then correlate them here.
let shell = ShellHistorySource::new(&entries);
let usb   = DeviceSource::new(&devices);

let timeline = build_timeline(&[&shell, &usb]);   // merged, sorted by epoch
for finding in audit(&timeline) {
    println!("[{:?}] {}{}", finding.severity, finding.code, finding.note);
    // [Some(Low)]    USERACT-EXEC-DURING-REMOVABLE-MEDIA — the command "tar … /media/usb" ran within …
    // [Some(Medium)] USERACT-HISTORY-TAMPERED            — user activity "unset HISTFILE" disables …
}

What it normalizes into

Every source collapses into one event type:

pub struct UserActivity {
    pub timestamp: Option<i64>,   // Unix epoch, when the source records it
    pub actor:     Option<String>,// user / SID, when the source attributes it
    pub action:    Action,        // Executed | Accessed | Connected | Searched | Typed | HistoryTampered
    pub subject:   Subject,       // Command | File | Folder | Device{id, volume_serial} | Query
    pub source:    SourceKind,    // which reader produced it
    pub detail:    String,
}

A new source is one impl ActivitySource { fn activities(&self) -> Vec<UserActivity> } away — it slots straight into build_timeline with no API change.

v0.1 sources, and the v0.2 roadmap

Source Crate Action Status
Shell command history (bash/zsh/fish/PowerShell) shellhist-core Executed / HistoryTampered ✅ v0.1
External device connections (setupapi.dev.log) peripheral-core Connected (+ volume serial) ✅ v0.1
Recent-file LNK (and the volume serial that completes the device join) lnk-core Accessed (File) v0.2
Shellbags (folder access) shellbag-core Accessed (Folder) v0.2
Per-user app exec + network bytes by SID srum-core Executed / Connected (actor!) v0.2
UserAssist / RecentDocs / MRU / MountPoints2 winreg-artifacts Executed / Accessed v0.2

The v0.2 sources need those reader crates published first. SRUM is the strongest — the first source that attributes activity to a specific SID. See docs/roadmap.md.

The anomaly codes

Each finding is an observation ("consistent with …"); the examiner draws the conclusions. Codes are a stable, published contract.

Code Severity Category What it observes
USERACT-EXEC-DURING-REMOVABLE-MEDIA Low Threat A shell command executed within an hour of a removable mass-storage device being connected (temporal cross-source join) — consistent with activity involving external media (MITRE T1052 / T1091)
USERACT-HISTORY-TAMPERED Medium Concealment A history-clearing activity present in the timeline — consistent with anti-forensic history tampering (MITRE T1070.003)

A volume-serial join seam (device_file_volume_joins) is implemented generically over UserActivity today and tested by construction; it activates with zero code change the moment a v0.2 LNK / shellbag source contributes a file subject carrying a volume serial.

Trust, but verify

useract-forensic consumes attacker-controllable, already-decoded evidence and correlates it:

  • #![forbid(unsafe_code)] — no FFI, no C bindings, no raw pointers.
  • Panic-free — the workspace denies clippy::unwrap_used and clippy::expect_used in production code; correlation degrades gracefully, never crashes.
  • 100% line coverage on the library, clippy -D warnings clean.
  • Validated on real artifacts — the integration test feeds a .bash_history file written by a genuine bash subshell (decoded with the published shellhist_core::parse_auto) plus a real peripheral_core::DeviceConnection, and asserts the timeline merges and both findings fire (tests/real_data.rs).
cargo add useract-forensic
cargo test

Privacy Policy · Terms of Service · © 2026 Security Ronin Ltd