shellhist-forensic 0.1.0

Forensic anomaly auditor for shell command history — history clearing, timestamp regression, and download-pipe-to-shell as graded report::Finding, built on shellhist-core
Documentation

shellhist-forensic

shellhist-forensic shellhist-core Docs.rs License: Apache-2.0 CI Sponsor

Point it at a shell-history file, get back severity-graded anomalies — history clearing, back-dated entries, download-pipe-to-shell payloads, and encoded PowerShell as forensicnomicon::report::Findings.

[dependencies]
shellhist-forensic = "0.1"   # pulls in shellhist-core
use shellhist_core::parse_auto;
use shellhist_forensic::{audit, source};

let entries = parse_auto(history_bytes, Some(".bash_history"));

for anomaly in audit(&entries) {
    let finding = anomaly.to_finding(source("host"));
    println!("[{:?}] {}{}", finding.severity, finding.code, finding.note);
    // e.g. [Some(Medium)] SHELLHIST-REMOTE-EXEC-PIPE — the command "curl … | sh" downloads and pipes …
}

audit grades an entry stream; audit_findings(&entries, scope) does the parse-to-Finding conversion in one call. Malformed history degrades to plain lines upstream in shellhist-core, never a panic.

The anomaly codes

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

Code Severity Category What it observes
SHELLHIST-HISTORY-DISABLED Medium Concealment A surviving command that disables or clears history (unset HISTFILE, history -c, …) — consistent with anti-forensic history tampering (MITRE T1070.003)
SHELLHIST-TIMESTAMP-REGRESSION Medium Integrity An entry whose epoch precedes its predecessor's — history went backwards in time, consistent with injected or back-dated entries
SHELLHIST-REMOTE-EXEC-PIPE Medium Threat A download piped straight into a shell (curl … | sh) — consistent with remote payload execution (MITRE T1059 / T1105)
SHELLHIST-PWSH-ENCODED-CMD Medium Threat An encoded or policy-bypassing PowerShell invocation — consistent with obfuscated execution (MITRE T1059.001 / T1027)

audit(&entries) returns the typed [HistAnomaly] stream; each anomaly emits a graded report::Finding via to_finding(source). source(scope) stamps the analyzer provenance.

The two-crate split

This crate is the analyzer; the reader is shellhist-core (bash, zsh EXTENDED_HISTORY, fish, and PowerShell PSReadLine into one uniform HistoryEntry stream, with parse_auto / detect and per-format parse entry points). The split mirrors ntfs-core/ntfs-forensic. Together they feed issen for cross-artifact correlation.

Trust, but verify

Built for untrusted history files from potentially compromised systems: #![forbid(unsafe_code)]; panic-free on crafted input (the workspace denies clippy::unwrap_used / expect_used in production code, parsing is lenient and bounds-checked); fuzzed with five cargo-fuzz targets (one per format plus the full parse→audit pipeline) and exercised end-to-end against a history file generated by a real bash subshell, with its planted traces re-surfaced.


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